Day35.Java 8新特性: Lambda表达式、函数式接口、Java内置四大核心函数式接口、方法引用、构造器|数组引用

目录

Java8新特性

函数式接口 (Single Abstract Method)

四大内置函数式接口

Lambda表达式

函数式(Functional)接口

Java内置四大核心函数式接口

方法引用

构造器引用、数组引用


Java8新特性

函数式接口 (Single Abstract Method)

函数式编程:强调做什么,而不是以什么形式做---> 结果导向

函数式接口(SAM):只有一个抽象方法的接口

曾经学习过的函数式接口:Runnable Comparator

@FunctionalInterface :判断是否为函数式接口

@FunctionalInterface
public interface Function {
    void MySAM();
}

四大内置函数式接口

java.util.function 包下

消费型接口

消费型接口:有形参,但是返回值类型是void (接收数据,不返回数据。)

接口名抽象方法描述
Consumer<T>void accept(T t)接收一个对象用于完成功能
BiConsumer<T,U>void accept(T t, U u)接收两个对象用于完成功能
DoubleConsumervoid accept(double value)接收一个double值
IntConsumervoid accept(int value)接收一个int值
LongConsumervoid accept(long value)接收一个long值
ObjDoubleConsumer<T>void accept(T t, double value)接收一个对象和一个double值
ObjIntConsumer<T>void accept(T t, int value)接收一个对象和一个int值
ObjLongConsumer<T>void accept(T t, long value)接收一个对象和一个long值

供给型接口

这类接口的抽象方法特点:无参,但是有返回值 (不接受数据,返回数据)

接口名抽象方法描述
Supplier<T>T get()返回一个对象
BooleanSupplierboolean getAsBoolean()返回一个boolean值
DoubleSupplierdouble getAsDouble()返回一个double值
IntSupplierint getAsInt()返回一个int值
LongSupplierlong getAsLong()返回一个long值

判断型接口

这里接口的抽象方法特点:有参,但是返回值类型是boolean结果。

接口名抽象方法描述
Predicate<T>boolean test(T t)接收一个对象
BiPredicate<T,U>boolean test(T t, U u)接收两个对象
DoublePredicateboolean test(double value)接收一个double值
IntPredicateboolean test(int value)接收一个int值
LongPredicateboolean test(long value)接收一个long值

功能型接口

这类接口的抽象方法特点:既有参数又有返回值

接口名抽象方法描述
Function<T,R>R apply(T t)接收一个T类型对象,返回一个R类型对象结果
UnaryOperator<T>T apply(T t)接收一个T类型对象,返回一个T类型对象结果
DoubleFunction<R>R apply(double value)接收一个double值,返回一个R类型对象
IntFunction<R>R apply(int value)接收一个int值,返回一个R类型对象
LongFunction<R>R apply(long value)接收一个long值,返回一个R类型对象
ToDoubleFunction<T>double applyAsDouble(T value)接收一个T类型对象,返回一个double
ToIntFunction<T>int applyAsInt(T value)接收一个T类型对象,返回一个int
ToLongFunction<T>long applyAsLong(T value)接收一个T类型对象,返回一个long
DoubleToIntFunctionint applyAsInt(double value)接收一个double值,返回一个int结果
DoubleToLongFunctionlong applyAsLong(double value)接收一个double值,返回一个long结果
IntToDoubleFunctiondouble applyAsDouble(int value)接收一个int值,返回一个double结果
IntToLongFunctionlong applyAsLong(int value)接收一个int值,返回一个long结果
LongToDoubleFunctiondouble applyAsDouble(long value)接收一个long值,返回一个double结果
LongToIntFunctionint applyAsInt(long value)接收一个long值,返回一个int结果
DoubleUnaryOperatordouble applyAsDouble(double operand)接收一个double值,返回一个double
IntUnaryOperatorint applyAsInt(int operand)接收一个int值,返回一个int结果
LongUnaryOperatorlong applyAsLong(long operand)接收一个long值,返回一个long结果
BiFunction<T,U,R>R apply(T t, U u)接收一个T类型和一个U类型对象,返回一个R类型对象结果
BinaryOperator<T>T apply(T t, T u)接收两个T类型对象,返回一个T类型对象结果
ToDoubleBiFunction<T,U>double applyAsDouble(T t, U u)接收一个T类型和一个U类型对象,返回一个double
ToIntBiFunction<T,U>int applyAsInt(T t, U u)接收一个T类型和一个U类型对象,返回一个int
ToLongBiFunction<T,U>long applyAsLong(T t, U u)接收一个T类型和一个U类型对象,返回一个long
DoubleBinaryOperatordouble applyAsDouble(double left, double right)接收两个double值,返回一个double结果
IntBinaryOperatorint applyAsInt(int left, int right)接收两个int值,返回一个int结果
LongBinaryOperatorlong applyAsLong(long left, long right)接收两个long值,返回一个long结果

系统内置的四个函数式接口 功能展示 

//系统内置的四个函数式接口 功能展示
public class SystemTest {
    @Test
    public void test02(){
        //消费型  Consumer<T>
        //遍历Map集合
        Map<Integer,String> map = new HashMap<>();

        map.put(1, "张三");
        map.put(2, "李四");
        map.put(3, "王五");
        map.put(4, "赵六");

        map.forEach(new BiConsumer<Integer, String>() {
            @Override
            public void accept(Integer key, String value) {
                System.out.println(key+" ---> "+value);
            }
        });

        System.out.println("---------------------");
        //()->{}

        map.forEach((k,v)-> System.out.println(k+" <===> "+v));
    }
    @Test
    public void test03(){
        //供给型接口 Supplier<T>
        Supplier<String> s1 = new Supplier<String>() {
            @Override
            public String get() {
                return "嬴政";
            }
        };

        String ele = s1.get();
        System.out.println("ele = " + ele);
        System.out.println("-----------------");
        //()->{}
        Supplier<String> s2 = ()->"嬴政";

        String s = s2.get();
        System.out.println("s = " + s);
    }
     @Test
    public void test9(){
        //断定 Predicate
        //去掉不及格的同学  
        List<Student> li = new ArrayList<>();
        li.add(new Student(60));
        li.add(new Student(54));
        li.add(new Student(37));
        li.add(new Student(96));
        li.add(new Student(75));

        li.removeIf(new Predicate<Student>() {
            @Override
            public boolean test(Student student) {
                return student.getScore()<60;
            }
        });
        System.out.println("-----------------");
        li.removeIf(s -> s.getScore()<60);
        //遍历
        li.forEach(s -> System.out.println(s));
    }
    @Test
    public void test05(){
        //功能型 Function<T,R>
        //将Integer转为String
        Function<Integer, String> fun = new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) {//10
                return String.valueOf(integer);
            }
        };
        String apply = fun.apply(30);
        System.out.println("apply = " + apply);

        System.out.println("-------------------------");

        Function<Integer,String> f1 = a->String.valueOf(a);

        String apply1 = f1.apply(66);

        System.out.println("apply1 = " + apply1);
    }

Lambda表达式

复制小括号(参数),写死右箭头(->),落地大括号{}

  • Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以

    传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更

    灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了

    提升。

  • 代码举例

public class LambdaTest {
    @Test
    public void test1(){
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("我爱北京天安门");
            }
        };
        r1.run();

        System.out.println("---------------------");
        //Lambda表达式
        Runnable r2 = () -> System.out.println("我爱北京故宫");

        r2.run();
    }
    @Test
    public void test2(){
        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };
        int compare1 = com1.compare(12,21);
        System.out.println(compare1);   //-1

        System.out.println("-----------------------");
        //Lambdad表达式写法
        Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1,o2);
        int compare2 = com2.compare(12,21);
        System.out.println(compare2);   //-1

        System.out.println("-----------------------");
        //方法引用
        Comparator<Integer> com3 = Integer :: compare;

        int compare3 = com2.compare(12,21);
        System.out.println(compare3);   //-1
    }
}
  • 代码实现

/*
* Lambda表达式的使用
*
* 1.举例 : (o1,o2) -> Integer.compare(o1,p2);
* 2.格式 :
*       -> :Lambda操作符 或 箭头操作符
*       ->左边 :Lambda形参列表 (其实就是接口中抽象方法的形参列表)
*       ->右边 :Lambda体 (其实就是重写的抽象方法的方法体)
* 3.Lambda表达式的使用: (分6种情况介绍)
*
*       总结:
*       ->左边: Lambda形参列表的参数类型可以省略(类型推断): 如果Lambda形参列表,其()也可以省略
*       ->右边: Lambda体应该使用一对{}包裹: 如果Lambda体只有一条执行语句(可能是return语句),可以省略这一对{}和return关键字
 *
* 4.Lambda表达式本质: 作为函数式接口的实例
*
* 5.如果接口中,只声明了一个抽象方法,则此接口被称为函数式接口。
* 我们可以在一个接口上使用@FunctionalInterface注解,这样做可以检查它是否是一个函数式接口。
* 同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
*
* 6.所以以前用匿名实现类表示的现在都可以用Lambda表达式来写。
* */

public class LambdaTest1 {
    //语法格式一:无参,无返回值
    @Test
    public void test1(){
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("我爱北京天安门");
            }
        };
        r1.run();
        System.out.println("---------------------");

        Runnable r2 = () -> {
            System.out.println("我爱北京故宫");
        };
        r2.run();
    }

    //语法格式二:Lambda 需要一个参数,但是没有返回值。
    @Test
    public void test2(){
        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("s");
            }
        };
        con.accept("谎言和誓言的区别是什么?");

        System.out.println("-----------------------");
        Consumer<String> con1 = (String s) ->{
            System.out.println("s");
        };
        con1.accept("一个是听的人当真了,一个是说的人当真了");
    }

    //语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
    @Test
    public void test3(){
        Consumer<String> con1 = (String s) ->{
            System.out.println("s");
        };
        con1.accept("一个是听的人当真了,一个是说的人当真了");

        System.out.println("-----------------------");

        Consumer<String> con2 = (s) ->{ //变化
            System.out.println("s");
        };
        con2.accept("一个是听的人当真了,一个是说的人当真了");
        //--------------------------------------------
        ArrayList<String> list = new ArrayList<>(); //类型推断

        int[] arr1 = new int[]{1,2,3};
        int[] arr2 = {1,2,3};   //类型推断
    }

    //语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略
    @Test
    public void test4(){
        Consumer<String> con1 = (s) ->{ //变化
            System.out.println("s");
        };
        con1.accept("一个是听的人当真了,一个是说的人当真了");

        System.out.println("-----------------------");

        Consumer<String> con2 = s ->{ //变化
            System.out.println("s");
        };
        con2.accept("一个是听的人当真了,一个是说的人当真了");
    }

    //语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
    @Test
    public void test5(){

        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println(o1);
                System.out.println(o2);
                return o1.compareTo(o2);
            }
        };
        System.out.println(com1.compare(12,21));
        System.out.println("-----------------------");

        Comparator<Integer> com2 = (o1,o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };
        System.out.println(com2.compare(12,21));
    }

    //语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略
    @Test
    public void test6(){
        Comparator<Integer> com1 = (o1,o2) -> {
            return o1.compareTo(o2);
        };
        System.out.println(com1.compare(12,21));

        System.out.println("-----------------------");

        Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);

        System.out.println(com2.compare(12,21));
    }
    @Test
    public void Test7(){
        Consumer<String> con1 = s ->{
            System.out.println("s");
        };
        con1.accept("一个是听的人当真了,一个是说的人当真了");

        System.out.println("-----------------------");

        Consumer<String> con2 = s -> System.out.println("s");

        con1.accept("一个是听的人当真了,一个是说的人当真了");

    }
}

函数式(Functional)接口

  • 只包含一个抽象方法的接口,称为函数式接口

  • 你可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式

    抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽

    象方法上进行声明)。

  • 我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检

    查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个

    接口是一个函数式接口。

  • 在java.util.function包下定义了Java 8 的丰富的函数式接口

//​​​​​​​自定义函数式接口
@FunctionalInterface
public interface MyInterface {
    void method1();
}

Java内置四大核心函数式接口

  • 代码

/*
*
* 消费型接口 Consumer<T>     void accept(T t);
* 供给型接口 Supplier<T>     T get();
* 函数型接口 Function<T,R>   R aply(T t)
* 断定型接口 Predicate<T>    boolean test(T t)   filter
*
* */
public class LambdaTest2 {

    @Test//例子1
    public void test1(){

        happyTime(500, new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println("去天上人间买了瓶娃哈哈,价格为"+aDouble);
            }
        });

        System.out.println("-------------");
        //Lambda表达式
        happyTime(500,aDouble-> System.out.println("去天上人间买了瓶娃哈哈,价格为"+aDouble));

    }
    //消费形接口
    public void happyTime(double money, Consumer<Double> con){
        con.accept(money);
    }

    @Test//例子2
    public void Test2(){
        List<String> list = Arrays.asList("北京","南京","天津","东京","西京","普京","晶晶");

        List<String> filterStrs = filterString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("京");
            }
        });
        System.out.println(filterStrs);

        System.out.println("-------------");
        //Lambda表达式
        List<String> filterStrs1 = filterString(list,s ->s.contains("京"));
    }

    //断定型接口:根据给定的规则,过滤集合中的字符串。此规则由Predicate方法决定
    public List<String> filterString(List<String> list, Predicate<String> pre){

        ArrayList<String> filterString = new ArrayList<>();

        for(String s: list){
            if(pre.test(s)){    //Predicate接口中的方法 test
                filterString.add(s);
            }
        }
        return filterString;
    }
}

方法引用

  • 代码
/**
 * 方法引用的使用
 *
 * 1.使用情景:党要传递给Lamda体的操作,已经有实现的方法了,可以使用方法引用
 *
 * 2.方法引用,本质上就是Lambda表达式,而我们的Lambda表达式作为函数式接口的实例出现。
 *   所以方法引用,也是函数式接口的实例。
 *
 * 3.使用格式: 类(或对象) :: 方法名
 *
 * 4.具体分为如下的三种情况:
 *   1.重写方法的形参是方法体内调用的方法对象      类型(类名)::方法
 *   2.重写方法的形参与方法体内调用方法的实参匹配  类型(类名)::静态方法 或 对象::普通方法
 *      类名::静态方法名   Math::rendom
 *      类名::静态方法名   Person::getName
 *      对象名::方法名     p1::getName
 *
 * 5.方法引用使用的要求:要求接口中的抽象方法的形参列表和返回值类型与
 * 	 (针对情况1、2)    方法引用的方法的形参列表和返回值类型相同
 *
 *
 *
 * Created by shkstart.
 */
public class MethodRefTest {

	// 情况一:对象 :: 实例方法
	//Consumer中的void accept(T t)
	//PrintStream中的void println(T t)
	@Test
	public void test1() {

		Consumer<String> con1 = str -> System.out.println(str);
		con1.accept("北京");

		System.out.println("----------------------");

		PrintStream ps = System.out;
		Consumer<String> con2 =ps ::println;
		con2.accept("北京");

	}
	
	//Supplier中的T get()
	//Employee中的String getName()
	@Test
	public void test2() {
		Employee emp = new Employee(1001,"tom",23,5600);
		Supplier<String> sup1 = () -> emp.getName();
		System.out.println(sup1.get());

		System.out.println("----------------------");

		Supplier<String> sup2 = emp :: getName;
		System.out.println(sup2.get());

	}

	// 情况二:类 :: 静态方法
	//Comparator中的int compare(T t1,T t2)
	//Integer中的int compare(T t1,T t2)
	@Test
	public void test3() {
		Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
		System.out.println(com1.compare(12,21));

		System.out.println("----------------------");

		Comparator<Integer> com2 = Integer :: compare;
		System.out.println(com2.compare(12,21));
		
	}
	
	//Function中的R apply(T t)
	//Math中的Long round(Double d)
	@Test
	public void test4() {

		Function<Double,Long> func = new Function<Double, Long>() {
			@Override
			public Long apply(Double d) {
				return Math.round(d);
			}
		};
		System.out.println("----------------------");
		Function<Double,Long> func1 = d -> Math.round(d);
		System.out.println(func1.apply(12.3));

		System.out.println("----------------------");

		Function<Double,Long> func2 = Math :: round;
		System.out.println(func2.apply(12.3));

	}

	// 情况三:类 :: 实例方法 (有难度)
	// Comparator中的int comapre(T t1,T t2)
	// String中的int t1.compareTo(t2)
	@Test
	public void test5() {
		Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
		System.out.println(com1.compare("abc","abd"));

		System.out.println("----------------------");

		Comparator<String> com2 = String :: compareTo;
		System.out.println(com2.compare("abc","abm"));

	}

	//BiPredicate中的boolean test(T t1, T t2);
	//String中的boolean t1.equals(t2)
	@Test
	public void test6() {
		BiPredicate<String,String> pre1 = (s1,s2) -> s1.equals(s2);
		System.out.println(pre1.test("abc","abc"));

		System.out.println("----------------------");
		BiPredicate<String,String> pre2 = String :: equals;
		System.out.println(pre2.test("abc","abd"));

	}

	// Function中的R apply(T t)
	// Employee中的String getName();
	@Test
	public void test7() {

		Employee employee = new Employee(1001, "Jerry", 23, 6000);

		Function<Employee,String> fun1 = e ->e.getName();
		System.out.println(fun1.apply(employee));

		System.out.println("----------------------");
		Function<Employee,String> fun2 = Employee :: getName;
		System.out.println(fun2);
	}
}

构造器引用、数组引用

        //构造器引用: 重写方法的形参是 与方法体内创建对象的构造器实参匹配
        //类名::new

        //数组引用: 重写方法的新参是 与方法体内创建数组的实参匹配
        //type[]::new;
    @Test
    public void test07() {
       /* Supplier<Person> s1 = new Supplier<Person>() {
            @Override
            public Person get() {
                return new Person("z",30);
            }
        };*/
        //  Supplier<Person> s2 = ()->new Person();
        //构造器引用
        Supplier<Person> s2 = Person::new;

        Person person = s2.get();

        System.out.println("person = " + person);
    }
        @Test
        public void test08() {
      /*Function<Integer,int[]> function = new Function<Integer, int[]>() {
          @Override
          public int[] apply(Integer integer) {
              return new int[integer];
          }
        };*/
        //lambda
        //Function<Integer, int[]> f1 = i -> new int[i];
        //数组引用
        Function<Integer, int[]> f1 = int[]::new;

        int[] apply = f1.apply(30);
        System.out.println("apply.length = " + apply.length);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值