一、Stream说明
Stream与IO无任何关系。
Java 8 中的Stream是对集合 (Collection) 对象功能的增强, 他专注于对集合对象进行各种非常便利,高效的聚合操作(aggregate operation), 或者大批量数据操作 (bulk data operation).
Stream API借助于同样新出现的Lambda 表达式, 极大的提高编程效率和程序可读性. 同时他提供穿行和并行两种模式进行汇聚操作, 并发模式能够成分利用多核处理器的优势, 使用fork/join 并行法师来拆分任务和加速处理过程.
通常编写并行代码很难而且容易出错, 但使用Stream API无需编写一行多线程的代码, 就可以很方便地写出高性能的并发代码.
Java 8中首次出现的java.util.stream是一个函数式语言+多核时代综合影响的产物.
二、java7于java8 Stream的使用对比
需要使用到的实体类
@Setter
@Getter
public class Apple {
private Long appleId;
private String appleName;
public Apple(){}
public Apple(Long appleId,String appleName){
this.appleId=appleId;
this.appleName=appleName;
}
}
以下是一个java7对list的操作,包括了筛选、排序、取值等操作。
public static void java7(){
//目标,获取id大于10的苹果名称,并对结果集按照id大小排序
List<Apple> list=getList();
List<Apple> targetList=new ArrayList<>();
for(Apple apple : list){
if(apple.getAppleId()>10){
targetList.add(apple);
}
}
Collections.sort(targetList, new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return o2.getAppleId().compareTo(o1.getAppleId());
}
});
List<String> nameList=new ArrayList<>();
for(Apple apple : targetList){
nameList.add(apple.getAppleName());
}
XLogUtils.info(jsonToString(nameList));
}
java8对列表进行筛选、排序、取值操作
是不是很清爽?那么…那么代价是什么呢?看完全文你就知道啦。
public static void java8(){
List<Apple> list=getList();
List studentList = list.stream()
.filter(x->x.getAppleId()>10)
.sorted(Comparator.comparing(Apple::getAppleId).reversed())
.map(Apple::getAppleName)
.collect(Collectors.toList());
XLogUtils.info(jsonToString(studentList));
}
三、Stream概述
1、Stream的特性
- 不存储数据
- 不改变数据源
- 延迟执行
2、Stream的创建
- 可以通过已存在的数组创建
- 可以通过已存在集合创建
- 可以创建一个空的流
- 可以创建一个无限的流
- 可以创建一个规律的流
3、对Stream的操作
- 一般使用
- 提取流、组合流
- 聚合操作
- Optional类型说明
- 分组与分片
- 收集结果
4、并行流
5、原始类型流
四、Stream使用以及说明
1、Stream的延迟特性
(1)延迟性验证
public static boolean filter(Apple s) {
System.out.println("begin compare");
return s.getAppleId() > 5;
}
/**
* 验证延迟性
*/
public static void f2() {
List<Apple> list=getList();
Stream<Apple> stream = list.stream()
.filter(apple -> filter(apple));
System.out.println("split-----------------------------------");
List<Apple> studentList = stream.collect(Collectors.toList());
System.out.println("end-------------------------------------");
}
输出:
split-----------------------------------
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
begin compare
end-------------------------------------
由上述可确认,Stream确实是具有延迟性。
(2)延迟性事故
/**
* 延迟特性,导致的空指针异常
*/
public static void f4(){
List<Apple> list=getList();
Stream<Apple> appleList= list.stream();
appleList.forEach(s -> {
System.out.println("s->"+s);
if (s.getAppleId() < 4) {
System.out.println("select->"+s);
list.remove(s);
XLogUtils.info(jsonToString(list));
}
});
}
输出:
select->Stream.Apple@71bbf57e
[info]>>>>null
s->Stream.Apple@7f13d6e
select->Stream.Apple@7f13d6e
[info]>>>>null
s->Stream.Apple@51cdd8a
select->Stream.Apple@51cdd8a
[info]>>>>null
s->null
Exception in thread “main” java.lang.NullPointerException
at Stream.TestStreamClass.lambda$f4 9 ( T e s t S t r e a m C l a s s . j a v a : 171 ) a t j a v a . u t i l . A r r a y L i s t 9(TestStreamClass.java:171) at java.util.ArrayList 9(TestStreamClass.java:171)atjava.util.ArrayListArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at Stream.TestStreamClass.f4(TestStreamClass.java:169)
at Stream.TestStreamClass.main(TestStreamClass.java:38)
如上,出现了空指针异常。出现异常的是
if (s.getAppleId() < 4) {
s对象空指针异常。list.remove(s);使对象被remove,但是此处又调用了此对象的方法,导致空指针异常。
(3)延迟性的使用
List<Apple> list=getList();
Stream<Apple> stream = list.stream()
.filter(apple -> filter(apple));
list.add(new Apple(1001L,"New Apple"));
List<Apple> studentList = stream.collect(Collectors.toList());
指令执行的顺序为:
[1]获取数据源
[2]声明Stream
[3]添加数据到数据源
[4]执行Stream业务(过滤),并聚合为list。
所以,虽然add操作是在声明Stream之后,但是它也被执行过滤。
2、创建Stream
(1)通过数组创建流
/**
* 通过数组创建流
*/
@Test
public void testArrayStream(){
//1.通过Arrays.stream
//1.1基本类型
int[] arr = new int[]{1,2,34,5};
IntStream intStream = Arrays.stream(arr);
//1.2引用类型
Student[] studentArr = new Student[]{new Student("s1",29),new Student("s2",27)};
Stream<Student> studentStream = Arrays.stream(studentArr);
//2.通过Stream.of
Stream<Integer> stream1 = Stream.of(1,2,34,5,65);
//注意生成的是int[]的流
Stream<int[]> stream2 = Stream.of(arr,arr);
stream2.forEach(System.out::println);
}
(2)通过集合创建流
@Test
public void testCollectionStream(){
List<String> strs = Arrays.asList("11212","dfd","2323","dfhgf");
//创建普通流
Stream<String> stream = strs.stream();
//创建并行流
Stream<String> stream1 = strs.parallelStream();
}
(3)创建空的流
@Test
public void testEmptyStream(){
//创建一个空的stream
Stream<Integer> stream = Stream.empty();
}
(4)创建无限流
@Test
public void testUnlimitStream(){
//创建无限流,通过limit提取指定大小
Stream.generate(()->"number"+new Random().nextInt()).limit(100).forEach(System.out::println);
Stream.generate(()->new Student("name",10)).limit(20).forEach(System.out::println);
}
(5)创建规律的无限流
@Test
public void testUnlimitStream1(){
Stream.iterate(0,x->x+1).limit(10).forEach(System.out::println);
Stream.iterate(0,x->x).limit(10).forEach(System.out::println);
//Stream.iterate(0,x->x).limit(10).forEach(System.out::println);与如下代码意思是一样的
Stream.iterate(0, UnaryOperator.identity()).limit(10).forEach(System.out::println);
}
参考文章:https://www.cnblogs.com/andywithu/p/7404101.html
参考文章:https://www.jianshu.com/p/9101b2ef96d8