流介绍
流是java API的新成员,他允许你以声明的方式处理数据集合(通过查询语句,而不是临时编写一个实现)
使用流
集合是流最容易上手的方式,Java8 中的集合支持一个新的stream方法,他会放回一个流对象(接口定义在java.util.stream.Stream)中
使用流可以完成什么事?他可以让我们以一种流水线的方法处理集合数据
像我们前面处理苹果集合时那样,可以实现一个方法来收集或处理某些数据,比如过滤颜色不是红色的苹果,收集苹果的重量列表,但是每一次都需要调用一个方法,流为我们处理这种“一系列”数据提供了一些方法,可以像工厂流水线的方法对流数据进行处理
比如要收集颜色是红色苹果的重量集合,可以想这样写
inventory.stream().filter(apple -> apple.getColor().equals("red")).map(Apple::getWeight).forEach(System.out::println);
这里先通过方法stream()生成一个流对象,再使用filter方法过滤掉颜色不是红色的苹果,接着通过map将所有颜色是红色的苹果的重量返回成一个数值流
也就是剩下苹果重量的集合,接着调用forEach方法打印剩下苹果的重量。可以读作先过滤掉颜色不是红色的苹果,接着返回所有苹果重量的集合,然后打印
如果使用上一节自定义方法实现这些操作书写格式如下:
inventory = filter(inventory,apple -> apple.getColor().equals("red"));
List<Integer> weights = map(inventory,Apple::getWeight);
forEach(weights, System.out::println);
可以看见流的可读性以及书写性都要高于自定义实现
流方法
流的方法分为两类,一类是中间操作,一类是终端操作,中间操作是对流完成操作之后还会返回一个流对象,而终端操作的返回结果是任何不是流的值,前面的filter,map就是中间操作,forEach就是终端操作
使用流方法对苹果库存进行操作
使用forEach打印数据
inventory.stream().forEach(System.out::println);
筛选颜色为红色的苹果
inventory.stream().filter(apple -> apple.getColor().equals("red")).forEach(System.out::println);
对苹果颜色进行排序,如果个颜色相同,根据重量大小由小到大排序
Comparator<Apple> colorSort = (a1,a2) -> a1.getColor().compareTo(a2.getColor()); Comparator<Apple> weightSort = (a1,a2) -> a1.getWeight() - a2.getWeight(); inventory.stream().sorted(colorSort.thenComparing(weightSort)).forEach(System.out::println);
去除颜色和重量相同的苹果
inventory.stream().distinct().forEach(System.out::println);
只获取前三个苹果
inventory.stream().limit(3).forEach(System.out::println);
跳过前面两个苹果,只获取后面三个
inventory.stream().skip(2).forEach(System.out::println);
不要第一个苹果也不要最后一个苹果
inventory.stream().skip(1).limit(inventory.size() - 2).forEach(System.out::println);
将所有苹果的重量加10
inventory.stream().peek(apple -> apple.setWeight(apple.getWeight() + 10)).forEach(System.out::println);
查看有没有重量是20,颜色是红色的苹果
System.out.println(inventory.stream().anyMatch(apple -> apple.getColor().equals("red")));
查看是不是所有苹果的重量是20,颜色是红色
System.out.println(inventory.stream().allMatch(apple -> apple.getColor().equals("red")));
查看是不是没有苹果是红色的
System.out.println(inventory.stream().noneMatch(apple -> apple.getColor().equals("red")));
查看第一个苹果
System.out.println(inventory.stream().findFirst());
返回苹果的总重量
System.out.println(inventory.stream().map(Apple::getWeight).reduce(0, (a,b) -> (a + b)));
返回苹果的最小重量
System.out.println(inventory.stream().map(Apple::getWeight).min((n1,n2) -> n1 - n2));
返回苹果的最大重量
System.out.println(inventory.stream().map(Apple::getWeight).max((n1,n2) -> n1 - n2));
流的终端操作
方法 作用
boolean allMatch(Predicate<? super T> predicate) 如果流对象都可以匹配谓词,返回true,否则返回false
boolean anyMatch(Predicate<? super T> predicate) 如果流对象中有一个或多个匹配谓词,返回true,否则返回false
boolean noneMatch(Predicate<? super T> predicate) 如果流对象中任何一个都没有匹配谓词,返回true,否则返回false
Optional<T> max(Comparator<? super T> comparator) 自定义比较方法,返回流对象中比较方法比较出来的最大值
Oprional<T> min(Comparator<? super T> comparator) 自定义比较方法,返回流对象中比较方法比较出来的最小值
Optional<T> findAny() 未知
Optional<T> findFirst() 返回流对象中的第一个值
long count() 返回流中数据的个数
<R,A> R collect(Collecotr<? super T,A,R> collector) 未知
<R> R collecot(Supplier<R> supplier,BiConsumer<R,? super T> accumulator,BiConsumer<R,R> combiner) 未知
void forEach(Consumer<? super T> action) 未知
void forEachOrDered(Consumer<? super T> action) 未知
Oprional<T> reduce<T identity,BinaryOperator<T> accumulator) 未知
<U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner) 未知
Object[] toArray() 未知
<A> A[] toArray(IntFunction<A[]> generator) 未知
流的中间操作
方法 作用
distinct() 去重,流中的对象需要实现equlas方法
filter(Predicate<? super T> predicate) 按照规则过滤,满足规则的留下,不满足的去掉
limit(long maxSize) 返回数据的最大个数,10表示返回10个数据,5表示返回5个
map(Function<? super T,? extends R> mapper) 将每个流对象作为函数的参数,并且将返回值填充流对象
flatMap(Function<? super T,? extends Stream<? extends R>> mapper) 将每个流对象作为函数的参数,但是只返回一个流对象
peek(Consumer<? super T> action) 可以在流处理时对每个流数据进行操作,并返回Stream对象
skip(long n) 跳过n个数据,n等于10,表示跳过前面10个数据,和limit方法一起使用效果更好
sorted() 默认排序,排序类需要实现默认排序接口
sorted(Comparator<? super T> comparator) 使用自定义排序对流数据进行排序
值得注意的是flatMap方法,这个方法和map方法不同,map方法会将每一个流对象都作用于Function<? super T,? extends R>返回一个R对象,flatMap方法也会将所有的流对象作用于Function的方法,但是只会返回一个`流对象`,这个方法可以用作一个流中的对象的属性是集合,并且需要将所有流对象为集合的属性收集起来的情况,比如收集几个字符串中所有不重复的字符。