遇到 Predicate 是自己在自定义 Mybatis 拦截器的时候, 在拦截器中我们是通过反射机制获取对象的所有属性, 再查看这些属性上是否有我们自定义的 UUID 注解.
如果有该注解, 那么就给该属性赋值 UUID 随机字符串, 作为主键保存到数据库. 所以前提条件就是获取带有 UUID 注解的属性, 就需要用到 Predicate.
- // 获取所有带 UUID 注解的属性
- Set<Field> 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> {
- /**
- * 具体过滤操作 需要被子类实现.
- * 用来处理参数 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<T> {
- // 重写过滤条件
- @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