JAVASE:方法引用

概述

方法引用:把已经存在的方法拿过来用,当作函数式接口中抽象方法的方法体
方法引用符: ::

注意:

1、引用出处必须是函数式接口
2、被引用的方法必须存在
3、被引用方法的形参和返回值需要跟抽象方法一致
4、被引用的方法的功能要满足当前需求,这个方法应该要与匿名内部类一致(形参类型、返回值)

eg:

public class ArrayTest {
    public static void main(String[] args) {
        Integer[] arr = {3, 5, 4, 1, 6, 2};
        Arrays.sort(arr, ArrayTest::subtraction);
        System.out.println(Arrays.toString(arr));
    }
    public static int subtraction(int num1, int num2){
        return num2 - num1;
    }
}

引用静态方法

格式:类名::静态方法
eg:Integer::parseInt
练习:把集合中的"1",“2”,“3”,“4”,"5"变为int类型:

public class ArrayTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "1","2","3","4","5");
        List<Integer> list1 = list.stream().map(Integer::parseInt).collect(Collectors.toList());
        System.out.println(list1);
    }
}

引用成员方法

格式:对象::成员方法

  1. 其他类:其他类对象::方法名
  2. 本类:this::方法名
  3. 父类:super::方法名

引用其他类的成员方法

格式:其他类对象::方法名
练习:将集合中的的名字进行过滤,留下以"张"开头的,并且名字是3个字的。

可以先写匿名内部类:

	list.stream().filter(new Predicate<String>() {
        @Override
        public boolean test(String s) {
            return s.length()==3&&s.startsWith("张");
        }
    }).forEach(s-> System.out.println(s));

观察这个匿名内部类重写方法中的形参为String类型,返回值为boolean类型的,但是java并没专门提供这样的方法,所以不能直接使用,因此我们可以新建一个类:

public class StringOperation {
    public boolean stringJudge(String s){
        return s.startsWith("张")&&s.length()==3;
    }
}

现在就可以引用这个成员方法了,但是需要注意,这里的方法不是静态方法,所以需要用对象调用成员方法,不是直接用类来调用的,需要创建这个对象出来:

list.stream().filter(new StringOperation()::stringJudge).forEach(s-> System.out.println(s));

引用本类和父类成员方法

注意:引用处不能是静态方法,因为在静态方法中,没有this和super
引用本类:this::方法名
引用父类:super::方法名

引用构造方法

格式:类型::new
eg:Student::new
练习:在集合中存储姓名和年龄,将数据封装为Student对象并收集到List集合中。
先试用匿名内部类编写代码:

public class demo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌,15", "吗喽,13", "张三丰,100", "张良,35");
        List<Student> newList = list.stream().map(new Function<String, Student>() {
            @Override
            public Student apply(String s) {
                return new Student(s.split(",")[0], Integer.parseInt(s.split(",")[1]));
            }
        }).collect(Collectors.toList());
        System.out.println(newList);
    }
}

形参是String,返回值为Student类型,所以Student中需要专门有一个形参为String类型的构造方法,这种构造方式和一般的方式还是有点不一样的:

public student(string s){
    this.name = s.split( regex:",")[0];
    this.age = Integer.parseInt(s.split( regex:",")[1]);
}

List<Student> newList = list.stream().map(Student::new).collect(Collectors.toList());

其他调用方式

使用类名引用成员方法

格式:类名::成员方法
eg:String::substring
抽象方法形参的详解:
第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法
在 Stream 流当中,第一个参数一般都表示流里面的每一个数据。
假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用 String 这个类中的方法
第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法
局限性:
不能引用所有类中的成员方法。
是跟抽象方法的第一个参数有关,这个参数是什么类型的,那么就只能引用这个类中的方法。
练习:对集合中的一些字符串变成大写并输出:

	public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "aaa", "bbb", "ccc");
        List<String> newList = list.stream().map(String::toUpperCase).collect(Collectors.toList());
        System.out.println(newList);
    }

引用数组的构造方法

格式:数据类型[]::new
eg:int[]::new
练习:集合中存储一些整数,收集到数组中去。
细节:
数组的类型,需要跟流中数据的类型保持一致。
首先编写一下匿名内部类:

	public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1, 2, 3, 4, 5);
        Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {
            @Override
            public Integer[] apply(int value) {
                //System.out.println(value);
                return new Integer[value];
            }
        });
        System.out.println(Arrays.toString(arr));
    }

注意,IntFunction中的泛型装的是要处理的数据类型,这里放了一堆的整数可以当作是Integer[],注意不能写int不然会报错。
apply中的value不是指元素值,而是这个数组的长度,因此需要返回Integer[value]。

因此转换为方法引用的代码如下所示,由于上面的形参必须是Integer[]类型的,所以这边也不能用int[]

	public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1, 2, 3, 4, 5);
        Integer[] arr = list.stream().toArray(Integer[]::new);
        System.out.println(Arrays.toString(arr));
    }

练习

1.集合中存储一些字符串的数据,比如:张三,23。
收集到 Student 类型的数组当中

public Student(String s){
        this.name=s.split(",")[0];
        this.age=Integer.parseInt(s.split(",")[1]);
    }
public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌,15","周芷若,14","赵,13","张强,20","张三丰,100","张翠山,40","张良,35","王二麻子,37");
        Student[] array = list.stream()
                .map(Student::new)
                .toArray(Student[]::new);
        System.out.println(Arrays.toString(array));
    }

2.需求:
创建集合添加学生对象
学生对象属性:name,age
要求:
获取姓名并放到数组当中
使用方法引用完成
技巧:

  1. 现在有没有一个方法符合我当前的需求
  2. 如果有这样的方法,这个方法是否满足引用的规则
    静态方法:类名::方法名
    成员方法:对象::方法名 类名::方法名
    构造方法:类名::new 数据类型::new
public static void main(String[] args) {
        ArrayList<Student> list=new ArrayList<>();
        list.add(new Student("zhangsan",23));
        list.add(new Student("lisi",24));
        String[] array = list.stream()
                .map(Student::getName)
                .toArray(String[]::new);
        System.out.println(Arrays.toString(array));
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值