Stream流,是jdk1.8中对集合对象功能的增强,可以通过将集合转换为六模型,通过声明的方式对集合中每个元素进行一系列并行或者串行的流水操作
对数据进行排序取值
从数据源中获取一组用户信息,查找年满18周岁以上的所有用户,然后针对用户信息按照工资值进行倒叙排序,获取所有用户的id编号
public class User{
private Long id;
private String name;
private Double salary;
private int age;
}
随机生成用户信息放在List集合中
List<User> list = new ArrayList<>();
for(int i = 1;i < 11;i++){
User user = new User();
user.setId(i+0L);
user.setName("name-"+i);
user.setSalary(random.nextDouble()*9000+1000);
user.setAge(random.nextInt(18)+10);
list.add(user);
}
常规编程方法
List<User> ulist = new ArrayList<>();
for(User tmp : list){
if(tmp.getAge() > 18)
ulist.add(tmp);
}
Collections.sort(ulist,new Comparator<User>(){
public int compare(User u1,User u2){
return u2.getSalary().compareTo(u1.getSalary());
}
});
List<Long> idList = newArrayList<>();
for(User tmp : ulist)
idList.add(tmp.getId());
System.out.println(idList);
Stream的使用
使用Stream可以简化代码,使代码简洁易读;如果使用parallelStream可以启动并发模式,使程序执行速度更快
list.stream().filter(t -> t.getAge() > 18).sorted((u1, u2) -> u2.getSalary().compareTo(u1.getSalary()))
.map(User::getId).forEach(System.out::println);
概述Stream
Stream不是集合元素,不是数据结构并不保存数据,Stream是有关算法和计算的,类似一个高级版本的迭代器Iterator。Stream只要给出对其中包含的元素执行什么操作,Stream就会隐式的在内部进行遍历,并给出响应的数据转换。单向不可往复、数据只能遍历一次,遍历过后就使用完毕
Stream可以并行化操作,Stream的并行操作是依赖java7中引入的Fork/Join框架拆分任务和加速处理过程,并且允许数据源是无限的
基本执行流程
使用Stream通常包括三个基本步骤:获取一个数据源source---转换为流---执行操作----获取想要的结果。每次转换原有的Stream对象,执行结果还是Stream,可以使用串行写法定义多个操作
-
数据源就是数据集合
-
将
List<T>
集合转换为Stream<T>
-
针对Stream进行一系列操作,每次操作结束返回还是Stream
-
可以将Stream转换为集合类型,也可以直接对其中的元素进行处理
Integer ids = roomList.stream().filter(b->b.getLength == 10).sort((x,y)->x.getHigh()-y.getHigh()).mapToInt(Room::getWidth).sum();
1.创建Stream
2.抓换Stream,每次执行转换Stream对象类型不改变,返回一个新的Stream对象
3.对Stream进行聚合操作,获取想要的结果
创建Stream
流Stream可以是顺序的,也可以是并行的。顺序流的操作是在单线程上执行的,而并行流实在多线程上并发执行的
1.可以使用Arrays.stream将一组数据转换为Stream
Integer[] arr = new Integer[]{2,5,63,98,7,8,9,20,30};
long count = Arrays.stream(arr).filter(i->i > 20).count();//统计大于20的数据个数
2.使用Collection.parallelStream使用并行流,处理任务并行执行。前提是硬件支持,也可以使用Collection.stream使用串行流
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
Stream<Integer> stream = list.parallelStream();
stream.forEach(System.out::println);
-
parallelStream在使用上和Stream沒有区别,本质上返回的都是一个流,只不过底层处理时会根据执行环境的条件判断时是并行还是串行
-
并行流不会按照原本的顺序轨迹执行,而是随机执行
3.对于基本类型目前有3中对应的包装类型Stream:IntStream、LongStream和DoubleStream。如果不适用对应的Stream类型,也可以使用Stream<Integer>、Stream<Long>和Stream<Double>
,但是针对元素进行装拆箱操作比较耗时,所以才有了常用的基本数据类型的对应Stream
//参数类型为int...不确定个数的参数,可以根据参数生成一个stream
IntStream.of(1,2,3,8,6,5,4).forEach(System.out::println);
System.out.println("---------");
//根据指定的返回生成一组连续值,含左不含右
IntStream.range(1, 10).forEach(System.out::println);
System.out.println("---------");
//根据指定的返回生成一组连续值,含左含右
IntStream.rangeClosed(1,10).forEach(System.out::println);
4.从输如入流中获取数据的方法
可以使用BufferedReader生成Stream,把流中的内容一行一行的读取出来
BufferedReader br = new BufferedReader(new FileReader("data.txt"));
Stream<String> stream = br.lines();
stream.forEach(System.out::println);
5.创建无限流的方法
generate方法可以获取一个参数函数用于创建无线stream
Stream<BigInteger> stream =Stream.generate.iterate(BigInteger.ZERO,n->n.add(BigInteger.TEN));
BigInteger[] arr = stream.limit(10).toArray(BigInteger[]::new);
System.out.println(Arrays.toString(arr));
遍历操作
Stream提供了forEach可以迭代器流中的每个元素,forEach方法可以接收一个lambda表达式,并且在每个元素上执行该表达式,但是注意不能修改本地变量值,也不能break/return之类的关键字提前结束循环
随机数的输出前10个值
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
r.ints().limit(10).forEach((tt)->{
if(tt > 10)
System.out.println(tt);
});