java8 汇聚操作之reduce、collect用法

java8 汇聚操作之reduce、collect用法

1. reduce

--reduce 操作可以实现从一组值中生成一个值。它有三个override的方法,我们一起来看看具体的实现。
  • Optional reduce(BinaryOperator accumulator);

     接受一个BinaryOperator类型的累加器,使用的lambda表达式为:
    
System.out.println(
				Stream.of(2,4,6,7,9,11)
				.reduce((sum , num) -> sum + num )
				.get());

分析:可以看到reduce方法接受一个函数,这个函数有两个参数,第一个参数是上次函数执行的返回值(也称为中间结果),
第二个参数是stream中的元素,这个函数把这两个值相加,得到的和会被赋值给下次执行这个函数的第一个参数。
要注意的是:第一次执行的时候第一个参数的值是Stream的第一个元素,第二个参数是Stream的第二个元素
这个方法返回值类型是Optional,这是Java8防止出现NPE的一种可行方法。

  • T reduce(T identity, BinaryOperator accumulator);

      第二个方法跟第一个差不多,不过他接收一个初始,如果Stream为空,就直接返回该值。而且这个方法不会返回Optional,因为其不会出现null值。
    
System.out.println(
				Stream.of(2,4,6,7,9,11)
				.reduce(0 , (sum , num) -> sum + num )
				);
  • <U> U reduce(U identity,BiFunction<U>, ? super T, U> accumulator,BinaryOperator<u> combiner)

     第三个方法比第二个多了一个参数 BinaryOperator  combiner,这个是在并发执行的时候用的,用来把多个accumulator的结果结合到一起。
    
List<Integer> nums = new ArrayList<Integer>();
		nums.add(1);
		nums.add(2);
		nums.add(9);
		nums.add(7);
		nums.add(5);
		System.out.println(
				nums.parallelStream().reduce(0, (sum,num) -> sum + num , (result1 , result2) -> result1 + result2 ));

2. collect

  1. <R, A> R collect(Collector<? super T, A, R> collector);

    我们看到collect()接收一个参数collector,这是一个收集器,一种通用的、从流生成复杂值的结构。只要将它传给collect 方法,所有的流就都可以使用它了。标准类库已经提供了一些有用的收集器,现在我们主要对java.util.stream.Collectors的几个方法进行讲解。
    

    1) 数据分块 partitioningBy

    如果你想把流分成两个集合,那么你可以用 Collectors.partitioningBy(Predicate predicate)。
    

收集器partitioningBy,它接受一个流,并将其分成两部分。它使用Predicate 对象判断一个元素应该属于哪个部分,并根据布尔值返回一个Map 到列表。因此,对于true List 中的元素,Predicate 返回true;对其他List 中的元素,Predicate 返回false。

*******  需求:把一群人中的未成年与成年人分出来。 *********

主要代码片段:
class Person{
	
	private String name;
	private int age;
	private String city;
	
	
	public boolean isTeenager(){
		if(age <= 18)
			return true;
		return false;
	}
	...
}
案例实现:
		Person p1 = new Person("liMing", 21, "nc");
		Person p2 = new Person("liuHua", 14, "nc");
		Person p3 = new Person("zhangLiao", 25, "sz");
		Person p4 = new Person("zhuGang", 7, "sh");
		
		Map<Boolean, List<Person>>  lists = Stream.of(p1 , p2 , p3 ,p4 ).collect(Collectors.partitioningBy(person -> person.isTeenager()));

输出结果:
{true=[[name=liuHua, city=nc, age=14], [name=zhuGang, city=sh, age=7]], 
 false=[[name=liMing, city=nc, age=21], [name=zhangLiao, city=sz, age=25]]}
Collectors.partitioningBy(Predicate predicate ,Collector downstream )。这个重载方法是对predicate 后的数据进行二次处理。比如可以求未成年与成年人的数量:
Stream.of(p1 , p2 , p3 ,p4 ).collect(Collectors.partitioningBy(person -> person.isTeenager() , Collectors.counting()));			

2) 数据分组 groupingBy

数据分组是一种更自然的分割数据操作,与将数据分成ture 和false 两部分不同,可以使用任意值对数据分组。	
******* 需求:按照城市把人分组。***********

案例实现:
Map<String, List<Person>>  lists2 = Stream.of(p1 , p2 , p3 ,p4 ).collect(Collectors.groupingBy(person -> ((Person)person).getCity()));

输出:
{sh=[[name=zhuGang, city=sh, age=7]], 
 nc=[[name=liMing, city=nc, age=21], [name=liuHua, city=nc, age=14]], 
 sz=[[name=zhangLiao, city=sz, age=25]]}

附:两个参数的重载跟 partitioningBy一样,三个参数的是指定返回值的类型。
groupingByConcurrent是并行操作的时候用的,当不需要保证输出流的顺序的时候,可以用这个。

参考

1:Java 8 Lambdas book
2:Java 8 API doc
3:http://ifeve.com/stream/

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值