java代碼之美(13)--- Predicate詳解

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章