通过流能更好地操作集合。java.util.Stream一般与lamda表达式结合使用。
1.流简介
流由三部分构成:源、0或多个中间操作、1个终止操作。
java.util.Stream这个interface里大部分函数都是高阶函数(高阶函数:接收函数作为参数的函数)。流支持串行/并行。
流操作的分类:1.惰性求值。2.及早求值。
惰性求值:中间操作,会返回一个全新的Stream对象,中间操作并不会立即执行,直到遇到终止操作才会执行。
及早求值:终止操作,不会返回Stream类型对象,可能不返回值,也可能返回其它类型的单个值。
2.流的创建方式
3.流的一些操作实例
a.流转化为String[]
Stream<String> stream = Stream.of("hello", "world"); //生成流对象
String[] stringArray = stream.toArray(length -> new String[length]);
或 String[] stringArray = stream.toArray(String[]::new);
b.流转化成List
Stream stream = Stream.of("hello", "world");
List list = stream.collect(Collectors.toList());
或者
List list = stream.collect(() ->newArrayList(), (theList, item) -> theList.add(item),
(theList1, theList2) -> theList1.addAll(theList2));
参数1:Supplier,返回给list的。
参数2:累加器,BiConsumer<R, ? super T> accumulator, theList是返回给list的,item是遍历的stream中的每个元素。
参数3:聚合器,BiConsumer<R, R> combiner, 将上一次得到的list加到theList1,theList1就是要返回的。
或者
List list = stream.collect(Collectors.toCollection(ArrayList::new));
c.将流中各元素拼接成字符串
String str = stream.collect(Collectors.joining());
d.用流的方式求List中每个数字的平方,打印
List list = Arrays.asList(1,2,3,4,5);
list.stream().map(item -> item * item).collect(Collectors.toList()).forEach(System.out::println);
e.将stream中每个list中的每个元素求平方,以一个整体输出
Stream> stream = Stream.of(Arrays.asList(1), Arrays.asList(2,3), Arrays.asList(4,5,6));
stream.flatMap(theList -> theList.stream()).map(item -> item * item).forEach(System.out::println); //将流中的每个list都转成一个stream
f. Stream.generate(Supplier<T> s)创建流
Stream stream = Stream.generate(UUID.randomUUID()::toString);
stream.findFirst().ifPresent(System.out::println); //findFirst()之所以返回Optional<T>是为了规避NPE
g. Stream.iterate(final T seed,final UnaryOperator<T> f) 生成无限串行有序流,一般加limit(size)限制流的长度。seed是初始值,不对对seed应用f函数,f(seed)、f(f(seed))、...
Stream stream = Stream.iterate(1, item -> item +2).limit(6); // 1,3,5,7,9,11
4.流的特点
a.流不能被重复使用,流关闭后也不能再被使用。
上例中,stream在29行中已经被使用过了,就不能在第30行中再次被使用。
写成下面这样就没问题,不过更推荐使用方法链调用方式的写法。即stream.filter(xxx).distinct(yy)写法;
b.流的每个中间操作都会返回一个全新的流对象,直到遇到及早求值(终止操作)才会执行得到最终结果,如果没有终止操作,则所有中间操作根本不会执行。
上例中由于没有终止操作,map操作根本不会执行,控制台输出为空,什么都不打印。