方法引用
一种简化代码的语法糖,用于直接引用已经存在的方法
是lambda表达式的一种简化形式,用于方法的参数传递
可以简化代码,提高代码的可读性和可维护性
当调用接口的抽象方法时,实际调用的是被引用的方法
方法引用的形式
1,静态方法引用:
类名::静态方法名
引用类中的静态方法,当某个lambda表达式的功能和某个类中的静态方法功能一致,直接通过类名引用方法就能将其替代
@FunctionalInterface
public interface ImTheOne {//函数式接口
String handleString(String a, String b);
}
class OneClass {//需要被引用的方法
public static String concatString(String a, String b) {
return a + b;//功能和需要写的lambda表达式一致
}
}
public class Test {
public static void main(String[] args) {
ImTheOne theOne = OneClass::concatString;//静态方法引用 类名::方法名
String result = theOne.handleString("abc", "def");
System.out.println(result);
//相当于以下效果,直接把类的静态方法写在Lambda体里
ImTheOne theOne2 = (a, b) -> OneClass.concatString(a, b);
String result2 = theOne2.handleString("123", "456");
System.out.println(result2);
}
}
注意:引用方法的参数列表必须和待重写的抽象方法一致
2,实例方法引用:
对象::实例方法名
引用对象的实例方法,通过对象实例来调用方法,当lambda表达式的功能和某个对象的实例方法功能一致,可以用实例方法引用替换lambda表达式
@FunctionalInterface
public interface ImTheOne {//函数式接口
String handleString(String a, String b);
}
class OneClass {
public String concatString(String a, String b) {
return a + b;
}
}
public class Test {
public static void main(String[] args) {
OneClass oneClass = new OneClass();
ImTheOne theOne = oneClass::concatString;//实例方法引用 对象::方法名
String result = theOne.handleString("abc", "def");
System.out.println(result);
//相当于以下效果
OneClass oneClass2 = new OneClass();
ImTheOne theOne2 = (a, b) -> oneClass2.concatString(a, b);
String result2 = theOne2.handleString("123", "456");
System.out.println(result2);
}
}
注意:
这里的对象可以是父类对象即可以写成super::方法()的形式,前提是父类存在这个方法
使用super进行父类的方法引用
使用this进行本类方法引用
3,构造方法引用:
类名::new
表示一个函数式接口中的唯一抽象方法引用了一个类的参数相同的构造方法
代码如下
@FunctionalInterface
public interface ImTheOne {
TargetClass getTargetClass(String a);
}
class TargetClass {
String oneString;
public TargetClass() {
oneString = "default";
}
public TargetClass(String a) {
oneString = a;
}
}
public class Test {
public static void main(String[] args) {
ImTheOne imTheOne = TargetClass::new;
TargetClass targetClass = imTheOne.getTargetClass("abc");
System.out.println(targetClass.oneString);
//相当于以下效果
ImTheOne imTheOne2 = (a) -> new TargetClass("abc");
TargetClass targetClass2 = imTheOne2.getTargetClass("123");
System.out.println(targetClass2.oneString);
}
}
4,引用类的实例方法
类名::成员方法
当接口中的抽象方法的参数为(obj,x,y…)形式
并且引用的效果为obj.fun(x,y)格式时
可以使用这种类名引用成员方法的格式进行应用
讲的有点抽象看下代码
public interface MyString {
String mySubString(String s, int x, int y);
}
参数第一项为substring方法的调用者,后面两项为substring的参数
public class MyStringDemo {
public static void main(String[] args) {
//Lambda表达式
useMyString((s, x, y) -> s.substring(x, y));
//引用类的实例方法
useMyString(String::substring);
}
private static void useMyString(MyString my) {
String s = my.mySubString("HelloWorld", 2, 5);
System.out.println(s);
}
}
可以转为成String::substring的形式
方法引用的使用场景
1,lambda表达式中仅仅调用一个已存在的方法时,可以使用方法引用来简化代码
2,当使用lambda表达式实现函数式接口时,如果已经有现成的方法可以使用,可以直接使用方法引用来代替表达式
3,方法引用可以提高代码的可读性和简洁性,尤其是对于一些复杂的逻辑
Stream流
jdk8中引入的一种新的数据处理方式,提供了一种函数式编程的方式来操作数据结构
本质是对数据集合进行一系列的操作包括过滤,映射,排序,聚合等,通过Stream流,可以更加简洁高效地对数据进行处理
Stream流是一段地址
Stream流能解决的问题
1,过滤:可以通过使用Stream流的filter()方法来筛选符合条件的元素
2,映射:可以通过使用Stream流的map()方法将一个元素转换成另一个元素
3,排序:可以通过使用Stream流的sorted()方法对元素进行排序
4,收集:可以通过使用Stream流collect()方法将流中的元素收集到一个新的集合中
Stream流的使用
可以分为三个阶段
获取功能
对于单列集合可以用集合的stream()方法获取Stream流对象
Stream<String> stream1 = list.stream();
对于双列集合可以用集合的entrySet().stream()方法获取Stream流对象
双列集合->单列集合->Stream流
Stream<Map.Entry<String, Integer>> stream2 = map.entrySet().stream();
对于数组需要用到Arrays.stream()方法获取Stream流对象
对于多个数据可以用Stream.of(int 1,int2…)方法获取Stream流对象
中间功能
Stream流的中间方法
可以被串联使用,形成一系列操作链,最终通过调用终端方法,才能触发流操作的执行,产生最终结果
终结功能
用来产生结果或者副结果的方法,一旦调用终结方法,流就不能再被使用
eg:forEach,toArray,collect
终结方法是流操作的最后一步
一旦调用流就不能在使用,否则会出现illegalStateException异常
可以把数据收集到新的集合或者数组中
可以对流中的元素进行聚合操作,如求max,min,avg
Stream流的收集方法
为了将流操作的结果转回到集合或者数组中去返回