All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.core.util.predicate.BeanPredicateUtil Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * 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.
     * 
     * 

说明:

*
*
    *
  1. * 常用于解析集合,如 {@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} 等方法. *
  2. *
*
* *

示例:

* *
* *

* 场景: 在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. * *

说明:

*
*
    *
  1. * 常用于解析集合,如 {@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} 等方法. *
  2. *
*
* *

示例:

* *
* *

* 场景: 在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)); } /** * 用来判断一个对象指定的属性以及属性值是否相等. * *

说明:

*
*
    *
  1. * 常用于解析集合,如 {@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} 等方法. *
  2. *
*
* *

示例:

* *
* *

* 场景: 在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 都相等的判断器. * *

说明:

*
*
    *
  1. * 常用于解析集合,如 {@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} 等方法. *
  2. *
*
* *

示例:

* *
* *

* 场景: 在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数组中. * *

说明:

*
*
    *
  1. * 常用于解析集合,如 {@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} 等方法. *
  2. *
*
* * @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集合中. * *

说明:

*
* *
    *
  1. * 常用于解析集合,如 {@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} 等方法. *
  2. *
* *
* * @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 大的结果 *

* *

说明:

*
*
    *
  1. 使用 {@link ComparatorUtils#naturalComparator()} 自然排序比较器.
  2. *
  3. 比较 comparator.compare(valueToCompare, propertyValue).
  4. *
  5. * 常用于解析集合,如 {@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} 等方法. *
  6. *
*
* *

关于 {@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的值 . * *

说明:

*
*
    *
  1. 使用 comparator 比较器
  2. *
  3. 比较 comparator.compare(valueToCompare, propertyValue).
  4. *
  5. * 常用于解析集合,如 {@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} 等方法. *
  6. *
*
* *

关于 {@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)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy