一、为什么引入Stream流
流是一系列与特定存储机制无关的元素——实际上,流并没有“存储”之说。使用流,无需迭代集合中的元素,就可以从管道提取和操作元素。这些管道通常被组合在一起,形成一系列对流进行操作的管道。
在大多数情况下,将对象存储在集合中是为了处理他们,因此你将会发现你将编程的主要焦点从集合转移到了流上,流的一个核心的好处是,它使得程序更加短小并且更易理解。当Lambda表达式和方法引用和流一起使用的时候会让人感觉自成一体。
二、如何使用Stream流
流操作的类型有三种:创建流,修改流元素(中间操作 Intermediate Operations),消费流元素(终端操作 Terminal Operations)
创建Stream流
使用Arrays.stream()方法创建
Integer[] arr = new Integer[]{1,2,3,4,5};
Arrays.stream(arr).filter(num -> num > 3);
使用Stream.of ()方法创建
Integer[] arr = new Integer[]{1,2,3,4,5};
Stream.of(arr).filter(num -> num > 3);
查看of()的源码中得知,该方法也是调用了Arrays.stream()方法实现的
/**
* Returns a sequential ordered stream whose elements are the specified values.
*
* @param <T> the type of stream elements
* @param values the elements of the new stream
* @return the new stream
*/
@SafeVarargs
@SuppressWarnings("varargs") // Creating a stream from an array is safe
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
使用Collection.stream()方法创建
List<String> list = new ArrayList<>(1);
list.stream().forEach(str -> System.out.println(str));
使用Stream.iterate()方法创建
Stream.iterate(1, num -> num + 2).limit(10).forEach(num -> System.out.println(num));
使用Stream.generate()方法创建
Stream.generate(() -> Arrays.asList(arr)).limit(1).forEach(num -> System.out.println(num));
修改流元素(中间操作 Intermediate Operations)
中间操作用于从一个流中获取对象,并将对象作为另一个流从后端输出,以连接到其他操作。http://www.mitmia.com
1、跟踪和调试
peek() 操作的目的是帮助调试,允许你无修改地查看流中的元素
// streams/Peeking.java
class Peeking {
public static void main(String[] args) throws Exception {
FileToWords.stream(“Cheese.dat”)
.skip(21)
.limit(4)
.map(w -> w + " ")
.peek(System.out::print)
.map(String::toUpperCase)
.peek(System.out::print)
.map(String::toLowerCase)
.forEach(System.out::print);
}
}
输出结果:
Well WELL well it IT it s S s so SO so
因为 peek() 符合无返回值的 Consu