双冒号运算操作符是类方法的句柄,是lambda表达式的一种简写。
1.双冒号(::)运算符
在Java 8中,双冒号(::)运算符称为方法引用。方法引用不执行任何操作,只是对现有方法的另一种调用。使用方法引用,可以获得更好的可读性。
大家平时最早接触双冒号方法引用的地方,就是把集合转换为stream流后的lambda表达式的遍历方式,如下:
List<String> list = Arrays.asList("北京","上海","广州","深圳");
list.forEach(System.out::println);
这里要特别强调一下,双冒号(::)运算符使用有两个大的前提条件,否则不适合使用方法引用。
双冒号(::)运算符有以下四种方法引用:
下来分别探讨这四种方法引用使用方式:
2.静态方法
将String列表转换为Integers列表,该方法引用静态方法Integer::parseInt。
List<String> list = Arrays.asList("1", "2", "3");
// method reference
List<Integer> list1 = list.stream()
.map(Integer::parseInt).collect(Collectors.toList());
list1.forEach(System.out::println);
3.引用特定对象的实例方法
Students按成绩降序排序列表。我们可以参考compareBySalary特定对象的实例方法ComparatorProvider。
class ComparatorProvider {
public int compareByAge(Students s1, Students s2) {
return s1.getAge().compareTo(s2.getAge());
}
public int compareByName(Students s1, Students s2) {
return s1.getName().compareTo(s2.getName());
}
public int compareByScore(Students s1, Students s2) {
return s2.getScore().compareTo(s1.getScore());
}
}
class Students {
String name;
Integer age;
Integer score;
public Students() {
}
public Students(String name, Integer age, Integer score) {
this.name = name;
this.age = age;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
@Override
public String toString() {
return "Students{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
public class Java8MethodReference2 {
public static void main(String[] args) {
List<Students> list = Arrays.asList(
new Students("张三", 18, 98),
new Students("李四", 19, 89),
new Students("王五", 25, 78),
new Students("赵六", 21, 90));
ComparatorProvider provider = new ComparatorProvider();
// method reference
list.sort(provider::compareByScore);
list.forEach(System.out::println);
}
}
运行结果:
Students{name='张三', age=18, score=98}
Students{name='赵六', age=21, score=90}
Students{name='李四', age=19, score=89}
Students{name='王五', age=25, score=78}
4.引用特定类型的任意对象的实例方法
引用String类型的任意对象的compareToIgnoreCase方法实现忽略大小写排序。
String[] arr = { "Barbara", "james", "Mary", "John",
"Patricia", "robert", "michael", "Linda" };
Arrays.sort(arr, String::compareToIgnoreCase);
List<String> list = Arrays.asList(arr);
list.forEach(System.out::println);
运行结果:
Barbara
james
John
Linda
Mary
michael
Patricia
robert
5.引用类的构造方法
在第一个例子中,将String列表转换为Integers列表,我们也可以使用Integer类的构造方法。
List<String> list = Arrays.asList("1", "2", "3");
// method reference
List<Integer> list1 = list.stream()
.map(Integer::new).collect(Collectors.toList());
list1.forEach(System.out::println);
6.双冒号(::)运算符本质lambda表达式的一种简写
我们知道只有一个抽象方法的接口称为函数式接口,实现函数式接口通常都是使用lambda表达式来实现。 例如:
interface MyConvert{
int parseToInteger(String s);
}
public class Java8MethodReference4 {
public static void main(String[] args) {
//1.lambda表达式实现方法
MyConvert convert = (obj)->{
return Integer.parseInt(obj);
};
Integer v1 = convert.parseToInteger("111");
System.out.println(v1);
//2.双冒号方法引用的简写方式
convert = Integer::parseInt;
Integer v2 = convert.parseToInteger("222");
System.out.println(v2);
}
}
小结:
Java中双冒号(::)运算操作符被称为方法引用,本质是lambda表达式的一种简写。
双冒号(::)运算符使用有两个大的前提条件,否则不适合使用方法引用。 - 满足lambda的相关条件,即(::)可以使用lambda表达式表示;(通常是实现函数式接口) - 只能有一条语句,且必须是调用方法的语句。
双冒号(::)运算符有以下四种方法引用: