Java 8 Predicate 函数接口

简介: Java 8 Predicate 函数接口

网络异常,图片无法展示
|

Predicate 函数接口同之前介绍的 Function 接口一样,是一个函数式接口,它可以接受一个泛型 <T> 参数,返回值为布尔类型Predicate 常用于数据过滤,如过滤出集合中符合某个条件的元素。

源码:Java 8 中函数接口 Predicate

package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

1.  Predicate test

Predicate 函数接口可以用于判断一个参数是否符合某个条件。

示例:判断某个字符串是否为空。

import java.util.function.Predicate;
public class Java8PredicateTest {
    public static void main(String[] args) {
        Predicate<String> isEmpty = String::isEmpty;
        System.out.println(isEmpty.test(""));
        System.out.println(isEmpty.test("www.wdbyte.com"));
    }
}

输出结果:

true
false

2. Predicate Stream filter

Stream 中的 filter() 方法是通过接收一个 Predicate 函数接口实现的。

示例:过滤出集合中,字符串长度为 4 的字符串。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Java8PredicateFilter {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("java", "node", "www.wdbyte.com");
        list = list.stream().filter(str -> str.length() == 4).collect(Collectors.toList());
        System.out.println(list);
    }
}

输出结果:

[java, node]

3.  Predicate and

使用 and() 方法,可以让前后两个 Predicate 判断条件一起生效。

示例 1:过滤数字集合中,数字大小在 5 至 9 之间的数字。

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Java8PredicateAnd {
    public static void main(String[] args) {
        List<Integer> numberList = Arrays.asList(3, 4, 5, 6, 7, 8, 9, 10);
        Predicate<Integer> greaterThan5 = number -> number > 5;
        Predicate<Integer> lessThan9 = number -> number < 9;
        Predicate<Integer> filter = greaterThan5.and(lessThan9);
        numberList = numberList.stream().filter(filter).collect(Collectors.toList());
        System.out.println(numberList);
    }
}

结果输出:

[6, 7, 8]

示例 2:一个 Predicate 过滤数字集合中,数字大小在 5 至 9 之间的数字。

List<Integer> numberList = Arrays.asList(3, 4, 5, 6, 7, 8, 9, 10);
numberList = numberList.stream().filter(x -> x > 5 && x < 9).collect(Collectors.toList());
System.out.println(numberList);

输出结果;

[6, 7, 8]

4.  Predicate negate

predicate.negate() 方法会返回一个与指定判断相反的 Predicate

示例:过滤数字集合中,数字大于 5 的数字。

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Java8PredicateNeagete {
    public static void main(String[] args) {
        List<Integer> numberList = Arrays.asList(3, 4, 5, 6, 7, 8, 9, 10);
        Predicate<Integer> greaterThan5 = number -> number > 5;
        numberList = numberList.stream().filter(greaterThan5.negate()).collect(Collectors.toList());
        System.out.println(numberList);
    }
}

输出结果:

[3, 4, 5]

5.  Predicate or

示例:过滤数字集合中,数字小于等于 5,或者大于等于 9 的数字。

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Java8PredicateOr {
    public static void main(String[] args) {
        List<Integer> numberList = Arrays.asList(3, 4, 5, 6, 7, 8, 9, 10);
        Predicate<Integer> lessThan5 = number -> number <= 5;
        Predicate<Integer> greaterThan8 = number -> number >= 9;
        numberList = numberList.stream().filter(lessThan5.or(greaterThan8)).collect(Collectors.toList());
        System.out.println(numberList);
    }
}

输出结果:

[3, 4, 5, 9, 10]

6. Predicate 链式编程

Predicateor()and()negate() 方法可以随意组合 Predicate,组合后的判断逻辑是从左到右,从前到后,顺次判断。

:(数字小于 5 ).and (数字大于 9 ).negate()

:(数字小于 5 )AND (数字大于 9 ) 对于任意数字都得 falsefalse.negate() 取相反 得 true

所以,此判断逻辑对于任意数字都为 true

示例Predicateor()and()negate()  方法组合使用。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Java8PredicateChain {
    public static void main(String[] args) {
        List<Integer> numberList = Arrays.asList(3, 4, 5, 6, 7, 8, 9, 10);
        Predicate<Integer> lessThan5 = number -> number <= 5;
        Predicate<Integer> greaterThan9 = number -> number >= 9;
        // 小于等于 5
        System.out.println(filter(numberList, lessThan5));
        // 大于 5
        System.out.println(filter(numberList, lessThan5.negate()));
        // 小于等于 5 或者大于等于 9
        System.out.println(filter(numberList, lessThan5.or(greaterThan9)));
        // ! (小于等于 5 AND 大于等于 9)
        System.out.println(filter(numberList, lessThan5.and(greaterThan9).negate()));
    }
    public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
        List<T> resultList = new ArrayList<>();
        for (T t : list) {
            if (predicate.test(t)) {
                resultList.add(t);
            }
        }
        return resultList;
    }
}

输出结果:

[3, 4, 5]
[6, 7, 8, 9, 10]
[3, 4, 5, 9, 10]
[3, 4, 5, 6, 7, 8, 9, 10]

7. Predicate 与对象

示例:过滤符合某些特征的狗。

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class Java8PredicateObject {
    public static void main(String[] args) {
        List<Dog> dogList = new ArrayList<>();
        dogList.add(new Dog("哈士奇", 1));
        dogList.add(new Dog("牧羊犬", 2));
        dogList.add(new Dog("柯基", 3));
        dogList.add(new Dog("柴犬", 3));
        // 找到 3岁的狗
        System.out.println(filter(dogList, dog -> dog.getAge().equals(3)));
        // 找到哈士奇信息
        Predicate<Dog> predicate = dog -> ("哈士奇").equals(dog.getName());
        System.out.println(filter(dogList, predicate));
    }
    public static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
        List<T> resultList = new ArrayList<>();
        for (T t : list) {
            if (predicate.test(t)) { resultList.add(t); }
        }
        return resultList;
    }
}
class Dog {
    private String name;
    private Integer age;
    public Dog(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Dog{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}

输出结果:

[Dog{name='柯基', age=3}, Dog{name='柴犬', age=3}]
[Dog{name='哈士奇', age=1}]

BiPredicatePredicate 函数接口一样,都是返回一个布尔类型,唯一不同的是 Predicate 接受一个参数,而 BiPredicate 可以接受两个不同类型的参数。

BiPredicate 在 Java 8 中源码:

package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface BiPredicate<T, U> {
    boolean test(T t, U u);
    default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) {
        Objects.requireNonNull(other);
        return (T t, U u) -> test(t, u) && other.test(t, u);
    }
    default BiPredicate<T, U> negate() {
        return (T t, U u) -> !test(t, u);
    }
    default BiPredicate<T, U> or(BiPredicate<? super T, ? super U> other) {
        Objects.requireNonNull(other);
        return (T t, U u) -> test(t, u) || other.test(t, u);
    }
}


相关文章
|
6天前
|
Java
Java——抽象类和接口
抽象类是一种不能被实例化的类,至少包含一个抽象方法(无实现体的方法),常用于定义一组相关类的共同特征,并强制子类实现特定方法。抽象方法不能被 `static` 或 `final` 修饰,且必须被重写。 接口则是一个完全抽象的类,用于规范类的行为。接口使用 `interface` 关键字定义,不能实例化,并且类与接口之间是实现关系。 内部类是在一个类内定义的类,分为成员内部类、静态内部类、局部内部类和匿名内部类。成员内部类可被修饰符修饰,静态内部类只能访问外部类的静态成员,局部内部类定义在方法内,匿名内部类则隐藏了名字,直接通过 `new` 关键字定义并实现接口或继承类。
12 5
Java——抽象类和接口
|
6天前
|
Java
Java——接口的使用实例
Comparable接口用于自定义类的对象比较。通过实现此接口并重写`compareTo`方法,可以定义自定义类型的比较规则。 接下来介绍了Comparator接口,它提供了一种更灵活的比较方式。通过实现Comparator接口并重写`compare`方法,可以根据不同属性定义不同的比较规则。例如,定义一个`BrandComparator`类来比较汽车的品牌。 最后,介绍了Cloneable接口,用于实现对象的克隆。实现该接口并重写`clone`方法后,可以创建对象的浅拷贝或深拷贝。浅拷贝仅复制对象本身,深拷贝则会递归复制所有成员变量。
13 4
Java——接口的使用实例
|
12天前
|
Java 数据库连接 数据库
Java服务提供接口(SPI)的设计与应用剖析
Java SPI提供了一种优雅的服务扩展和动态加载机制,使得Java应用程序可以轻松地扩展功能和替换组件。通过合理的设计与应用,SPI可以大大增强Java应用的灵活性和可扩展性。
44 18
|
9天前
|
Java 开发者
Java的接口详解
Java接口是编程中的一种重要特性,用于定义方法签名而不提供具体实现,作为类之间的契约,使不同类能以统一方式交互。接口使用`interface`关键字定义,可包含方法声明和常量。类通过`implements`关键字实现接口,并可同时实现多个接口,解决多重继承问题。接口中的方法默认为抽象方法,变量默认为`public static final`。Java 8引入了默认方法和静态方法,增强接口功能。接口广泛应用于回调机制和多态性实现,有助于构建更灵活和可维护的代码结构。
|
19天前
|
Java
盘点java8 stream中隐藏的函数式接口
`shigen`是一位坚持更新文章的博客作者,记录成长历程,分享认知见解,留住感动瞬间。本文介绍了函数式接口的概念及其在Java中的应用,包括`Comparator`、`Runnable`、`Callable`等常见接口,并详细讲解了`Function`、`Predicate`、`Consumer`、`Supplier`和`Comparator`等函数式接口的使用方法及应用场景,展示了如何利用这些接口简化代码并提高编程效率。**个人IP:shigen**,与shigen一起,每天进步一点点!
29 0
盘点java8 stream中隐藏的函数式接口
|
20天前
|
Java 编译器 开发者
Java中的Lambda表达式与函数式接口
【8月更文挑战第31天】本文将深入探讨Java 8中引入的Lambda表达式和函数式接口,它们如何改变我们编写代码的方式。通过简化集合操作、事件处理等示例,我们将看到这些特性如何提升代码可读性、减少冗余,并提高开发效率。准备好一起探索这个让Java编程更加简洁强大的新世界吧!
|
23天前
|
Java
在Java多线程领域,精通Lock接口是成为高手的关键。
在Java多线程领域,精通Lock接口是成为高手的关键。相较于传统的`synchronized`,Lock接口自Java 5.0起提供了更灵活的线程同步机制,包括可中断等待、超时等待及公平锁选择等高级功能。本文通过实战演练介绍Lock接口的核心实现——ReentrantLock,并演示如何使用Condition进行精确线程控制,帮助你掌握这一武林秘籍,成为Java多线程领域的盟主。示例代码展示了ReentrantLock的基本用法及Condition在生产者-消费者模式中的应用,助你提升程序效率和稳定性。
18 2
|
6天前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
17天前
|
监控 Java 调度
【Java学习】多线程&JUC万字超详解
本文详细介绍了多线程的概念和三种实现方式,还有一些常见的成员方法,CPU的调动方式,多线程的生命周期,还有线程安全问题,锁和死锁的概念,以及等待唤醒机制,阻塞队列,多线程的六种状态,线程池等
79 6
【Java学习】多线程&JUC万字超详解
|
3天前
|
Java
深入理解Java中的多线程编程
本文将探讨Java多线程编程的核心概念和技术,包括线程的创建与管理、同步机制以及并发工具类的应用。我们将通过实例分析,帮助读者更好地理解和应用Java多线程编程,提高程序的性能和响应能力。
15 4