java代码之美(13)--- Predicate详解

简介: java代码之美(13)--- Predicate详解遇到Predicate是自己在自定义Mybatis拦截器的时候,在拦截器中我们是通过反射机制获取对象的所有属性,再查看这些属性上是否有我们自定义的UUID注解。

java代码之美(13)--- Predicate详解
遇到Predicate是自己在自定义Mybatis拦截器的时候,在拦截器中我们是通过反射机制获取对象的所有属性,再查看这些属性上是否有我们自定义的UUID注解。

如果有该注解,那么就给该属性赋值UUID随机字符串,作为主键保存到数据库。所以前提条件就是获取带有UUID注解的属性,就需要用到Predicate。

//获取所有带UUID注解的属性
Set allFields = ReflectionUtils.getFields(object.getClass(),x.getAnnotation(UUId.class) != null);
也想到之前自己在用steam处理集合的时候,添加的过滤条件也是用Predicate,只不过它们不在同一包下。虽然它们不在同一包下但它们的作用是一致的,就是

Predicate接口主要用来判断一个参数是否符合要求

下面对这两个接口分别进行说明并举例。

一、java.util.function.Predicate
这里类是java自带主要广泛用在支持lambda表达式的API中。

1、接口源码
@FunctionalInterface
public interface Predicate {

/**
 * 具体过滤操作 需要被子类实现.
 * 用来处理参数T是否满足要求,可以理解为 条件A
 */
boolean test(T t);
/**
 * 调用当前Predicate的test方法之后再去调用other的test方法,相当于进行两次判断
 * 可理解为 条件A && 条件B
 */
default Predicate<T> and(Predicate<? super T> other) {
    Objects.requireNonNull(other);
    return (t) -> test(t) && other.test(t);
}
/**
 * 对当前判断进行"!"操作,即取非操作,可理解为 ! 条件A
 */
default Predicate<T> negate() {
    return (t) -> !test(t);
}
/**
 * 对当前判断进行"||"操作,即取或操作,可以理解为 条件A ||条件B
 */
default Predicate<T> or(Predicate<? super T> other) {
    Objects.requireNonNull(other);
    return (t) -> test(t) || other.test(t);
}

/**
 * 对当前操作进行"="操作,即取等操作,可以理解为 A == B
 */
static <T> Predicate<T> isEqual(Object targetRef) {
    return (null == targetRef)
            ? Objects::isNull
            : object -> targetRef.equals(object);
}

}
2、常规示例

public static void main(String[] args) {
    /**
     * 1、判断数字是否大于7
     */
    //设置一个大于7的过滤条件
    Predicate<Integer> predicate = x -> x > 7;
    System.out.println(predicate.test(10)); //输出 true
    System.out.println(predicate.test(6));  //输出 fasle
     /**
      * 2、大于7并且
      */
    //在上面大于7的条件下,添加是偶数的条件
    predicate = predicate.and(x -> x % 2 == 0);
    System.out.println(predicate.test(6));  //输出 fasle
    System.out.println(predicate.test(12)); //输出 true
    System.out.println(predicate.test(13)); //输出 fasle
    /**
     * 3、add or 简化写法
     */
    predicate = x -> x > 5 && x < 9;
    System.out.println(predicate.test(10)); //输出 false
    System.out.println(predicate.test(6));  //输出 true
}

3、集合Stream示例
User对象

@Data
@AllArgsConstructor
@ToString
public class User {

/**
 * 姓名
 */
private String name;

/**
 * 性别
 */
private String sex;

/**
 * 年龄
 */
private Integer age;

/**

 * 重写equals和hashCode
 */
@Override
public boolean equals(Object obj) {
    if (obj instanceof User) {
        User user = (User) obj;
        if (name.equals(user.name)){
            return true;
        }
    }
        return false;
    }
    @Override
    public int hashCode () {
        return name.hashCode();
    }

}

测试代码

public static void main(String[] args) {
    User user1 = new User("张三", "女", 1);
    User user2 = new User("李四", "男", 2);
    User user3 = new User("张三", "女", 3);
    List<User> list = Lists.newArrayList(user1, user2, user3);

   /**
    * 1、获取年龄大于2的对象
    */
    List<User> collect = list.stream().filter(x -> x.getAge() > 2).collect(Collectors.toList());
    System.out.println("获取年龄大于2的数量 = " + collect.size());
    //输出:获取年龄大于2的数量 = 1

    /**
     * 2、去重 设置name相同即为相同对象
     */
    //方式1直接使用 distinct
    List<User> collect1 = list.stream().distinct().collect(Collectors.toList());
    System.out.println("输出剩余对象" + collect1);
    //输出:输出剩余对象[User(name=张三, sex=女, age=1), User(name=李四, sex=男, age=2)]

    /**
     * 3、从集合找出与该对象相同的元素 同样name相同即为相同对象
     */
    User user4 = new User("张三", "男", 8);
    Predicate<User> predicate =  Predicate.isEqual(user4);
    List<User> collect2 = list.stream().filter(predicate).collect(Collectors.toList());
    System.out.println("与该对象相同的对象有" + collect2);
    //输出:与该对象相同的对象有[User(name=张三, sex=女, age=1), User(name=张三, sex=女, age=3)]
}

运行结果

二、com.google.common.base.Predicate
这里的Predicate是配合guava使用的。

作用

处理集合的过滤条件
反射工具类的过滤条件
如果作为集合的过滤条件,现在已经没有必要用它了,因为JDK1.8的stream在处理集合的时候比它好用多了。

1、接口源码
@GwtCompatible
public interface Predicate {
//重写过滤条件
@CanIgnoreReturnValue
boolean apply(@Nullable T input);
//重写equals
boolean equals(@Nullable Object object);
在使用它的时候需要重写两个方法。

2、示例
自定义UUID注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface UUID {
}
Person

@Data
@AllArgsConstructor
@ToString
public class Person {

/**
 * 姓名 在name上使用UUID注解
 */
@UUID
private String name;
/**
 * 性别
 */
private String sex;
/**
 * 年龄
 */
private Integer age;

}
测试代码

public static void main(String[] args) {

    Person person1 = new Person("张三", "女", 1);
    Person person2 = new Person("李四", "男", 2);
    Person person3 = new Person("张三", "女", 3);

    List<Person> list = Lists.newArrayList(person1, person2, person3);
    /**
     * 1、guava使用过滤 年龄大于2的
     */
    Predicate<Person> predicate1 = new Predicate<Person>() {
        //重写两个方法
        @Override
        public boolean apply(Person input) {
            if (input.getAge() > 2) {
                return true;
            }
            return false;
        }
        @Override
        public boolean equals(Object object) {
            return true;
        }
    };
    list = Lists.newArrayList(Iterables.filter(list,predicate1));
    System.out.println("过滤后的集合数据: "+list);
    //输出: 过滤后的集合数据: [Person(name=张三, sex=女, age=3)]

    /**
     * 2、配合反射工具类ReflectionUtils过滤获取属性
     */
    Person person4 = new Person("张三", "女", 1);
    Set<Field> allFields = org.reflections.ReflectionUtils.getFields(person4.getClass(),x -> x != null && x.getAnnotation(UUID.class) != null);
    System.out.println("带UUID注解的属性有 "+ allFields);
    //输出 :带UUID注解的属性有 [private java.lang.String com.jincou.vo.Person.name]
}

运行结果

很明显,这里已经获取到了带有UUID注解的属性为name。

只要自己变优秀了,其他的事情才会跟着好起来(上将12)
原文地址https://www.cnblogs.com/qdhxhz/p/11323595.html

相关文章
|
7天前
|
Java 测试技术 应用服务中间件
常见 Java 代码缺陷及规避方式(下)
常见 Java 代码缺陷及规避方式(下)
26 0
|
8天前
|
Java
Java中ReentrantLock释放锁代码解析
Java中ReentrantLock释放锁代码解析
25 8
|
11天前
|
前端开发 小程序 Java
uniapp上传图片 前端以及java后端代码实现
uniapp上传图片 前端以及java后端代码实现
28 0
|
13天前
|
设计模式 存储 Java
23种设计模式,享元模式的概念优缺点以及JAVA代码举例
【4月更文挑战第6天】享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享技术有效地支持大量细粒度对象的重用。这个模式在处理大量对象时非常有用,特别是当这些对象中的许多实例实际上可以共享相同的状态时,从而可以减少内存占用,提高程序效率
30 4
|
13天前
|
设计模式 Java 中间件
23种设计模式,适配器模式的概念优缺点以及JAVA代码举例
【4月更文挑战第6天】适配器模式(Adapter Pattern)是一种结构型设计模式,它的主要目标是让原本由于接口不匹配而不能一起工作的类可以一起工作。适配器模式主要有两种形式:类适配器和对象适配器。类适配器模式通过继承来实现适配,而对象适配器模式则通过组合来实现
30 4
|
14天前
|
存储 缓存 算法
优化 Java 后台代码的关键要点
【4月更文挑战第5天】本文探讨了优化 Java 后台代码的关键点,包括选用合适的数据结构与算法、减少不必要的对象创建、利用 Java 8 新特性、并发与多线程处理、数据库和缓存优化、代码分析与性能调优、避免阻塞调用、JVM 调优以及精简第三方库。通过这些方法,开发者可以提高系统性能、降低资源消耗,提升用户体验并减少运营成本。
|
15天前
|
Java 开发工具 流计算
flink最新master代码编译出现Java Runtime Environment 问题
在尝试编译Flink源码时遇到Java运行时环境致命错误:EXCEPTION_ACCESS_VIOLATION。问题出现在JVM.dll+0x88212。使用的是Java 11.0.28和Java HotSpot(TM) 64-Bit Server VM。系统为Windows客户端,没有生成核心dump文件。错误日志保存在hs_err_pid39364.log和replay_pid39364.log。要解决这个问题,建议检查JDK版本兼容性,更新JDK或参照错误报告文件提交Bug至http://bugreport.java.com/bugreport/crash.jsp。
|
17天前
|
Java
使用Java代码打印log日志
使用Java代码打印log日志
73 1
|
17天前
|
设计模式 Java 数据库
Java设计模式精讲:让代码更优雅、更可维护
【4月更文挑战第2天】**设计模式是解决软件设计问题的成熟方案,分为创建型、结构型和行为型。Java中的单例模式确保类仅有一个实例,工厂方法模式让子类决定实例化哪个类。适配器模式则协调不兼容接口间的合作。观察者模式实现了一对多依赖,状态变化时自动通知相关对象。学习和适当应用设计模式能提升代码质量和可维护性,但需避免过度使用。设计模式的掌握源于实践与不断学习。**
Java设计模式精讲:让代码更优雅、更可维护
|
17天前
|
SQL 设计模式 安全
Java单例模式几种写法以及代码案例拿来直接使用
Java单例模式几种写法以及代码案例拿来直接使用
31 0