Jdk新特性之方法引用

1、方法引用的使用场景

我们用Lambda表达式来实现匿名方法。但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,在这种情况下,我们倾向于通过方法名来调用它,而Lambda表达式可以帮助我们实现这一要求,它使得Lambda在调用那些已经拥有方法名的方法的代码更简洁、更容易理解。方法引用可以理解为Lambda表达式的另外一种表现形式。

2、方法引用的分类

类型语法对应的Lambda表达式
静态方法引用类名::staticMethod(args) -> 类名.staticMethod(args)
实例方法引用inst::instMethod(args) -> inst.instMethod(args)
对象方法引用类名::instMethod(inst,args) ->inst(实例对象)类名.instMethod(args)
构建方法引用类名::new(args) -> new 类名(args)

能用方法引用一定可以用lambda表达式,但不是所有lambda表达式都可以使用方法引用;

3、方法引用举例

3.1 静态方法引用

有一个Person类,如下所示:(set集合可以通过在实体类中实现compareble接口重写比较器即可,list需要在新建的队形加入对应比较器)

@Data//实体类
public class Person {

    private String name;

    private Integer age;
    //比较两个Person对象的年龄是否一致。
    public static int compareByAge(Person a, Person b) {
        return a.age.compareTo(b.age);
    }
}

现假设,一个部门有10人,把他们存放在一个数组中,并按年龄排序,通常我们可以自己写一个比较器,代码如下:

Person[] rosterAsArray = new Person[10];
// 添加数组元素省略

class PersonAgeComparator implements Comparator<Person> {
    public int compare(Person a, Person b) {
        return a.getAge().compareTo(b.getAge());
    }
}

Arrays.sort(rosterAsArray, new PersonAgeComparator());

Arrays.sort的声明为:public static void sort(T[] a, Comparator<? super T> c),比较器参数Comparator为一个函数式接口,利用上一节Lambda表达式所学知识,可以改写为以下代码:

Person[] rosterAsArray = new Person[10];
// 添加数组元素省略
Arrays.sort(rosterAsArray, (a,b) -> a.getAge().compareTo(b.getAge()));

然而,你会发现,Person类中已经有了一个静态方法的比较器:compareByAge,因此,我们改用Person类已经提供的比较器:

Person[] rosterAsArray = new Person[10];
// 添加数组元素省略
Arrays.sort(rosterAsArray, (a,b) -> Person.compareByAge(a,b));

以上代码,因为Lambda表达式调用了一个已经存在的静态方法,根据我们第2节表格中的语法,上面的代码可以最终改写成静态方法引用:

Person[] rosterAsArray = new Person[30];
// 添加数组元素省略
Arrays.sort(rosterAsArray, Person::compareByAge);

下面这个例子更简单:

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(82,22,34,50,9);//integer数组 进行排序。
//        Collections.sort(list,(o1,o2)->o1.compareTo(o2));//int compare(T o1, T o2);
//        Collections.sort(list,(o1,o2)->Integer.compare(o1,o2));
        Collections.sort(list,Integer::compare);
        System.out.println(list);
    }

对一个Integer列表进行排序,因为Integer中已经存在静态的比较方法compare(),因此可以直接用静态方法引用的方式来调用 ,运行结果为:

[9, 22, 34, 50, 82]

3.2 实例方法引用

实例方法引用,顾名思义就是调用已经存在的实例的方法,与静态方法引用不同的是类要先实例化,静态方法引用类无需实例化,直接用类名去调用。

@Data
@AllArgsConstructor
@NoArgsConstructor
class User {
    private String name;
    private Integer age;
}

public class TestInstanceReference {

    public static void main(String[] args) {
        User user = new User("峰峰",32);
        Supplier<String> supplier = () -> user.getName();//供给型
        System.out.println("Lambda表达式输出结果:" + supplier.get());

        Supplier<String> supplier2 = user::getName;
        System.out.println("实例方法引用输出结果:" + supplier2.get());
    }
}

输出结果:

Lambda表达式输出结果:峰峰
实例方法引用输出结果:峰峰

3.3 对象方法引用

若Lambda参数列表中的第一个**参数是实例方法(对象)的参数调用者,**而第二个参数是实例方法的参数时,可以使用对象方法引用。

String的equals()方法:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
public static void main(String[] args) {

   BiPredicate<String,String> bp = (x, y) -> x.equals(y);
   BiPredicate<String,String> bp1 = String::equals;

   boolean test = bp1.test("xy", "xx");
   System.out.println(test);
}//==================例子贰========================
    public static void main(String[] args) {
        //可以接受两个参数,返回值为boolean
        // boolean test(T t, U u);
//        BiPredicate<String,String> predicate=(t,u)->t.equals(u);
        BiPredicate<String,String> predicate=String::equals;
        System.out.println(predicate.test("hah", "ha"));
    }

代表了一个两个参数的boolean值方法

BiPredicate的test()方法接受两个参数,x和y,具体实现为x.equals(y),满足Lambda参数列表中的第一个参数是实例方法的参数调用者,而第二个参数是实例方法的参数,因此可以使用对象方法引用。

3.4 构造方法引用

注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致。

如:要获取一个空的User列表:

Supplier<List<User>> userSupplier = () -> new ArrayList<>();
List<User> user = userSupplier.get();
Supplier<List<User>> userSupplier2 = ArrayList<User>::new;  // 构造方法引用写法
List<User> user2 = userSupplier.get();
    public static void main(String[] args) {
        //Supplier<User> p=()->new User(); //T get();
//        Supplier<User> p=User::new; //T get();

//        System.out.println(p.get());
// * @param <T> the type of the first argument to the function
// * @param <U> the type of the second argument to the function
// * @param <R> the type of the result of the function
   //    BiFunction<Integer,String,User> f=(t,u)->new User(t,u);
        BiFunction<Integer,String,User> f=User::new;
        System.out.println(f.apply(18,"龙龙"));
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值