收集HashMap<String, List<String>> Java 8

50
我想要将一个列表 List 转换为一个 HashMap,其中键是元素名称 elementName,值是一些随机的东西列表(在这种情况下,它是元素名称)。所以简而言之,我想要 (A->List(A), B->List(B), C-> List(C))。我尝试使用 toMap() 并传递 keyMapperValueMapper,但我得到了一个编译错误。如果有人能帮助我,我将不胜感激。 谢谢!
public static void main(String[] args) {
    // TODO Auto-generated method stub
    List<String> list = Arrays.asList("A","B","C","D");
    Map<String, List<String>> map = list.stream().map((element)->{
        Map<String, List<String>> map = new HashMap<>();
        map.put(element, Arrays.asList(element));
        return map;
    }).collect(??);
}


Function<Map<String, String>, String> key = (map) -> {
    return map.keySet().stream().findFirst().get();
};

Function<Map<String, String>, String> value = (map) -> {
    return map.values().stream().findFirst().get();
};

=== 这种方法对我有用

感谢各位的帮助!@izstas所提到的“它们应该在元素上操作”对我很有帮助。其实这正是我所需要的。

public static void test2 (){
    Function<Entry<String, List<String>>, String> key = (entry) -> {
        return entry.getKey();
    };
    Function<Entry<String, List<String>>, List<String>> value = (entry) -> {
        return new ArrayList<String>(entry.getValue());
    };
    BinaryOperator<List<String>> merge = (old, latest)->{
        old.addAll(latest);
        return old;
    };

    Map<String, List<String>> map1 = new HashMap<>();
    map1.put("A", Arrays.asList("A1", "A2"));
    map1.put("B", Arrays.asList("B1"));
    map1.put("D", Arrays.asList("D1"));

    Map<String, List<String>> map2 = new HashMap<>();
    map2.put("C", Arrays.asList("C1","C2"));
    map2.put("D", Arrays.asList("D2"));

    Stream<Map<String, List<String>>> stream =Stream.of(map1, map2);
    System.out.println(stream.flatMap((map)->{
        return map.entrySet().stream(); 
    }).collect(Collectors.toMap(key, value, merge)));
}

2
编译器错误是什么? - Tripp Kinetics
发布您的源代码,请参阅如何创建一个最小、完整和可验证的示例 - DavidPostill
我不确定,但据我所知,在您的映射部分中,无论您从左侧拥有什么,都必须与右侧匹配,因此我认为您应该返回元素而不是映射 :) - Kick Buttowski
3个回答

100
你可以使用groupingBy方法来进行聚合管理,例如:
public static void main(String[] args) {
    List<String> list = Arrays.asList("A", "B", "C", "D", "A");
    Map<String, List<String>> map = list.stream().collect(Collectors.groupingBy(Function.identity()));
}
如果您想要更灵活地使用(例如将值映射并返回Set而不是List),则可以始终使用在javadoc中指定的更多参数来使用groupingBy方法。
Map<City, Set<String>> namesByCity = people.stream().collect(Collectors.groupingBy(Person::getCity, mapping(Person::getLastName, toSet())));

groupingBy 存在吗? - Pablo Matias Gomez
3
我修复了这个例子,抱歉。groupingBy 方法是 java.util.stream.Collectors 中的一个静态方法。 - Phoenix
2
在地图上很棒的<城市,集合<字符串>>。谢谢! - wild_nothing

26

您在代码中定义的 keyvalue 函数不正确,因为它们应该操作您列表的 元素,而不是您的元素不是 Map

以下代码适用于我:

List<String> list = Arrays.asList("A", "B", "C", "D");
Map<String, List<String>> map = list.stream()
        .collect(Collectors.toMap(Function.identity(), Arrays::asList));

Collectors.toMap 的第一个参数定义了如何从列表元素中创建键(保留不变),第二个参数定义了如何创建一个值(使用单个元素创建 ArrayList)。


1
你有没有考虑用 Function.<String>identity() 替换 (element) -> element? - Jeff
@Jeff 哦,这是个好建议。我会更新我的答案。顺便说一下,似乎在不明确指定类型参数的情况下它也可以工作。 - izstas
好的。是的,类型不需要。这只是复制/粘贴。 - Jeff
我已经更新了问题,并找到了我要寻找的解决方案。谢谢! - user3869813
9
这段代码无法处理多个元素,请尝试使用 List<String> list = Arrays.asList("A", "B", "C", "D", "A"); - Phoenix

9

谢谢大家的帮助!@izstas 的建议“他们应该对元素进行操作”真的帮了我很多。实际上,这正是我要找的。

public static void test2 (){
    Function<Entry<String, List<String>>, String> key = (entry) -> {
        return entry.getKey();
    };
    Function<Entry<String, List<String>>, List<String>> value = (entry) -> {
        return new ArrayList<String>(entry.getValue());
    };
    BinaryOperator<List<String>> merge = (old, latest)->{
        old.addAll(latest);
        return old;
    };

    Map<String, List<String>> map1 = new HashMap<>();
    map1.put("A", Arrays.asList("A1", "A2"));
    map1.put("B", Arrays.asList("B1"));
    map1.put("D", Arrays.asList("D1"));

    Map<String, List<String>> map2 = new HashMap<>();
    map2.put("C", Arrays.asList("C1","C2"));
    map2.put("D", Arrays.asList("D2"));

    Stream<Map<String, List<String>>> stream =Stream.of(map1, map2);
    System.out.println(stream.flatMap((map)->{
        return map.entrySet().stream(); 
    }).collect(Collectors.toMap(key, value, merge)));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,