Convert String list to sorted Map String length as

2019-03-31 19:53发布

问题:

I have a List<String> and I have to convert it to Map, by grouping same length Strings into a List, using String length as the key in, sorted order. It can be done using -

Map<Integer, List<String>> result = new TreeMap<>();
for (String str : list) {
    if (!result.containsKey(str.length())) {
        result.put(str.length(), new ArrayList<>());
    }
    result.get(str.length()).add(str);
}

How can we do it using Java 8 streams?

回答1:

You could do it with streams:

Map<Integer, List<String>> result = list.stream()
    .collect(Collectors.groupingBy(
        String::length,        // use length of string as key
        TreeMap::new,          // create a TreeMap
        Collectors.toList())); // the values is a list of strings

This collects the stream by means of the overload of Collectors.groupingBy that accepts 3 arguments: the key mapper function, the supplier of the map and the downstream collector.

However, there's a more compact way to do it, without streams:

Map<Integer, List<String>> result = new TreeMap<>();
list.forEach(s -> result.computeIfAbsent(s.length(), k -> new ArrayList<>()).add(s));

This uses List.forEach and Map.computeIfAbsent to achieve what you want.



回答2:

Java streams can be grouped into a map by using the grouping collectors, the easiest way to make one is to use

Collectors.groupBy(comparator)

where comparator converts streamed values into map keys.

The return is a Map from comparator key to list of entries

public class Test {
  public static void main(final String... args) {
    List<String> in = Arrays.asList("A", "AB", "B", "ABC");
    final Map<Integer, List<String>> all = in.stream()
        .collect(Collectors.groupingBy(String::length));
    System.out.println(all);
  }
}

Output:

{1=[A, B], 2=[AB], 3=[ABC]}



回答3:

You can do this in Java 8 with groupingBy on one line.

result = list.stream().collect(Collectors.groupingBy(String::length));