①:函数式接口(支持Lamda):(有且只有一个抽象方法的接口)
列举几个常用的
public static void main(String[] args) {
// 一个参数,一个返回值
Function<String, String> dd = i -> {
String ii = "My Name is";
return ii + i;
};
// 一个参数,无返回值
Consumer<String> ee = i -> System.out.println(i);
// 一个参数,返回布尔类型
Predicate<String> ff = i -> i.length() > 10;
// 没有参数,一个返回值
Supplier<String> gg = () -> "yes";
System.out.println(dd.apply("wenwenYU"));
ee.accept("CAI CAI WO SHI SHUI");
System.out.println(ff.test("1234567891234"));
System.out.println(gg.get());
}
个人理解:函数式接口更像是把代码逻辑块作为方法的参数。
问一个问题:函数式接口的好处是什么?可用Lamda表达式写函数式接口的好处是什么?
举一个例子:现在一个list要筛选出来code是988的
不用lamda表达式↓
List<Person> personList = new ArrayList<>();
personList.add(new Person("于问问", "988"));
personList.add(new Person("苗问问", "988"));
personList.add(new Person("李问问", "777"));
personList.stream().filter(new Predicate<Person>() {
@Override
public boolean test(Person person) {
return person.getCode().equals("988");
}
}).collect(Collectors.toList());
首先stream几乎所有的方法需要的参数都是函数式接口, 就得自己new接口 匿名函数去回调方法
,首先看着就乱,其次new一次是不是就得在栈中开辟一点空间出来呢
②:Lamda表达式(只有函数式接口才能支持Lamda表达式)
用lamda表达式:
filter方法需要的是Predicate函数式接口(传进一个参数,返回一个boolean)
由于函数式接口只有一个抽象方法,虚拟机自己就判断去执行那个方法而不去要显性的去显示调方法名
实际上person.getCode().equals("988")这段逻辑,就是代替了重写的test方法块了。
结论:Lamda表达式更加简洁
personList.stream().filter(person -> person.getCode().equals("988")).collect(Collectors.toList());
③:StreamAPI
一个Stream流操作:可以有N个中间操作,但只能有且只有一个终止操作。
场景1:List<Person>变成Map<code,name>
一个List<Person>
Person有两个属性String name,String code
现在要变成map<String,String> key为code,value为name
public static void main(String[] args) {
List<Person> personList =new ArrayList<>();
personList.add(new Person("于问问","988"));
personList.add(new Person("苗问问","988"));
personList.add(new Person("李问问","777"));
Map<String, String> personMap = personList.stream()
.collect(
Collectors.toMap(Person::getCode, Person::getName)
);
}
这样会不会有问题?答案是会有问题的。
Map的key值不能重复,现在于问问和苗问问的code号都是988
遇到这种情况转Map时就必须得有取舍了,苗问问和于问问只能留一个,那就留苗问问吧
Map<String, String> personMap = personList.stream()
.collect(Collectors.toMap(Person::getCode, Person::getName, (v1, v2) -> v2));
(v1,v2)->v2的意思也就是前者和后者传进来,只留后者
场景2:以code分组作为map的key,value是一个list<person>,有重复的code就加到list里面
Map<String, List<Person>> collect = personList.stream().collect(Collectors.groupingBy(Person::getCode));