• 念念不忘,必有回响!包含: Java 基础, Java 部分源码, JVM, Spring, Spring Boot, Spring Cloud, 开源项目等
  • 念念不忘,必有回响!包含: 数据库原理, MySQL, ElasticSearch, MongoDB, Docker,CI&CD, Linux, DevOps, 分布式, 中间件等
  • 念念不忘,必有回响!包含: 开发工具, Git, IDE, 源码阅读,读书笔记等

内置的函数式接口

2023-04-15 11:14
1481
0

JDK 1.8 API 包含了很多内置的函数式接口。其中就包括我们在老版本中经常见到的 Comparator 和 Runnable,Java 8 为他们都添加了 @FunctionalInterface 注解,以用来支持 Lambda 表达式。

例如我们旧版本的Jdk中常用的 Comparator 和 Runnable 外,还有一些新的函数式接口,可以通过函数注解实现Lamdba支持,它们很多都借鉴于知名的 Google Guava (opens new window)库。

即使你已经熟悉这个类库,也应该密切关注那些接口是如何通过一些有用的方法扩展来扩展的:

#1. Predicate 断言

Predicate 是一个可以指定入参类型,并返回 boolean 值的函数式接口。它内部提供了一些带有默认实现的方法,可以 被用来组合一个复杂的逻辑判断(and, or, negate):

@Test
public void test11() {
	Predicate<String> predicate = (s) -> s.length() > 0;
boolean foo0 = predicate.test("foo");           // true
boolean foo1 = predicate.negate().test("foo");  // negate否定相当于!true

Predicate&lt;Boolean&gt; nonNull = Objects::nonNull;
Predicate&lt;Boolean&gt; isNull = Objects::isNull;

Predicate&lt;String&gt; isEmpty = String::isEmpty;
Predicate&lt;String&gt; isNotEmpty = isEmpty.negate();

}

    @小傅哥: 代码已经复制到剪贴板

#2. Functions

Function 函数式接口的作用是,我们可以为其提供一个原料,他给生产一个最终的产品。通过它提供的默认方法,组合,链行处理(compose, andThen):

@Test
public void test12() {
    Function<String, Integer> toInteger = Integer::valueOf;                                         //转Integer
    Function<String, String> backToString = toInteger.andThen(String::valueOf);                     //转String
    Function<String, String> afterToStartsWith = backToString.andThen(new Something()::startsWith); //截取第一位 
    String apply = afterToStartsWith.apply("123");// "123"
    System.out.println(apply);
}
    @小傅哥: 代码已经复制到剪贴板

#3. Suppliers

Supplier 与 Function 不同,它不接受入参,直接为我们生产一个指定的结果,有点像生产者模式:

@Test
public void test13() {
    Supplier<Person> personSupplier0 = Person::new;
    personSupplier0.get();   // new Person
    Supplier<String> personSupplier1 = Something::test01;  //这个test方法是静态的,且无入参
    personSupplier1.get();   // hi
Supplier&lt;String&gt; personSupplier2 = new Something()::test02;

}

    @小傅哥: 代码已经复制到剪贴板

#4. Consumers

对于 Consumer,我们需要提供入参,用来被消费,如下面这段示例代码:

@Test
public void test14() {
    // 参照物,方便知道下面的Lamdba表达式写法
    Consumer<Person> greeter01 = new Consumer<Person>() {
        @Override
        public void accept(Person p) {
            System.out.println("Hello, " + p.firstName);
        }
    };
    Consumer<Person> greeter02 = (p) -> System.out.println("Hello, " + p.firstName);
    greeter02.accept(new Person("Luke", "Skywalker"));  //Hello, Luke
    Consumer<Person> greeter03 = new MyConsumer<Person>()::accept;    // 也可以通过定义类和方法的方式去调用,这样才是实际开发的姿势
    greeter03.accept(new Person("Luke", "Skywalker"));  //Hello, Luke
}
    @小傅哥: 代码已经复制到剪贴板

#5. Comparators

Comparator 在 Java 8 之前是使用比较普遍的。Java 8 中除了将其升级成了函数式接口,还为它拓展了一些默认方法:

@Test
public void test15(){
    Comparator<Person> comparator01 = (p1, p2) -> p1.firstName.compareTo(p2.firstName);
    Comparator<Person> comparator02 = Comparator.comparing(p -> p.firstName);           //等同于上面的方式
    Person p1 = new Person("John", "Doe");
    Person p2 = new Person("Alice", "Wonderland");
    comparator01.compare(p1, p2);             // > 0
    comparator02.reversed().compare(p1, p2);  // < 0
}

全部评论