文章目录
- 参考文章
- 1..java8中的新特性值stream.map和reduce :
- 2.Predicate接口的使用
- foreach的使用
- 双冒号(::)(Lamda表达式中的另一种表现形式)
- 构造器引用
- 类::实例方法名的理解
(1) 参考博文1 参考博文2
(2)创建stream的方式(包含无限流和有限流) (3)strem中的中间操作和终止操作的详解,映射系列。
在其中使用Comparator.comparing进行排序:
参考博文1
函数式接口:(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
Predicate 接口是一个函数式接口,它接受一个输入参数 T,返回一个布尔值结果。
该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)。
foreach的使用
如果使用lambda表达式中调用函数;可以使用:
书写方式:
public class Test {
public String getValue1(String name) {
return "test:" + name;
}
public static String getValue2(String name) {
return "test:" + name;
}
public static void main(String[] args) {
// 默认的Lamba调用方法逻辑
Test obj = new Test();
IUser iu0 = (x) -> {
return obj.getValue1(x);
};
// 1)对象::实例方法名
IUser iu1 = (x) -> obj.getValue1(x);
// 可以写成:
IUser iu11 = obj::getValue1;
// 2)类名::静态方法名
IUser iu2 = (x) -> Test.getValue2(x);
IUser iu22 = Test::getValue2;
// 2)类名:new
Supplier<String> sup1 = () -> new String();
// 可以写成:
Supplier<String> sup2 = String::new;
Function<Integer, String[]> fun1 = (x) -> new String[x];
// 可以写成:
Function<Integer, String[]> fun2 = String[]::new;
// 2)类名::实例方法名
BiPredicate<String, String> bi1 = (x, y) -> x.equals(y);
// 可以写成:
BiPredicate<String, String> bi2 = String::equals;
}
使用实例
public class Test01 {
public void run(){
HashMap<Integer, Integer> map = new HashMap<>(16);
map.put(1,1);
map.put(2,2);
map.put(3,3);
Iterator<Map.Entry<Integer, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<Integer, Integer> next = iterator.next();
map.put(next.getKey(), next.getValue()+4);
System.out.println(next.getKey()+" "+ next.getValue());
}
System.out.println("****** ");
map.keySet().forEach(k->{
map.put(k,map.get(k)+2);
System.out.println(k+" " + map.get(k));
});
map.keySet().forEach(this::sum);
}
public static void main(String[] args) {
Test01 test01 = new Test01();
test01.run();
}
public void sum(Integer i){
System.out.println(i+2+"数字");
}
}
双冒号(:😃(Lamda表达式中的另一种表现形式)
理解:若Lambda体中的内容有方法实现了(Lambda表达式中的参数和返回值需要和方法中的参数和返回值一样 ),我们可以使用“方法引用”(可以理解为方法引用是Lambda表达式的另外一种表现形式)
主要有三种语法格式:
- 对象::实例方法名
- 类::静态方法名
- 类::实例方法名
自己的理解:
(1)Lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致。
(2)若Lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method(类::实例方法)
构造器引用
格式:
ClasName::new
注意:需要调用的构造器的参数列表要与函数式接口中抽象方法中的参数列表保持一致。
@Test
public void test(){
Supplier<Employee> sup = ()-> new Employee();
// 构造器引用和上面的代码一样的功能,此时调用的是无参的构造方法。
Supplier<Employee> sup2 = Employee::new;
}{
类::实例方法名的理解
参考文章,点击这里 这种方法引用的方式较之前两种稍微有一些不好理解,因为无论是通过类名调用静态方法还是通过对象调用实例方法这都是符合Java的语法,使用起来也比较清晰明了。那我们带着这个疑问来了解一下这个比较特殊的方法引用。
现在再看一下Student类中静态方法的定义
public static int compareStudentByScore(Student student1,Student student2){
return student1.getScore() - student2.getScore();
}
虽然这个方法在语法上没有任何问题,可以作为一个工具正常使用,但是有没有觉得其在设计上是不合适的或者是错误的。这样的方法定义放在任何一个类中都可以正常使用,而不只是从属于Student这个类,那如果要定义一个只能从属于Student类的比较方法下面这个实例方法更合适一些
public int compareByScore(Student student){
return this.getScore() - student.getScore();
}
接收一个Student对象和当前调用该方法的Student对象的分数进行比较即可。现在我们就可以使用 类名::实例方法名 这种方式的方法引用替换lambda表达式了
我的理解:必须接收一个对象,并且和类中的属性发生关系
students.sort(Student::compareByScore);
students.forEach(student -> System.out.println(student.getScore()));
这里非常奇怪,sort方法接收的lambda表达式不应该是两个参数么,为什么这个实例方法只有一个参数也满足了lambda表达式的定义(想想这个方法是谁来调用的)。这就是 类名::实例方法名 这种方法引用的特殊之处:当使用 类名::实例方法名 方法引用时,一定是lambda表达式所接收的第一个参数来调用实例方法,如果lambda表达式接收多个参数,其余的参数作为方法的参数传递进去。
结合本例来看,最初的lambda表达式是这样的
students.sort((o1, o2) -> o1.getScore() - o2.getScore());
那使用 类名::实例方法名 方法引用时,一定是o1来调用了compareByScore实例方法,并将o2作为参数传递进来进行比较。是不是就符合了compareByScore的方法定义。