大家好啊,今天继续学习Java中的stream流的知识,在B站和其他网站都有相关的具体视频讲解,做好学习总结的准备,加油!
Stream(流)是一个来自数据源的元素队列,元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
Stream流,是JDK1.8中对集合对象功能的增强,可以通过将集合转换为流模型,通过声明的方式对集合中个每个元素进行一系列并行或者串行的流水线操作。
Stream概述
Stream不是集合元素,不是数据结构并不保存数据,Stream是有关算法和计算的,像是一个高级版本的迭代器Iterator。Stream只要给出对其包含的元素执行什么操作,Stream就会隐式地在内部进行遍历,并给出响应的数据转换。单向不可往复、数据只能遍历一次,遍历过后就使用完毕。
执行流程
通常包括3个基本步骤:获取一个数据源source---转换为流---执行操作---获取所想要的结果。
数据源就是原始的数据集合
将 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[]{3,4,6,8,9,23,232,33,96};
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);
3、对于基本类型目前有3中对应的包装类型Stream:IntStream、LongStream和DoubleStream。如果不使用对应的Stream类型,也可以使用 Stream<Integer>、Stream<Long>和Stream<Double> ,但是针对元素进行装拆箱操作比较耗时,所以才有了常用的基本数据类型的对应Stream
//参数类型为int...不确定个数的参数,可以根据参数生成一个stream
IntStream.of(3, 5, 18, 1, 4).forEach(System.out::println);
//根据指定的返回生成一组连续值,1-10含左不含右
IntStream.range(1, 10).forEach(System.out::println);
//根据指定的返回生成一组连续值,10-20含左含右
IntStream.rangeClosed(10, 20).forEach(System.out::println);
4、从输入流中获取数据的方法,可以使用BufferedReader生成stream,把流中的内容一行一行的读取出来
BufferedReader br = new BufferedReader(new FileReader("input/data.txt"));
Stream<String> stream=br.lines();
stream.forEach(System.out::println);
5、创建无限流的方法
//generate方法可以接收一个参数函数用于创建无限stream
Stream<String> stream = Stream.generate(() -> "test");
//stream.forEach(System.out::println);
// 获取前10个String转换为String[]
String[] arr = stream..limit(10).toArray(String[]::new);
System.out.println(Arrays.toString(arr));
//iterate方法可以接收一个参数函数用于创建无限的stream
Stream<BigInteger> stream = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.TEN));
BigInteger[] arr=stream.limit(10).toArray(BigInteger[]::new);
System.out.println(Arrays.toString(arr)); //[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
遍历操作
Stream提供了forEach可以迭代流中的每个数据,forEach方法可以接收一个lambda表达式,并且在每个元素上执行该表达式,但是注意不能修改本地变量值,也不能break/return之类的关键字提前结束循环。
//随机数的输出前10个值
Random r = new Random();
r.ints().limit(10).forEach(System.out::println);
r.ints().limit(10).forEach((tt) -> {
if(tt>10)
System.out.println(tt);
});
流的转换操作
Stream的操作符基本可以分为中间操作符和终止操作符两大类,中间操作符会继续向下传递,终止操作符直接对数据进行消费或者收集,不会继续向下传递。
中间操作符
map转换操作符,可以将一个A转换为一个B
flatMap可以将一个A转换为多个B
limit限流操作
distinct去重操作,底层采用equals进行比对
filter过滤操作,去除不满足条件的数据
peek跳出操作
skip跳过操作
sorted排序操作,Comparable和Comparator接口
终止操作
collect收集操作,使用官方的Collectors提供的收集器
count统计操作,统计数据个数
findFirst/findAny查找操作,返回的类型为Optional
noneMatch、AllMatch和anyMatch匹配操作,检查数据流中是否存在符合条件的数据
min和max最值操作,需要比较器
reduce规约操作,将数据流的值规约为一个值,例如count/min/max底层实际上就是使用reduce
forEach遍历操作,可以对最终的数据进行消费
toArray数组操作,用于将数据流的元素转换为数组
filter方法
filter方法用于对传入的数据流进行过滤处理,只返回满足条件的数据组成的新的数据流。
List<Integer> list = new ArrayList<>();
list.add(15);
list.add(32);
list.add(5);
list.add(232);
System.out.println(list);
List<Integer> result = list.stream().filter(i -> i > 50).collect(Collectors.toList());
System.out.println(result);
map方法
map方法用于对流中的数据进行某种形式的转换,转换操作函数当作参数传入方法
例如将Integer转换为String
List<Integer> list = new ArrayList<>();
list.add(15);
list.add(32);
list.add(5);
list.add(232);
List<String> result=list.stream().map(i->String.valueOf(i))
.collect(Collectors.toList());
List<String> result = list.stream().map(i -> String.valueOf(i))
.filter(bb->bb.length()>2).collect(Collectors.toList());
flatMap方法
flatMap可以对每个元素应用一个函数,并将返回的值收集到一个新的流中
List<Integer> list=new ArrayList<>();
list1.add(34);
list1.add(25);
list1.add(35);
List<Integer> list2=new ArrayList<>();
list2.add(999);
list2.add(888);
list2.add(999);
list2.add(666);
Map<String,List<Integer>> testMap=new HashMap<>();
testMap.put("aa",list1);
testMap.put("bb",list2);
List<Integer> result=testMap.values() //获取到两个Collection<List<Integer>>
.stream().flatMap(num->num.stream()).collect(Collectors.toList());
limit方法
limit方法会返回一个包含指定个数元素的新stream,如果原始数据总长大小不足则返回原始流
List<Integer> list=new ArrayList<>();
for(int i=0;i<10;i++)
list.add(i);
List<Integer> result=list.stream().limit(5).collect(Collectors.toList());
skip方法
skip方法的含义是跳过多少个元素,继续处理后续元素
List<Integer> list=new ArrayList<>();
for(int i=0;i<10;i++)
list.add(i);
List<Integer> result=list.stream().skip(5).collect(Collectors.toList());
distinct方法
distinct会根据原始流中的元素返回一个具有相同顺序,但是剔除了重复值的流
List<Integer> list=new ArrayList<>();
list.add(10);
list.add(39);
list.add(10);
list.add(78);
list.add(39);
list.stream().forEach(obj -> System.out.print(obj + "\t"));
System.out.println("");
List<Integer> result=list.stream().distinct().collect(Collectors.toList());
System.out.println(result);
sorted方法
sorted方法是遍历整个流的所有数据,并且在产生任何数据元素之前对它进行排序。注意Comparable接口和Comparator接口
List<Integer> list=new ArrayList<>();
list.add(10);
list.add(39);
list.add(10);
list.add(78);
list.add(39);
List<Integer> result=list.stream()
.sorted(Integer::compareTo) //指定比较器,表示调用Integer类中的compareTo方法
.collect(Collectors.toList());
Random r=new Random();
r.ints().limit(10).sorted().forEach(System.out::println);
好了,今天就先总结学习到这里吧!下一篇继续总结学习Stream流的其他知识。