【问题标题】:Collect both matching and non-matching in one stream processing?在一个流处理中收集匹配和不匹配?
【发布时间】:2018-11-14 09:27:33
【问题描述】:

有没有办法在一次处理中同时收集匹配和不匹配的流元素? 举个例子:

final List<Integer> numbers = Arrays.asList( 1, 2, 3, 4, 5 );
final List<Integer> even = numbers.stream().filter( n -> n % 2 == 0 ).collect( Collectors.toList() );
final List<Integer> odd = numbers.stream().filter( n -> n % 2 != 0 ).collect( Collectors.toList() );

有没有办法避免两次遍历数字列表?像“匹配的收集器和不匹配的收集器”之类的东西?

【问题讨论】:

标签: java java-8 java-stream


【解决方案1】:

你可以这样做,

Map<Boolean, List<Integer>> oddAndEvenMap = numbers.stream()
        .collect(Collectors.partitioningBy(n -> n % 2 == 0));
final List<Integer> even = oddAndEvenMap.get(true);
final List<Integer> odd = oddAndEvenMap.get(false);

【讨论】:

  • 非常感谢,就是这样 - 我怎么能错过这个?! ;) 特别有用的是 partitioningBy 与另一个收集器结合使用,如下所示:Map&lt;Boolean,Map&lt;Integer,Boolean&gt;&gt; infos = numbers.stream().collect( Collectors.partitioningBy( n -&gt; n % 2 == 0, Collectors.toMap( n-&gt;n, n-&gt; expensiveCalculation(n) ) ) );
【解决方案2】:

如果您有 2 个以上的组(而不是使用 %2 的奇数和偶数),例如在余数类 %3 中对整数进行分组,您可以使用函数:

Function<Integer, Integer> fun =  i -> i%3;
List<Integer> a = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Map<Integer, List<Integer>> collect = a.stream().collect(Collectors.groupingBy(fun));

System.out.println(collect);
//{0=[3, 6, 9], 1=[1, 4, 7, 10], 2=[2, 5, 8]}

或者想象你有一个字符串列表,你想通过开始 char 来分组 而不是对匹配和不匹配进行分组(例如,以 a 开头) 你可以这样做:

Function<String, Character> fun =  s -> s.charAt(0);
List<String> a = Arrays.asList("baz","buzz","azz","ayy","foo","doo");
Map<Character, List<String>> collect = a.stream().collect(Collectors.groupingBy(fun));

System.out.println(collect);
//{a=[azz, ayy], b=[baz, buzz], d=[doo], f=[foo]}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多