Java 8 Stream:过滤、处理结果,然后处理排除项

12

在Java 8的Streams中,我知道如何基于谓词对集合进行过滤,并处理谓词为true的项。我想知道的是,如果谓词将集合分成仅两组,是否可以通过API基于谓词进行过滤、处理过滤结果,然后立即链接到一个调用,以处理过滤器排除的所有元素?

例如,考虑以下列表:

List<Integer> intList = Arrays.asList(1,2,3,4);

能否做到以下事情:

intList.stream()
    .filter(lessThanThree -> lessThanThree < 3)
    .forEach(/* process */)
    .exclusions(/* process exclusions */); //<-- obviously sudocode
或者我只需要对筛选出的项目执行forEach过程,然后调用原始列表上的stream()filter()来处理剩余的项目吗?
谢谢!

4
https://dev59.com/g1cP5IYBdhLWcg3w19Xz - Holger
2个回答

17

请看 Collectors.partitioningBy,它接收一个谓词作为参数。使用Stream.collect来使用它。

结果是一个只有两个Boolean条目的映射:对于true键,您有一个包含与谓词匹配的流元素的List,而对于false键,则有一个包含未匹配的元素的List

请注意,Collectors.partitioningBy还有一个重载版本,可以接受第二个参数,它是下游收集器,如果您想将每个分区收集到不同于列表的东西中,则可以使用该参数。

在您的示例中,可以这样使用它:

Map<Boolean, List<Integer>> partition = intList.stream()
    .collect(Collectors.partitioningBy(i -> i < 3));

List<Integer> lessThan = partition.get(true); // [1, 2]
List<Integer> notLessThan = partition.get(false); // [3, 4]

我还想强调一个重要的观察结果,来自于用户@Holger在链接问题中添加的评论:

Collectors.partitioningBy方法将总是在Map中为truefalse有一个结果,即使没有任何元素分入该组,也会返回一个空列表,而不是null

这种特殊情况已经添加到jdk9文档中作为API注释(同样,这是由用户@Holger观察到的):

如果分区没有元素,则其在结果Map中的值将是一个空列表。


2
你可以从以下链接获取示例:http://www.concretepage.com/java/jdk-8/java-8-collectors-partitioningby-example - Mohamed Anees A

1

Stream接口中没有访问排除项的操作。但是,您可以实现一个更复杂的谓词:

intList.stream()
    .filter(i -> {
        if (i < 3) return true;
        else {
            // Process excluded item i
            return false;
        }
    }).forEach(/* Process included item. */)

但是你必须小心保持谓词不干扰和无状态。


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