从函数式接口到lambda表达式

JDK1.8之前接口开发示例,下面以Comparator为例

接口方式

import org.junit.Test;
public class LambdaTest {
   @Test
   public void testInterface1() {
        String[] strings = {"123", "25", "7686", "92872", "b"};
        System.out.println(Arrays.toString(strings));
        Comparator<String> lengthComparator = new LengthComparator();
        Arrays.sort(strings, lengthComparator);
        System.out.println(Arrays.toString(strings));
    }
    @Test
    public void testInterface2() {
        String[] strings = {"123", "25", "7686", "92872", "b"};
        System.out.println(Arrays.toString(strings));
        Comparator<String> lengthComparator = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.length() - o2.length();
            }
        };
        Arrays.sort(strings, lengthComparator);
        System.out.println(Arrays.toString(strings));
    }
}
class LengthComparator implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        return o1.length() - o2.length();
    }
}

从JDK1.8开始java开始支持lambda表达式,lambda表达式适用于函数式接口,函数式接口是只有一个抽象方法的接口,下面以Comparator为例

lambda完整语法

先不讨论两种形式的区别,后面会讲

import org.junit.Test;
public class LambdaTest {
    @Test
    public void testLambda() {
        String[] strings = {"123", "25", "7686", "92872", "b"};
        System.out.println(Arrays.toString(strings));
        Comparator<String> lengthComparator = (String str1, String str2) -> {
            return str1.length() - str2.length();
        };
        Arrays.sort(strings, lengthComparator);
        System.out.println(Arrays.toString(strings));
    }
    @Test
    public void testLambda2() {
        String[] strings = {"123", "25", "7686", "92872", "b"};
        System.out.println(Arrays.toString(strings));
        Arrays.sort(strings, (String str1, String str2) -> {
            return str1.length() - str2.length();
        });
        System.out.println(Arrays.toString(strings));
    }
}

函数式接口和lambda表达式的区别

从上面的代码可以看出,lambda表达式就是函数式接口具体实现方法的参数和方法体,并且lambda表达式可以当成一个参数直接传递给方法.

lambda表达式可以传递给相同参数签名和返回值的任何函数式接口.换句话说两个函数式接口的参数签名和返回值一样的他们的lambda表达式是通用的

lambda表达式简写形式

import org.junit.Test;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionListener;
public class LambdaTest {
    /**
     * 参数类型可省略
     * 函数体只有一行可以省略{},return(如果有返回值),最后的分号
     */
 	@Test
    public void testLambdaAbbr1() {
        String[] strings = {"123", "25", "7686", "92872", "b"};
        System.out.println(Arrays.toString(strings));
        Arrays.sort(strings, (str1, str2) -> str1.length() - str2.length());
        System.out.println(Arrays.toString(strings));
    }

    /**
     * 只有一个参数可以省略括号
     */
    @Test
    public void testLambdaAbbr2() {
        Timer t = new Timer(1000, event -> {
            System.out.println("At the tone,the time is " + new Date());
            Toolkit.getDefaultToolkit().beep();
        });
        t.start();
    }
}

lambda表达式简写形式之方法引用

当lambda表达式只有一行时,可以使用方法引用的简写方式,使用方法引用主要有三种情况(方法引用中使用this参数.例如 ,this::equals等同于x->this.equals(x),使用super也是合法的)

  • object::instanceMethod
  • Class::static Method
  • Class::instanceMethod
    /**
     * 方法引用形式一
     * object::instanceMethod
     * 参数省略,并且参数是方法的实参(如果有参数)
     */
    @Test
    public void testMethodReference() {
        ActionListener listener = System.out::println;
        Timer t = new Timer(1000, listener);
        t.start();
    }

    /**
     * 二 方法引用形式
     * Class::staticMethod
     * 参数省略,并且参数是方法的实参(如果有参数)
     */
    @Test
    public void testMethodReference2() {
        //无参
        Supplier<Person> personSupplier = Person::build;
        Person person = personSupplier.get();
        System.out.println(person);
        //有参
        Consumer<String> personConsumer = Person::print;
        personConsumer.accept("abc");
        System.out.println(personConsumer);
    }
    /**
     * 方法引用形式三
     * Class::instanceMethod
     * 第一个参数会成为方法的执行者
     * 第二个参数是方法的参数
     */
    @Test
    public void testMethodReference3() {
        String[] strings = {"123", "25", "7686", "92872", "b"};
        System.out.println(Arrays.toString(strings));
        ToIntFunction<String> toIntFunction = String::length;
        Arrays.sort(strings, Comparator.comparingInt(toIntFunction));
        System.out.println(Arrays.toString(strings));
    }

lambda表达式简写形式之构造器引用

构造器引用与方法引用很类似,只不过方法名为new

    @Test
    public void testConstructorReference() {
        List<String> names = new ArrayList<>();
        names.add("aa");
        Stream<Person> stream = names.stream().map(Person::new);
        List<Person> people = stream.collect(Collectors.toList());
        System.out.println(Arrays.toString(people.toArray()));
    }

    /**
     * Java有一个限制,无法构造泛型类型T的数组
     * 数组构造器引用对于克服这个限制很有用
     */
    @Test
    public void testConstructorReference2() {
        List<Person> people = new ArrayList<>();
        people.add(new Person("aa", 10));
        Person[] peopleArray = people.stream().toArray(Person[]::new);
        System.out.println(Arrays.toString(peopleArray));
    }

lambda表达式参数和自由变量

lambda表达式有三个部分组成

  1. 一个代码块
  2. 参数
  3. 自由变量的值,这是指非参数而且不在代码中定义的变量
    需要注意的是lambda表达式使用自由变量时,自由变量的值不会改变(因为线程安全问题)
    /**
     * ERROR
     * lambda表达式不能改变在外部定义的变量,即不能改变自由变量
     */
    @Test
    public void testLambdaRunnable() {
        int i = 0;
        run(() -> {
            for (; i < 10; i++) {
                System.out.println("Hello world");
            }
        });
    }
    private void run(Runnable runnable) {
        runnable.run();
    }

常见函数式接口及其实现样例

https://blog.csdn.net/dhbfjh/article/details/103897464

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值