使用带 Java 8 的流从列表生成地图

Generate a Map from a list using Streams with Java 8

我有一个 列表 String

我想将每个 string 存储为 key 并将字符串的 length 存储为 value in a Map (say HashMap).

我做不到。

List<String> ls = Arrays.asList("James", "Sam", "Scot", "Elich");
Map<String,Integer> map = new HashMap<>();

Function<String, Map<String, Integer>> fs = new Function<>() {
    @Override
    public Map<String, Integer> apply(String s) {
        map.put(s,s.length());
        return map;
    }
};

Map<String, Integer> nmap = ls
        .stream()
        .map(fs).
        .collect(Collectors.toMap()); //Lost here

System.out.println(nmap);

所有字符串都是唯一的

不需要像您创建的 函数 那样用自己的 map 包装每个字符串。

相反,您需要在调用 Collectors.toMap() 时提供适当的 参数 :

  • keyMapper - 负责从流元素中提取 key 的函数。
  • valueMapper - 从流元素生成 的函数。

因此,你需要流元素本身是一个 key 我们可以使用 Function.identity(),它比 lambda str -> str 更具描述性,但是一模一样

Map<String,Integer> lengthByStr = ls.stream()
            .collect(Collectors.toMap(
                Function.identity(), // extracting a key
                String::length       // extracting a value
            ));

如果源列表可能包含重复项,您需要提供第三个参数 - mergeFunction,它将负责解决重复项。

Map<String,Integer> lengthByStr = ls.stream()
            .collect(Collectors.toMap(
                Function.identity(),   // key
                String::length,        // value
                (left, right) -> left  // resolving duplicates
            ));

你说过不会有重复的字符串。但是,如果有人通过了,您可以使用 distinct()(内部使用 set)来确保它不会引起问题。

  • a-> a是使用流值的shorthand。本质上是一个 returns 其参数的 lambda。
  • distinct() 删除所有重复的字符串
Map<String, Integer> result = names.stream().distinct()
        .collect(Collectors.toMap(a -> a, String::length));

如果你想得到一个String的长度,你可以直接像someString.length()那样做。但是假设您想要获取所有按特定长度键控的字符串的映射。您可以使用 Collectors.groupingBy() 来做到这一点,默认情况下会将重复项放入列表中。在这种情况下,副本将是字符串的长度。

  • 使用字符串的length作为关键字。
  • 该值将是一个 List<String> 来保存匹配该长度的所有字符串。
List<String> names = List.of("James", "Sam", "Scot",
          "Elich", "lucy", "Jennifer","Bob", "Joe", "William");

Map<Integer, List<String>> lengthMap = names.stream()
        .distinct()
        .collect(Collectors.groupingBy(String::length));

lengthMap.entrySet().forEach(System.out::println);

打印

3=[Sam, Bob, Joe]
4=[Scot, lucy]
5=[James, Elich]
7=[William]
8=[Jennifer]