java 聚集_Java:聚集操作

你使用集合的目的是什么?当然不是为了简单的存储然后置之不理,你是为了从集合取数据和操作数据的。

再次考虑前一篇文章提到的背包类,

如果要打印所有背包的重量,

for(Package p : packages)

System.out.println(p.getWeight());

遍历,可以使用"forEach"这一聚集操作,

packages.stream()

.forEach(e -> System.out.println(p.getWeigh());

看不懂语法不要紧。我们再来个稍微复杂一点的,

我们只打印“重量大于20的背包重量”,

packages.stream()

.filter(e -> e.getWeight() > 20)

.forEach(e - > System.out.println(e.getWeight());

分析其结构,

packages是个集合,stream()方法是获取其“流”,能产生流的不只是集合,数组,I/O通道都可以。下面就是管道操作(和MongoDB或是Linux下的管道类似)了。即有0个或若干个中间操作,如这里的filter,来产生新的流,然后有一个终结操作,它可以有返回值(不再是一个流),也可以没有返回值。

其中,filter的函数原型是:

Stream filter p)接受一个谓词参数(条件)。

查看java.util.strem下面的API,其操作时很多的,部分如下,

0818b9ca8b590ca3270a3433284dd417.png

具体用法不一一介绍。

我们再看一个需求,求“重量大于20的背包的平均重量”。

double average = packages

.stream()

.filter(e -> e.getWeight() > 20)

.mapToInt(e -> e.getWeigh())

.average()

.getAsDouble();

除了filter表示过滤,还有maptoInt,返回一个IntStream。

函数原型是,

IntStream maptoInt(toIntFunction super T> mapper)其参数是一个返回Int的lambda表达式。

average()是IntStream的方法,很明显,是取平均值的,返回一个OptionalDouble,你可以回想OptionalDouble是什么?怎么不直接返回Double!!OptionalDouble是java8新加的,类似的API很多,它的特点是该对象可能包含也可能不包含一个值。作用在于:传统方法返回一个为Null的值,继续操作会报NullException,如果OptionalXX没有值,是可以继续操作的(当然没有值getAsDouble会报NoSuchElement异常。

另外,average这个终结操作也是reduction 操作。

在JDK里面,像average,sum,min等都是通过组合流的内容返回一个值,这些操作称为reduction操作。当然,有点reduction操作返回一个集合而不是一个值。值得一提的是,JDK还提供了两个一般化的操作:reduce和collect。

假设我们需要对背包容量求和,

Integer total = packages

.stream()

.mapToInt(e -> e,getWeight())

.sum();

如果要用reduce对它改造,

Integer total = packages

.stream()

.mapToInt(e -> e,getWeight())

.reduce(0,(a,b) -> a + b);

如果使用函数引用,

Integer total = packages

.stream()

.mapToInt(e -> e,getWeight())

.reduce(0,Integer::sum);

查看reduce的函数原型:

T reduce(T indentidy,BinaryOperator accumulator)

这可能比较费解,

API是这样介绍的,using the provided identity value and an associative accumulation function。

先看是associative,“结合性”,就是说要满足,

a op b op c = a op (b op c)

像加法,最小值,最大值,字符拼接都有这个性质。

API 还说,reduce函数等价于,

T result = identity;

for (T element : this stream)

result = accumulator.apply(result, element)

return result;

那identy是什么呢?对于操作的集合的所有t,应该有

accumulator.apply(identity, t) = t

是的,它就是离散数学里面提到的1元。对加法而言,1元就是0。

reduce操作总会返回新的值。然而,累积函数在每次处理流中的一个元素时也返回一个新的值。假设你要把流“reduce”成一个集合,你每添加一个元素处理就会产生一个新的结合,这显然是个性能上的缺憾,是很低效的。这时,你可以考虑更新已有的集合。这就是collect方法做的事情。

下一篇再介绍collect的使用细节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值