且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

转换列表< MyObject> to Map< String,List< String>>在Java 8中,当我们有重复元素和自定义过滤条件时

更新时间:2022-04-18 07:09:29

使用流,您可以使用 Collectors.groupingBy 以及 Collectors.mapping

With streams, you could use Collectors.groupingBy along with Collectors.mapping:

Map<String, Set<String>> map = list.stream()
    .collect(Collectors.groupingBy(
        Student::getName,
        Collectors.mapping(student -> getNum(student.getAddr()),
            Collectors.toSet())));

我选择创建集合而不是列表地图,因为它似乎你不希望列表中有重复项。

I've chosen to create a map of sets instead of a map of lists, as it seems that you don't want duplicates in the lists.

如果你确实需要列表而不是集合,那么首先更有效率收集到集合,然后将集合转换为列表:

If you do need lists instead of sets, it's more efficient to first collect to sets and then convert the sets to lists:

Map<String, List<String>> map = list.stream()
    .collect(Collectors.groupingBy(
        Student::getName,
        Collectors.mapping(s -> getNum(s.getAddr()),
            Collectors.collectingAndThen(Collectors.toSet(), ArrayList::new))));

这使用 Collectors.collectingAndThen ,首先收集然后转换结果。

This uses Collectors.collectingAndThen, which first collects and then transforms the result.

另一种更紧凑的方式,没有流:

Another more compact way, without streams:

Map<String, Set<String>> map = new HashMap<>(); // or LinkedHashMap
list.forEach(s -> 
    map.computeIfAbsent(s.getName(), k -> new HashSet<>()) // or LinkedHashSet
        .add(getNum(s.getAddr())));

此变体使用 Iterable.forEach 迭代列表和 Map.computeIfAbsent 按学生名称对转换后的地址进行分组。

This variant uses Iterable.forEach to iterate the list and Map.computeIfAbsent to group transformed addresses by student name.