Java8引入了全新的Stream API,Stream API为Java编程提供了丰富的函数式编程操作。
Stream API与Java提供的其他集合类型有本质的区别,具体如下:
java.io的InputStream/OutputStream和java.util.stream的不同 :
java.io
java.util.stream
存储
顺序读写byte / char
顺序输出任意Java对象
用途
序列化至文件 / 网络
内存计算 / 业务逻辑
java.util.List和java.util.stream的区别
java.util.List
java.util.stream
元素
已分配并存储至内存
未分配,实时计算
用途
操作一组已存在的Java对象
惰性计算
Stream的特点:
可以“存储”有限个或无限个元素
可以转换为另一个Stream
计算通常发生在最后结果的获取(惰性计算)
惰性计算: 一个Stream转换城另外一个Stream的时候只存储转换规则,并不做实质性的计算
Stream API的特点:
Stream API提供了一套新的流式处理抽象序列
Stream API支持函数式编程 / 链式操作
Stream API 可以表示无限序列,多数情况下是惰性求值的
创建Stream
创建Stream通常有两种方法种方法:
将现有数据结构转化成Stream
Stream s = Stream.of(1, 2, 3, 4, 5);
Stream s = Arrays.stream(arr);
Stream s = aList.stream();
通过Stream.generate()方法:
// 这种方法通常表示无限序列
Stream s = Stream.generate(SuppLier s);
// 创建全体自然数的Stream
class NatualSupplier implements Supplier {
BigInteger next = BigInteger.ZERO;
@Override
public BigInteger get() {
next = next.add(BigInteger.ONE);
return next;
}
}
通过其他方法返回
Stream lines = Files.lines(Path.get(filename))
...
map方法
把一种操作运算映射到Stream的每一个元素上,从而完成一个Stream到另一个Stream的转换
map方法接受的对象是Function接口,这个接口是一个函数式接口:
Stream map(Function super T, ? extends R> mapper);
@FunctionalInterface
public interface Function {
// 将T转换为R
R apply(T t);
}
map方法的使用:
// 获取Stream里每个数的平方的集合
Stream ns = Stream.of(1, 2, 3, 4, 5);
ns.map(n -> n * n).forEach(System.out::println);
filter方法
filter方法用于过滤Stream中的元素,并用符合条件的元素生成一个新的Stream。
filter方法接受的参数是Predicate接口对象,这个接口是一个函数式接口:
Stream filter(Predicate super T>) predicate;
@FunctionInterface
public interface Predicate {
// 判断元素是否符合条件
boolean test(T t);
}
filter方法的使用:
// 获取当前Stream所有偶数的序列
Stream ns = Stream.of(1, 2, 3, 4, 5);
ns.filter(n -> n % 2 == 0).forEach(System.out::println);
reduce方法
reduce方法将一个Stream的每一个元素一次作用于BiFunction,并将结果合并。
reduce方法接受的方法是BinaryOperator接口对象。
Optional reduce(BinaryOperator accumulator);
@FuncationalInterface
public interface BinaryOperator extends BiFunction {
// Bi操作,两个输入,一个输出
T apply(T t, T u);
}
reduce的使用方法:
// 求当前Stream累乘的结果
Stream ns = Stream.of(1, 2, 3, 4, 5);
int r = ns.reduce( (x, y) -> x * y ).get();
System.out.println(r);