Java Stream按条件减少多个列表

Posted

技术标签:

【中文标题】Java Stream按条件减少多个列表【英文标题】:Java Stream reducing multiple lists by condition 【发布时间】:2020-12-02 19:57:21 【问题描述】:

在 java 1.8 或更高版本上是否可以减少列表列表?

当数字的总和不能超过 8 时,我需要数字数组。

示例:我有以下列表:[ 2 , 4 , 6 ]。 返回值可以是 [ [ 2 , 4 ] , [ 6 ] ] 或 [ [ 2, 6 ],[ 4 ] ]。

我尝试了以下方法:

List<Integer> nums = Arrays.asList(2,4,6);
        nums.stream()
            .filter((p) -> p <= 8)
            .map(Collections::singleton)
            .reduce(new ArrayList<List<Integer>>(), (s1, s2) -> 
                int sumS1 = s1.stream().reduce(0, (n1, n2) -> n1 + n2);
                if (sumS1 == 8 ) return s1;
                int sumS2 = s1.stream().reduce(0, (n1, n2) -> n1 + n2);
                if (sumS1 + sumS2 <= 8 ) return s1.addAll(s2);
                return s1;
            )
            .collect(Collectors.toSet());

但我没有得到预期的结果。

我使用有状态和访问控制的外部变量,但这不是最好的方法。

有没有办法用 Stream 和无状态来构建它?

我认为是在 flatMap 对面

【问题讨论】:

Java Streams 是错误的工具。这个问题可能需要用 recursion 来实现。 【参考方案1】:

如果你想从所有的组合中找到一个满足条件的组合。

List<Integer> list = Arrays.asList(2, 4, 6);
List<List<Integer>> result = IntStream.range(0, 1 << list.size())
    .mapToObj(i -> IntStream.range(0, list.size())
        .filter(j -> (1 << j & i) != 0)
        .mapToObj(list::get)
        .collect(Collectors.toList()))
    .filter(x -> x.stream().mapToInt(i -> i).sum() < 8)
    .collect(Collectors.toList());
System.out.println(result);

输出

[[], [2], [4], [2, 4], [6]]

【讨论】:

以上是关于Java Stream按条件减少多个列表的主要内容,如果未能解决你的问题,请参考以下文章

使用stream()按元素属性的Java排序列表[重复]

java8 stream对数组按条件进行分组

在Java Stream中减少If

如何将多个谓词应用于 java.util.Stream?

Java 通过stream()获取找到List(列表)中最小的对象元素

java.util.stream 库简介