filter:主要是流的过滤
可以通过filter 方法将一个流转换成另一个子集流。查看方法签名:
Stream<T> filter(Predicate<? super T> predicate);
该接口接收一个Predicate 函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。
复习Predicate接口
此前我们已经学习过java.util.stream.Predicate 函数式接口,其中唯一的抽象方法为:
boolean test(T t);
可以看出该方法有参数,有返回值,该方法将会产生一个boolean值结果,代表指定的条件是否满足。如果结果为true,那么Stream流的filter 方法
将会留用元素;如果结果为false,那么filter 方法将会舍弃元素。
基本使用
Stream流中的filter 方法基本使用的代码如:
package com.learn.demo02.Stream;
import java.util.stream.Stream;
/*
Stream流中的常用方法_filter:用于对Stream流中的数据进行过滤
Stream<T> filter(Predicate<? super T> predicate);
filter方法的参数Predicate是一个函数式接口,所以可以传递Lambda表达式,对数据进行过滤
Predicate中的抽象方法:
boolean test(T t);
*/
public class Demo03Stream_filter {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
//对Stream流中的元素进行过滤,只要姓张的人
Stream<String> stream2 = stream.filter((String name)->{return name.startsWith("张");});
//遍历stream2流
stream2.forEach(name-> System.out.println(name));
/*
Stream流属于管道流,只能被消费(使用)一次
第一个Stream流调用完毕方法,数据就会流转到下一个Stream上
而这时第一个Stream流已经使用完毕,就会关闭了
所以第一个Stream流就不能再调用方法了
IllegalStateException: stream has already been operated upon or closed
*/
//遍历stream流
stream.forEach(name-> System.out.println(name));
}
}
这里对<? super T>和<? extends T>进行说明一下
java的一个设计理念是,与泛型相关的异常最好是在编译期间就被发现,因此设计了extends与super这两种方式。
具体来说,List<? extends T>表示该集合中存在的都是类型T的子类,包括T自己。
而List<? super T>表示该集合中存的都是类型T的父类,包括T自己。
List<? extends T>如果去添加元素的时候,因为list中存放的其实是T的一种子类,如果我们去添加元素,其实不知道到底应该添加T的哪个子类,这个时候桥接方法在进行强转的时候会出错。但是如果是从集合中将元素取出来,我们可以知道取出来的元素肯定是T类型。所以? extends T这种方式可以取元素而不能添加,这个叫get原则。
List<? super T>因为存的都是类型T的父类,所以如果去添加T类或者T类子类的元素,肯定是可以的。但是如果将元素取出来,则不知道到底是什么类型,所以? super T可以添加元素但是没法取出来,这个叫put原则。
public static void test() {
List<? extends Number> l1 = new ArrayList<>();
// l1.add(1); 会报错
List<? super Number> l2 = new ArrayList<>();
// Number n = l2.get(1); 会报错
l2.add(1);
l2.add(2);
l2.add(0.11);
for(Object n: l2) {
System.out.println(n.toString());
}
}