com.feilong.core.util.predicate.BeanPredicateUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of feilong Show documentation
Show all versions of feilong Show documentation
feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.
/*
* Copyright (C) 2008 feilong
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.feilong.core.util.predicate;
import static com.feilong.core.Validator.isNotNullOrEmpty;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import org.apache.commons.collections4.Predicate;
import com.feilong.core.Validate;
import com.feilong.core.bean.PropertyUtil;
import com.feilong.core.lang.ArrayUtil;
import com.feilong.core.util.AggregateUtil;
import com.feilong.core.util.CollectionsUtil;
import com.feilong.core.util.equator.IgnoreCaseEquator;
import com.feilong.lib.collection4.ComparatorUtils;
import com.feilong.lib.collection4.PredicateUtils;
import com.feilong.lib.collection4.functors.ComparatorPredicate;
import com.feilong.lib.collection4.functors.ComparatorPredicate.Criterion;
import com.feilong.lib.collection4.functors.EqualPredicate;
/**
* 专门针对bean,提供的 BeanPredicateUtil.
*
* @author feilong
* @see com.feilong.lib.collection4.PredicateUtils
* @see com.feilong.core.util.predicate.BeanPredicate
* @since 1.8.0
*/
@SuppressWarnings("squid:S1192") //String literals should not be duplicated
public final class BeanPredicateUtil{
/** Don't let anyone instantiate this class. */
private BeanPredicateUtil(){
//AssertionError不是必须的. 但它可以避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化.
//see 《Effective Java》 2nd
throw new AssertionError("No " + getClass().getName() + " instances for you!");
}
//---------------------------------------------------------------
/**
* 用来指定 T
对象的特定属性 propertyName
equals 指定的 propertyValue
.
*
* 说明:
*
*
* -
* 常用于解析集合,如 {@link CollectionsUtil#select(Iterable, Predicate) select},{@link CollectionsUtil#find(Iterable, Predicate) find},
* {@link CollectionsUtil#selectRejected(Iterable, Predicate) selectRejected},
* {@link CollectionsUtil#group(Iterable, String, Predicate) group},
* {@link AggregateUtil#groupCount(Iterable, String, Predicate) groupCount},
* {@link AggregateUtil#sum(Iterable, String, Predicate) sum} 等方法.
*
*
*
*
* 示例:
*
*
*
*
* 场景: 在list中查找 名字是 关羽,并且 年龄是30 的user
*
*
*
*
* User guanyu30 = new User("关羽", 30);
* List{@code } list = toList(//
* new User("张飞", 23),
* new User("关羽", 24),
* new User("刘备", 25),
* guanyu30);
*
* Predicate{@code } predicate = PredicateUtils
* .andPredicate(BeanPredicateUtil.equalPredicate("name", "关羽"), BeanPredicateUtil.equalPredicate("age", 30));
*
* assertEquals(guanyu30, CollectionsUtil.find(list, predicate));
*
*
*
*
*
* @param
* the generic type
* @param
* the value type
* @param propertyName
* 泛型T对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见
* propertyName
* @param propertyValue
* the property value
* @return 如果 propertyName
是null,抛出 {@link NullPointerException}
* 如果 propertyName
是blank,抛出 {@link IllegalArgumentException}
* @see com.feilong.lib.collection4.PredicateUtils#equalPredicate(Object)
*/
public static Predicate equalPredicate(String propertyName,V propertyValue){
Validate.notBlank(propertyName, "propertyName can't be blank!");
return new BeanPredicate<>(propertyName, PredicateUtils.equalPredicate(propertyValue));
}
/**
* 用来指定 T
对象的特定属性 propertyName
equalsIgnoreCase 指定的 propertyValue
.
*
* 说明:
*
*
* -
* 常用于解析集合,如 {@link CollectionsUtil#select(Iterable, Predicate) select},{@link CollectionsUtil#find(Iterable, Predicate) find},
* {@link CollectionsUtil#selectRejected(Iterable, Predicate) selectRejected},
* {@link CollectionsUtil#group(Iterable, String, Predicate) group},
* {@link AggregateUtil#groupCount(Iterable, String, Predicate) groupCount},
* {@link AggregateUtil#sum(Iterable, String, Predicate) sum} 等方法.
*
*
*
*
* 示例:
*
*
*
*
* 场景: 在list中查找 name是 zhangfei(忽视大小写) 的user
*
*
*
* User zhangfei1 = new User("zhangfei", 22);
* User zhangfei2 = new User("zhangFei", 22);
* User zhangfei3 = new User("Zhangfei", 22);
* User zhangfeinull = new User((String) null, 22);
* User guanyu = new User("guanyu", 25);
* User liubei = new User("liubei", 30);
*
* List{@code } list = toList(zhangfei1, zhangfei2, zhangfei3, zhangfeinull, guanyu, liubei);
*
* List{@code } select = select(list, BeanPredicateUtil.{@code } equalIgnoreCasePredicate("name", "zhangfei"));
*
* assertThat(select, allOf(//
* hasItem(zhangfei1),
* hasItem(zhangfei2),
* hasItem(zhangfei3),
*
* not(hasItem(zhangfeinull)),
* not(hasItem(guanyu)),
* not(hasItem(liubei))
* //
* ));
*
*
*
*
* @param
* the generic type
* @param propertyName
* 泛型T对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见
* propertyName
* @param propertyValue
* the property value
* @return 如果 propertyName
是null,抛出 {@link NullPointerException}
* 如果 propertyName
是blank,抛出 {@link IllegalArgumentException}
* @see com.feilong.lib.collection4.PredicateUtils#equalPredicate(Object)
* @see com.feilong.core.util.equator.IgnoreCaseEquator#INSTANCE
* @since 1.10.1
*/
public static Predicate equalIgnoreCasePredicate(String propertyName,String propertyValue){
Validate.notBlank(propertyName, "propertyName can't be blank!");
return new BeanPredicate<>(propertyName, EqualPredicate.equalPredicate(propertyValue, IgnoreCaseEquator.INSTANCE));
}
/**
* 用来判断一个对象指定的属性以及属性值是否相等.
*
* 说明:
*
*
* -
* 常用于解析集合,如 {@link CollectionsUtil#select(Iterable, Predicate) select},{@link CollectionsUtil#find(Iterable, Predicate) find},
* {@link CollectionsUtil#selectRejected(Iterable, Predicate) selectRejected},
* {@link CollectionsUtil#group(Iterable, String, Predicate) group},
* {@link AggregateUtil#groupCount(Iterable, String, Predicate) groupCount},
* {@link AggregateUtil#sum(Iterable, String, Predicate) sum} 等方法.
*
*
*
*
* 示例:
*
*
*
*
* 场景: 在list中查找 名字是 关羽,并且 年龄是30 的user
*
*
*
*
* User guanyu30 = new User("关羽", 30);
* List{@code } list = toList(//
* new User("张飞", 23),
* new User("关羽", 24),
* new User("刘备", 25),
* guanyu30);
*
* Predicate{@code } predicate = PredicateUtils
* .andPredicate(BeanPredicateUtil.equalPredicate("name", "关羽"), BeanPredicateUtil.equalPredicate("age", 30));
*
* assertEquals(guanyu30, CollectionsUtil.find(list, predicate));
*
*
*
* 此时你可以优化成:
*
*
*
*
* User guanyu30 = new User("关羽", 30);
* List{@code } list = toList(//
* new User("张飞", 23),
* new User("关羽", 24),
* new User("刘备", 25),
* guanyu30);
*
* Map{@code } map = ConvertUtil.toMap("name", "关羽", "age", 30);
* assertEquals(guanyu30, find(list, BeanPredicateUtil.{@code } equalPredicate(map)));
*
*
*
*
* @param
* the generic type
* @param propertyNameAndPropertyValueMap
* 属性和指定属性值对应的map,其中key是泛型T对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见
* propertyName
* @return 如果 propertyNameAndPropertyValueMap
是null,抛出 {@link NullPointerException}
* 如果 propertyNameAndPropertyValueMap
是empty,抛出{@link IllegalArgumentException}
* 如果 propertyNameAndPropertyValueMap
中有key是null,抛出{@link NullPointerException}
* 如果 propertyNameAndPropertyValueMap
中有key是blank,抛出{@link IllegalArgumentException}
* @see #equalPredicate(String, Object)
* @since 1.9.5
*/
public static Predicate equalPredicate(Map propertyNameAndPropertyValueMap){
Validate.notEmpty(propertyNameAndPropertyValueMap, "propertyNameAndPropertyValueMap can't be null!");
@SuppressWarnings("unchecked")
BeanPredicate[] beanPredicates = ArrayUtil.newArray(BeanPredicate.class, propertyNameAndPropertyValueMap.size());
int index = 0;
for (Map.Entry entry : propertyNameAndPropertyValueMap.entrySet()){
String propertyName = entry.getKey();
Object propertyValue = entry.getValue();
Validate.notBlank(propertyName, "propertyName can't be blank!");
Array.set(beanPredicates, index, equalPredicate(propertyName, propertyValue));
index++;
}
return PredicateUtils.allPredicate(beanPredicates);
}
/**
* 构造属性与一个指定对象 bean
的一组属性的值 propertyNames
都相等的判断器.
*
* 说明:
*
*
* -
* 常用于解析集合,如 {@link CollectionsUtil#select(Iterable, Predicate) select},{@link CollectionsUtil#find(Iterable, Predicate) find},
* {@link CollectionsUtil#selectRejected(Iterable, Predicate) selectRejected},
* {@link CollectionsUtil#group(Iterable, String, Predicate) group},
* {@link AggregateUtil#groupCount(Iterable, String, Predicate) groupCount},
* {@link AggregateUtil#sum(Iterable, String, Predicate) sum} 等方法.
*
*
*
*
* 示例:
*
*
*
*
* 场景: 在list中查找 名字是 关羽,并且 年龄是30 的user
*
*
*
*
* User guanyu30 = new User("关羽", 30);
* List{@code } list = toList(//
* new User("张飞", 23),
* new User("关羽", 24),
* new User("刘备", 25),
* guanyu30);
*
* Predicate{@code } predicate = PredicateUtils
* .andPredicate(BeanPredicateUtil.equalPredicate("name", "关羽"), BeanPredicateUtil.equalPredicate("age", 30));
*
* assertEquals(guanyu30, CollectionsUtil.find(list, predicate));
*
*
*
* 此时你可以优化成:
*
*
*
*
* User guanyu30 = new User("关羽", 30);
* List{@code } list = toList(//
* new User("张飞", 23),
* new User("关羽", 24),
* new User("刘备", 25),
* guanyu30);
*
* assertEquals(guanyu30, find(list, BeanPredicateUtil.equalPredicate(guanyu30, "name", "age")));
*
*
*
*
* @param
* the generic type
* @param bean
* the bean
* @param propertyNames
* 如果 propertyNames
是null或者empty 那么取所有属性值.
* @return 如果 bean
是null,返回 {@link com.feilong.lib.collection4.PredicateUtils#nullPredicate()}
* 否则 调用 {@link com.feilong.core.bean.PropertyUtil#describe(Object, String...)} 提取属性值,再调用 {@link #equalPredicate(Map)}
* @see #equalPredicate(String, Object)
* @see com.feilong.core.bean.PropertyUtil#describe(Object, String...)
* @since 1.10.6
*/
public static Predicate equalPredicate(T bean,String...propertyNames){
if (null == bean){
return PredicateUtils.nullPredicate();
}
Map propertyNameAndPropertyValueMap = PropertyUtil.describe(bean, propertyNames);
return equalPredicate(propertyNameAndPropertyValueMap);
}
//---------------------------------------------------------------
/**
* 调用 {@link PropertyUtil#getProperty(Object, String)} 获得 propertyName
的值,使用
* {@link com.feilong.lib.lang3.ArrayUtils#contains(Object[], Object) ArrayUtils.contains} 判断是否在 values
数组中.
*
* 说明:
*
*
* -
* 常用于解析集合,如 {@link CollectionsUtil#select(Iterable, Predicate) select},{@link CollectionsUtil#find(Iterable, Predicate) find},
* {@link CollectionsUtil#selectRejected(Iterable, Predicate) selectRejected},
* {@link CollectionsUtil#group(Iterable, String, Predicate) group},
* {@link AggregateUtil#groupCount(Iterable, String, Predicate) groupCount},
* {@link AggregateUtil#sum(Iterable, String, Predicate) sum} 等方法.
*
*
*
*
* @param
* the generic type
* @param
* the value type
* @param propertyName
* 泛型T对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见
* propertyName
* @param propertyValues
* the property values
* @return 如果 propertyName
是null,抛出 {@link NullPointerException}
* 如果 propertyName
是blank,抛出 {@link IllegalArgumentException}
* @see com.feilong.lib.lang3.ArrayUtils#contains(Object[], Object)
*/
@SafeVarargs
public static Predicate containsPredicate(final String propertyName,final V...propertyValues){
Validate.notBlank(propertyName, "propertyName can't be blank!");
return new BeanPredicate<>(
propertyName, //
propertyValue -> com.feilong.lib.lang3.ArrayUtils.contains(propertyValues, propertyValue));
}
/**
* 调用 {@link PropertyUtil#getProperty(Object, String)} 获得 propertyName
的值,使用{@link java.util.Collection#contains(Object)
* Collection.contains} 判断是否在values
集合中.
*
* 说明:
*
*
*
* -
* 常用于解析集合,如 {@link CollectionsUtil#select(Iterable, Predicate) select},{@link CollectionsUtil#find(Iterable, Predicate) find},
* {@link CollectionsUtil#selectRejected(Iterable, Predicate) selectRejected},
* {@link CollectionsUtil#group(Iterable, String, Predicate) group},
* {@link AggregateUtil#groupCount(Iterable, String, Predicate) groupCount},
* {@link AggregateUtil#sum(Iterable, String, Predicate) sum} 等方法.
*
*
*
*
*
* @param
* the generic type
* @param
* the value type
* @param propertyName
* 泛型T对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见
* propertyName
* @param propertyValueList
* the property value list
* @return 如果 propertyName
是null,抛出 {@link NullPointerException}
* 如果 propertyName
是blank,抛出 {@link IllegalArgumentException}
* @see java.util.Collection#contains(Object)
*/
public static Predicate containsPredicate(final String propertyName,final Collection propertyValueList){
Validate.notBlank(propertyName, "propertyName can't be blank!");
return new BeanPredicate<>(
propertyName,
propertyValue -> isNotNullOrEmpty(propertyValueList) && propertyValueList.contains(propertyValue));
}
//---------------------------------------------------------------
/**
* 判断指定的值 valueToCompare
criterion
提取的bean对象属性propertyName
的值 .
*
*
* 注意: 是参数 valueToCompare
和 属性值进行比较 criterion
, BeanPredicateUtil.comparatorPredicate("age", 20,
* Criterion.LESS) 表示提取所有比20 大的结果
*
*
* 说明:
*
*
* - 使用 {@link ComparatorUtils#naturalComparator()} 自然排序比较器.
* - 比较
comparator.compare(valueToCompare, propertyValue)
.
* -
* 常用于解析集合,如 {@link CollectionsUtil#select(Iterable, Predicate) select},{@link CollectionsUtil#find(Iterable, Predicate) find},
* {@link CollectionsUtil#selectRejected(Iterable, Predicate) selectRejected},
* {@link CollectionsUtil#group(Iterable, String, Predicate) group},
* {@link AggregateUtil#groupCount(Iterable, String, Predicate) groupCount},
* {@link AggregateUtil#sum(Iterable, String, Predicate) sum} 等方法.
*
*
*
*
* 关于 {@link Criterion}:
*
*
*
*
*
* 字段
* 说明
*
*
*
*
* {@link Criterion#EQUAL}
* comparator.compare(valueToCompare, propertyValue) == 0
*
*
*
* {@link Criterion#LESS}
* comparator.compare(valueToCompare, propertyValue) {@code <} 0
*
*
*
* {@link Criterion#GREATER}
* comparator.compare(valueToCompare, propertyValue) {@code >} 0
*
*
*
* {@link Criterion#GREATER_OR_EQUAL}
* comparator.compare(valueToCompare, propertyValue) {@code >=} 0
*
*
*
* {@link Criterion#LESS_OR_EQUAL}
* comparator.compare(valueToCompare, propertyValue) {@code <=} 0
*
*
*
*
*
* 通常对于以下代码:
*
*
*
*
* 场景: 大于20岁的人分个组
*
*
*
* List{@code } list = toList(//
* new User("张飞", 10),
* new User("张飞", 28),
* new User("刘备", 32),
* new User("刘备", 30),
* new User("刘备", 10));
*
* Map{@code >} map = CollectionsUtil.group(list, "name", new Predicate{@code }(){
*
* {@code @Override}
* public boolean evaluate(User user){
* return user.getAge() {@code >} 20;
* }
* });
*
*
*
* 你可以简化成:
*
*
*
* List{@code } list = toList(//
* new User("张飞", 10),
* new User("张飞", 28),
* new User("刘备", 32),
* new User("刘备", 30),
* new User("刘备", 10));
*
* Predicate{@code } comparatorPredicate = BeanPredicateUtil.comparatorPredicate("age", 20, Criterion.LESS);
*
*
*
*
* @param
* the generic type
* @param
* the value type
* @param propertyName
* 泛型T对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见
* propertyName
* @param valueToCompare
* the value to compare
* @param criterion
* the criterion
* @return 如果 propertyName
是null,抛出 {@link NullPointerException}
* 如果 propertyName
是blank,抛出 {@link IllegalArgumentException}
* @see ComparatorUtils#naturalComparator()
* @since commons-collections 4
*/
public static > Predicate comparatorPredicate(
String propertyName,
V valueToCompare,
Criterion criterion){
Validate.notBlank(propertyName, "propertyName can't be blank!");
return comparatorPredicate(propertyName, valueToCompare, ComparatorUtils. naturalComparator(), criterion);
}
/**
* 判断指定的值 valueToCompare
criterion
提取的bean对象属性propertyName
的值 .
*
* 说明:
*
*
* - 使用
comparator
比较器
* - 比较
comparator.compare(valueToCompare, propertyValue)
.
* -
* 常用于解析集合,如 {@link CollectionsUtil#select(Iterable, Predicate) select},{@link CollectionsUtil#find(Iterable, Predicate) find},
* {@link CollectionsUtil#selectRejected(Iterable, Predicate) selectRejected},
* {@link CollectionsUtil#group(Iterable, String, Predicate) group},
* {@link AggregateUtil#groupCount(Iterable, String, Predicate) groupCount},
* {@link AggregateUtil#sum(Iterable, String, Predicate) sum} 等方法.
*
*
*
*
* 关于 {@link Criterion}:
*
*
*
*
*
* 字段
* 说明
*
*
*
*
* {@link Criterion#EQUAL}
* comparator.compare(valueToCompare, propertyValue) == 0
*
*
*
* {@link Criterion#LESS}
* comparator.compare(valueToCompare, propertyValue) {@code <} 0
*
*
*
* {@link Criterion#GREATER}
* comparator.compare(valueToCompare, propertyValue) {@code >} 0
*
*
*
* {@link Criterion#GREATER_OR_EQUAL}
* comparator.compare(valueToCompare, propertyValue) {@code >=} 0
*
*
*
* {@link Criterion#LESS_OR_EQUAL}
* comparator.compare(valueToCompare, propertyValue) {@code <=} 0
*
*
*
*
*
* @param
* the generic type
* @param
* the value type
* @param propertyName
* 泛型T对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见
* propertyName
* @param valueToCompare
* the value to compare
* @param comparator
* the comparator
* @param criterion
* the criterion
* @return 如果 propertyName
是null,抛出 {@link NullPointerException}
* 如果 propertyName
是blank,抛出 {@link IllegalArgumentException}
* @see com.feilong.lib.collection4.functors.ComparatorPredicate
* @since commons-collections 4
*/
public static > Predicate comparatorPredicate(
String propertyName,
V valueToCompare,
Comparator comparator,
Criterion criterion){
Validate.notBlank(propertyName, "propertyName can't be blank!");
return new BeanPredicate<>(propertyName, new ComparatorPredicate(valueToCompare, comparator, criterion));
}
}