Java 8 Stream API - Java 9 Collectors.flatMapping 用 Ja​​va 8 重写

2022-01-22 00:00:00 java-8 java java-stream collectors java-9

自从 java-9 调用 Collectors.flatMapping 作为分组或分区的下游发生.例如(示例取自 here):

列表<列表<整数>>列表 = Arrays.asList(Arrays.asList(1, 2, 3, 4, 5, 6),Arrays.asList(7, 8, 9, 10));映射<整数、列表<整数>>地图 =list.stream().collect(Collectors.groupingBy(收藏::尺寸,Collectors.flatMapping(l ->l.stream().filter(i -> i % 2 == 0),Collectors.toList())));

<块引用>

{4=[8, 10], 6=[2, 4, 6]}

这是一种相当优雅的方式,只使用 3 个收集器.我需要在 java-8 尚不支持的地方.我尝试使用 6 收集器,这是一种相当广泛的用法,但我无法找到使用较少它们的方法:

映射<整数、列表<整数>>地图 = list.stream().collect(Collectors.groupingBy(收藏::尺寸,Collectors.collectingAndThen(收藏家.映射(l ->l.stream().filter(i -> i % 2 == 0).collect(Collectors.toList()),Collectors.toList()),我->i.stream().flatMap(j -> j.stream()).collect(Collectors.toList()))));

有没有一个 更短 更好的方法,只使用 java-8?

解决方案

对于 this 特殊情况,我想这将是一个更简单的版本:

映射<整数、列表<整数>>地图=list.stream().collect(Collectors.toMap(收藏::尺寸,x ->x.stream().filter(y -> y % 2 == 0).collect(Collectors.toList())));

如果需要合并(两个大小相同的集合),我会添加一个非常简单的 merge 函数:

 映射<整数、列表<整数>>地图=list.stream().collect(Collectors.toMap(收藏::尺寸,x ->x.stream().filter(y -> y % 2 == 0).collect(Collectors.toCollection(ArrayList::new)),(左,右)->{left.addAll(right);向左返回;}));

否则,我同意 Michael 在此评论中的观点,这并不难向后移植到 java-8.

I got in touch with a new feature since java-9 called Collectors.flatMapping that takes place as a downstream of grouping or partitioning. Such as (example taken from here):

List<List<Integer>> list = Arrays.asList(
    Arrays.asList(1, 2, 3, 4, 5, 6), 
    Arrays.asList(7, 8, 9, 10));

Map<Integer, List<Integer>> map =list.stream()
    .collect(Collectors.groupingBy(
         Collection::size,
         Collectors.flatMapping(
             l -> l.stream().filter(i -> i % 2 == 0),
             Collectors.toList())));

{4=[8, 10], 6=[2, 4, 6]}

This is a fairly elegant way using just 3 collectors. I need to rewrite the collector in java-8 where is not yet supported. My attempt use 6 Collectors that is quite an extensive usage and I am not able to figure out a way using less of them:

Map<Integer, List<Integer>> map = list.stream()
    .collect(Collectors.groupingBy(
        Collection::size,
        Collectors.collectingAndThen(
            Collectors.mapping(
                l -> l.stream().filter(i -> i % 2 == 0).collect(Collectors.toList()),
                Collectors.toList()),
            i -> i.stream().flatMap(j -> j.stream()).collect(Collectors.toList()))));

Is there a shorter better way using solely java-8?

解决方案

For just this particular case, I guess this would be a simpler version:

Map<Integer, List<Integer>> map =
        list.stream()
            .collect(Collectors.toMap(
                Collection::size,
                x -> x.stream().filter(y -> y % 2 == 0).collect(Collectors.toList())
            ));

If there would be merging involved (two collections that would have the same size), I would add a merge function that is pretty trivial:

 Map<Integer, List<Integer>> map =
        list.stream()
            .collect(Collectors.toMap(
                Collection::size,
                x -> x.stream().filter(y -> y % 2 == 0).collect(Collectors.toCollection(ArrayList::new)),
                (left, right) -> {
                    left.addAll(right);
                    return left;
                }
            ));

Otherwise, I agree with Michael in this comment, this is not that hard to back-port to java-8.

相关文章