给定一个字符串列表,是否可以在一行中得到从每个长度到具有该长度的字符串集的映射,并按长度排序?

Given a list of strings, is it feasible to get in one line a map from each length to the set of strings having that length, sorted by length?

我想出了以下方法,它确实有效,但我觉得应该有一种不依赖于“外部”地图的更简洁的单行方式(下面的result):

public TreeMap<Integer, HashSet<String>> mapLenToString(List<String> strings){
    TreeMap<Integer, HashSet<String>> result = new TreeMap<>();
    strings.stream()
           .forEach(s -> { 
                int len = s.length();
                if (result.containsKey(len)) {
                    HashSet<String> larger = result.get(len);
                    larger.add(s);
                    result.replace(len, larger);
                }
                else {
                    HashSet<String> newSet = new HashSet<>();
                    newSet.add(s);
                    result.put(len, newSet);
                }
                
            });
    return result;
}

只需使用 groupingBy 收集器。您可以控制地图类型和元素收集到的集合类型。

TreeMap<Integer, HashSet<String>> result = strs
  .stream()
  .collect(
    Collectors.groupingBy(
      s -> s.length(),
      TreeMap::new,
      Collectors.toCollection(HashSet::new)
    )
  );

使用这个

List<String> strs = Arrays.asList(
  "DEF", "ABC", "Hello world", "z", 
  "a", "q", "90", "12345678910", "ab");

输出是

{1=[a, q, z], 2=[90, ab], 3=[ABC, DEF], 11=[12345678910, Hello world]}

Link to repl.it


您也可以使用 Collectors.toSet() 而不是 toCollection(HashSet::new),其中默认实现是 HashSet(但可能不保证如此)

使用 Guava Multimaps 的替代方法: com.google.common.collect.Multimaps.index(iterable, function)-

Multimap<Integer, String> index =
       Multimaps.index(strs,  s -> s.length());

不幸的是,它没有按结果排序。