java8新特性(二):stream流式编程详细介绍
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。这是目前为止最大的一次对Java库的完善,以便开发者能够写出更加有效、更加简洁和紧凑的代码。Steam API极大得简化了集合操作。
下面简单介绍下stream的使用
我们先造一个List
List<OrderInfo> list = new ArrayList<>();
OrderInfo orderInfo1 = new OrderInfo();
orderInfo1.setId(1);
orderInfo1.setName("apple");
orderInfo1.setPrice(33.56);
list.add(orderInfo1);
OrderInfo orderInfo2 = new OrderInfo();
orderInfo2.setId(2);
orderInfo2.setName("huawei");
orderInfo2.setPrice(1.2);
list.add(orderInfo2);
OrderInfo orderInfo3 = new OrderInfo();
orderInfo3.setId(3);
orderInfo3.setName("xiaomi");
orderInfo3.setPrice(13.2);
list.add(orderInfo3);
我现在要把list中每个orderInfo的name取出来,得到一个List
List namesList = new ArrayList<>();
for (OrderInfo info:list){
namesList.add(info.getName());
}
但是使用stream流之后,就可以使用一行代码搞定。类似地,也可以把id全部都取出来
List<String> names = list.stream().map(orderInfo -> orderInfo.getName()).collect(Collectors.toList());
List<Integer> ids = list.stream().map(orderInfo -> orderInfo.getId()).collect(Collectors.toList());
System.out.println(names);
System.out.println(ids);
我们运行一下,看看打印结果
[apple, huawei, xiaomi]
[1, 2, 3]
还可以用stream中的filter做筛选,筛选出符合条件的对象,比如,我要把list中name是apple的对象找出来
List<OrderInfo> appleList = list.stream().filter(orderInfo -> orderInfo.getName().equals("apple")).collect(Collectors.toList());
System.out.println("appleList:"+ JSON.toJSONString(appleList));
打印结果
appleList:[{"id":1,"name":"apple","price":33.56}]
还可以使用sum方法得出list中所有对象的某个属性的和,比如这个List
Double price = list.stream().mapToDouble(OrderInfo::getPrice).sum();
System.out.println("price:"+price);
打印结果
price:47.96
以上介绍的stream的用法都是串行流,java8中还有并行流(Parallel Stream)。写法有两种
list.stream().parallel();
list.parallelStream();
之所以设计使用并行流处理来处理业务,是为了充分利用CPU资源以获取更好的性能,所以使用parallelStream理论上速度会更快。我们可以对比一下:
先定义一个list,放入1000个数
List<Integer> linkedList =new LinkedList();
for (int a = 1;a <=10000 ;a++) {
linkedList.add(a);
}
首先我们用传统的for循环遍历
long start = System.currentTimeMillis();
for (int a = 0; a < linkedList.size(); a++) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("for循环遍历方式 : " + (System.currentTimeMillis() - start) + "ms");
然后我们用stream的串行流方式遍历
linkedList.stream().forEach(r -> {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("stream串行遍历方式 : " + (System.currentTimeMillis() - start) + "ms");
最后我们用parallelStream并行流方式遍历
linkedList.parallelStream().forEach(r -> {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("parallelStream并行遍历方式 : " + (System.currentTimeMillis() - start) + "ms");
一起运行,看看打印结果
for循环遍历方式 : 15358ms
stream串行遍历方式 : 30669ms
parallelStream并行遍历方式 : 32023ms
可以看到,前两种遍历方式的时间差不多,从0~15358ms,以及从15358ms~30669ms,但是并行流遍历的时间却特别短,30669ms~32023ms,非常快
最后多说一句,parallelStream虽然快,但是不要乱用,我们曾经遇到过在一个公共方法中使用了parallelStream来处理数据,结果很多入口都在调用这个方法,导致这个方法短时间内快速处理大量数据,疯狂占用CPU资源,CPU飙升导致服务器告警,系统卡顿。所以有些不是很重要,或者不需要那么及时处理的数据,可以不用parallelStream来处理。
当然,还有很多细节,这里就不逐一列举,根据以上几个例子,应该大致可以举一反三,自己去尝试探索和使用了
上一篇:java实现冒泡算法的几种方式