Изучение Ява 8 - PullRequest
       2

Изучение Ява 8

0 голосов
/ 09 декабря 2018

У меня есть существующий код на Java, который я хотел бы написать на Java 8.

Может кто-нибудь предложить предложения по переносу этого кода на Java 8.

class Solution {

public List<List<String>> groupAnagrams(String[] strs) {

    List<List<String>> result = new ArrayList();
    Map<String, List<String>> map = new HashMap();

    if (strs == null || strs.length == 0) return result;

    for (String word: strs) {
        char[] wordArr = word.toCharArray();
        Arrays.sort(wordArr);
        String sortedWord = new String(wordArr);
        if (map.containsKey(sortedWord)) {
            List<String> list = map.get(sortedWord); 
            list.add(word);
            map.put(sortedWord, list);
        } else {
            List<String> list = new ArrayList();
            list.add(word);
            map.put(sortedWord, list);
        }
    }
    return new ArrayList(map.values());
 }
}

ОБНОВЛЕНИЕ - Я использовал getOrDefault ()

class Solution {

    public List<List<String>> groupAnagrams(String[] strs) {

        List<List<String>> result = new ArrayList();

        Map<String, List<String>> map = new HashMap();

        if (strs == null || strs.length == 0) return result;

        for (String word: strs) {
            char[] wordArr = word.toCharArray();
            Arrays.sort(wordArr);
            String sortedWord = new String(wordArr);
            List<String> list = map.getOrDefault(sortedWord, new ArrayList());
            list.add(word);
            map.put(sortedWord, list);
        }
        return new ArrayList(map.values());
    }
}

Любой другой способ?

Ответы [ 6 ]

0 голосов
/ 09 декабря 2018

Этот ответ предоставляет решение java-stream , которое я лично выберу.Что касается вашей текущей реализации, вы довольно близки, но computeIfAbsent будет лучшим подходом для продолжения:

List<List<String>> groupAnagrams(String[] strs) {
        if (strs == null || strs.length == 0) return new ArrayList<>();
        Map<String, List<String>> map = new HashMap<>();

        for (String word : strs) {
            char[] wordArr = word.toCharArray();
            Arrays.sort(wordArr);
            map.computeIfAbsent(new String(wordArr), k -> new ArrayList<>()).add(word);
        }
        return new ArrayList<>(map.values());
}

Я почти уверен, что вы знаете, что делает большая часть кода, поэтому я буду толькообъясните часть computeIfAbsent выше, цитируя большую часть документации, так как это лучшее объяснение.

, если указанный ключ (new String(wordArr)) еще не связан со значением (или сопоставлен со значением NULL), пытается вычислить его значение с использованием заданной функции сопоставления (k -> new ArrayList<>()) и вводитэто в эту карту, если ноль.

в следующий раз, когда мы пытаемся добавить ключ, который уже присутствует на карте, возвращается существующий список, связанный с указанным ключом, и мы добавляем слово в него с помощью.add(word) выше.

0 голосов
/ 09 декабря 2018

Использование необязательных и потоков и некоторых статических импортов:

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static java.util.Collections.emptyList;
import static java.util.Optional.of;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.joining;
import static org.apache.commons.lang3.StringUtils.EMPTY;

    public class Solution {

        public List<List<String>> groupAnagrams(String[] strs) {

            Collection<List<String>> collection = of(asList(strs))
                            .orElse(emptyList())
                            .stream()
                            .collect(groupingBy(word -> stream(word.split(EMPTY))
                                            .sorted()
                                            .collect(joining())))
                            .values();
            return new ArrayList<>(collection);
        }
    }
0 голосов
/ 09 декабря 2018

Ответ от Аомина хороший, но можно переписать короче:

return strs == null? Collection.emptyList() : new ArrayList<>(Arrays.stream(strs)
        .collect(groupingBy(s -> Arrays.stream(s.split(""))
                .sorted()
                .collect(joining())))
        .values());
0 голосов
/ 09 декабря 2018

Если вы хотите использовать Streams, обратитесь к другим ответам, если вы хотите узнать, как вы используете Map операцию, чтобы упростить ваше if / else здесь:

Это keyне в map, добавьте его с empty list, затем получите list и add word:

for (String word : strs) {
    char[] wordArr = word.toCharArray();
    Arrays.sort(wordArr);
    String sortedWord = new String(wordArr);

    map.putIfAbsent(sortedWord, new ArrayList<>());
    map.get(sortedWord).add(word);
}
0 голосов
/ 09 декабря 2018

Вот лучшее решение, которое я мог бы придумать, используя потоки:

public class Solution {
    private static String sortString(String str) {
        char[] chars = str.toCharArray();
        Arrays.sort(chars);
        return new String(chars);
    }

    public List<List<String>> groupAnagrams(String[] strs) {
        if (strs == null) {
            return new ArrayList<>();
        }

        return new ArrayList<>(Arrays.stream(strs)
                .collect(Collectors.groupingBy(Solution::sortString))
                .values());
    }
}

Примечания:

Начиная с простого, мы создаем поток из массива strs с помощью служебного метода Arrays.stream(array):

Arrays.stream(strs);

Метод Stream#collect(collector) принимает поток и преобразует его в стандартный тип коллекции (Map, List и т. Д..):

Arrays.stream(strs)
        .collect(...);

В этом случае мы будем использовать Collectors.groupingBy(classifier).Этот сборщик сортирует ваш поток в «бины», причем метка бина определяется результатом передачи каждого значения через функцию classifier lambda.Тип возвращаемого значения - Map<K, List<V>> (где K - это тип метки, а V - это любой тип, который мы передаем в потоковом режиме) - та же самая форма, которую вы использовали для переменной map:

Arrays.stream(strs)
        .collect(Collectors.groupingBy(...));

Но какую функцию мы передаем .groupingBy()?Поскольку вы хотите группировать по отсортированной строке, нам нужна функция, которая будет создавать отсортированную строку из обычной.Мы собираемся использовать вашу существующую функцию для этого:

Arrays.stream(strs)
        .collect(Collectors.groupingBy(str -> {
                char[] chars = word.toCharArray();
                Arrays.sort(chars);
                return new String(chars);
        }));

В целях обеспечения потоковой передачи мы заменим эту функцию на другой stream *: ( Оказывается, char s не передается нормально )

В интересах аккуратности я реорганизовал лямбда-функцию в статический метод для вашего класса:

private static String sortString(String str) {
    char[] chars = str.toCharArray();
    Arrays.sort(chars);
    return new String(chars);
}
Arrays.stream(strs)
        .collect(Collectors.groupingBy(str -> {
                return Solution.sortString(str);
        }));

Поскольку мы делаем один вызов функции, которая принимает только один параметр, мы можем использовать ссылку на метод вместо лямбда-функции:

Arrays.stream(strs)
        .collect(Collectors.groupingBy(Solution::sortString));

Остальноеочень похоже на ваш существующий код.Используя Map#values(), уберите ключи из набора данных, затем оберните полученный Collection в ArrayList:

new ArrayList<>(Arrays.stream(strs)
        .collect(Collectors.groupingBy(Solution::sortString))
        .values());
0 голосов
/ 09 декабря 2018

По сути, вы ищете коллектор groupingBy:

List<List<String>> groupAnagrams(String[] strs) {       
    if (strs == null || strs.length == 0) 
         return new ArrayList<>();

    return new ArrayList<>(Arrays.stream(strs)
            .collect(groupingBy(s -> Arrays.stream(s.split(""))
                    .sorted()
                    .collect(joining())))
            .values());
}

Сначала мы создаем поток при вызове Arrays.stream(strs), который затем позволяет нам выполнить операцию сокращенияиспользуя collect, этот метод использует Collector, где этот Collector представляет собой groupingBy.

Эта перегрузка коллектора groupingBy создает Map<K, List<T>>, где ключами являются значения, полученные в результате применения функции классификации кэлементы ввода (т. е. Arrays.stream(s.split("")).sorted().collect(joining())) и соответствующие им значения являются списками, содержащими элементы ввода, которые отображаются на связанный ключ в функции классификации.

Наконец, мы вызываем values(), чтобы получить Collection<List<String>>и передайте это конструктору ArrayList и вернитесь.

Чтение, которое может вас заинтересовать:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...