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

alo*_*llj 9 java java-8 java-stream

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

例如,请考虑以下列表:

List<Integer> intList = Arrays.asList(1,2,3,4);
Run Code Online (Sandbox Code Playgroud)

有可能做到:

intList.stream()
    .filter(lessThanThree -> lessThanThree < 3)
    .forEach(/* process */)
    .exclusions(/* process exclusions */); //<-- obviously sudocode
Run Code Online (Sandbox Code Playgroud)

或者我是否必须只forEach对已过滤的项目执行此过程,然后调用stream()filter()在原始列表上处理剩余的项目?

谢谢!

Fed*_*ner 13

看一下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]
Run Code Online (Sandbox Code Playgroud)

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

Collectors.partitioningBy总会有一个结果的truefalseMap,即空列表如果没有元素属于这个组,而不是null.

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

如果分区没有元素,则结果Map中的值将为空List.

  • 您可以从http://www.concretepage.com/java/jdk-8/java-8-collectors-partitioningby-example获取样本 (2认同)