java程式碼之美(13)--- Predicate詳解
阿新 • • 發佈:2019-08-09
java程式碼之美(13)--- Predicate詳解
遇到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)