Home Articles

学习java 8

Asked
Viewed 875 times
1

我有一个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());
 }
}

UPDATE - 我用过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 Answers

  • 3

    这是我使用流可以提出的最佳解决方案:

    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());
        }
    }
    

    注意:

    从简单开始,我们使用实用方法Arrays.stream(array)从数组 strs 创建一个流:

    Arrays.stream(strs);
    

    Stream#collect(collector)方法接受一个流并将其转换为标准集合类型( MapList 等):

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

    在这种情况下,我们将使用Collectors.groupingBy(classifier) . 此收集器将您的流分类为'bins',其中bin标签由通过 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);
            }));
    

    为了流畅,我们用另一个流替换该函数* :(事实证明 char s不能很好地流动)

    为了整洁,我已经将lambda函数重构为类中的静态方法:

    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);
            }));
    

    由于我们只对一个只接受一个参数的函数进行单次调用,因此我们可以使用方法引用而不是lambda函数:

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

    其余的与您现有的代码非常相似 . 使用Map#values()从数据集中剥离键,然后将结果 Collection 包装在_60415中:

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

    This answer provides a 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 <>())计算其值并输入除非为null,否则进入此映射 .

    下次我们尝试添加已经存在于 Map 中的键时,将返回与指定键关联的现有列表,并使用上面的 .add(word) 将该单词添加到其中 .

  • 1

    你基本上是在寻找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) 时创建一个Stream,然后使我们能够使用 collect 执行缩减操作,此方法使用收集器,其中此收集器是 groupingBy .

    groupingBy 收集器的这种重载产生 Map<K, List<T>> ,其中键是将分类函数应用于输入元素(即 Arrays.stream(s.split("")).sorted().collect(joining()) )得到的值,其对应值是包含映射到分类函数下的关联键的输入元素的列表 .

    最后,我们调用 values() 来检索 Collection<List<String>> 并将其传递给 ArrayList 构造函数并返回 .

    读你可能会觉得有趣:

  • 1

    使用Optional和streams以及一些静态导入:

    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

    如果你想使用 Streams 参考其他答案,如果你想知道如何使用 Map 操作来简化你的if / else,它是:

    它是 key 不在 map 中,用 empty list 添加它,然后得到 listadd 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

    来自Aomine的答案很好,但可以重写更短的内容:

    return strs == null? Collection.emptyList() : new ArrayList<>(Arrays.stream(strs)
            .collect(groupingBy(s -> Arrays.stream(s.split(""))
                    .sorted()
                    .collect(joining())))
            .values());
    

Related