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

com.feilong.core.util.CollectionsUtil 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;

import static com.feilong.core.Validator.isNotNullOrEmpty;
import static com.feilong.core.Validator.isNullOrEmpty;
import static com.feilong.core.bean.ConvertUtil.toArray;
import static com.feilong.core.bean.ConvertUtil.toList;
import static com.feilong.core.util.MapUtil.newLinkedHashMap;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.Transformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.feilong.core.Validate;
import com.feilong.core.bean.PropertyUtil;
import com.feilong.core.bean.PropertyValueObtainer;
import com.feilong.core.util.closure.BeanPropertyValueChangeClosure;
import com.feilong.core.util.predicate.BeanPredicateUtil;
import com.feilong.core.util.transformer.BeanTransformer;
import com.feilong.lib.collection4.CollectionUtils;
import com.feilong.lib.collection4.IterableUtils;
import com.feilong.lib.collection4.ListUtils;

/**
 * {@link Collection} 工具类,是 {@link Collections} 的扩展和补充.
 *
 * 

Collections Framework关系图:

* *
*

* Collections Framework关系图 *

*
* *

关于 {@link java.util.Collection}:

* *
* * * * * * * * * *
字段说明
{@link java.util.Collection Collection} *
    *
  1. 一组对象的集合,一般不直接使用
  2. *
  3. 有 {@link Collection#add(Object) add},{@link Collection#size() size},{@link Collection#clear() clear}, * {@link Collection#contains(Object) contains} ,{@link Collection#remove(Object) remove},{@link Collection#removeAll(Collection) removeAll} * ,{@link Collection#retainAll(Collection) retainAll}, {@link Collection#toArray() toArray}方法
  4. *
  5. 没有get()方法.只能通过iterator()遍历元素
  6. *
*
*
* *

关于 {@link java.util.List}:

* *
* * * * * * * * * * * * * * * * * * * * * * * * * *
interface/class说明
{@link java.util.List List} *
    *
  1. An ordered collection
  2. *
  3. integer index for insert and search.
  4. *
  5. 除了继承Collection接口方法外,有自己的方法定义: get(int) indexOf lastIndexOf listIterator set(int) subList(int,int)
  6. *
  7. optional:可空,可重复
  8. *
*
{@link java.util.ArrayList ArrayList} *
    *
  1. Resizable-array implementation of the List interface
  2. *
  3. 元素可空
  4. *
  5. 有自己控制容量(数组大小)的方法
  6. *
*

* 扩容: *

*
*
    *
  1. see {@link java.util.ArrayList#ensureCapacity(int)},
    * 在jdk1.6里面,int newCapacity = (oldCapacity * 3)/2 + 1 通常是1.5倍
    * 在jdk1.7+里面,代码进行了优化
  2. *
*
*
{@link java.util.LinkedList LinkedList} *
    *
  1. Linked list implementation,双向链表
  2. *
  3. 元素可空
  4. *
*
{@link java.util.Vector Vector} *
    *
  1. growable array of objects
  2. *
  3. 线程安全的动态数组 synchronized
  4. *
  5. 操作基本和ArrayList相同
  6. *
*
{@link java.util.Stack Stack} *
    *
  1. last-in-first-out (LIFO) stack of objects
  2. *
*
*
* *
* *

关于 {@link Set }:

* *
* * * * * * * * * * * * * * * * * * * * * * * * * *
interface/class说明
{@link java.util.Set Set} *
    *
  1. A collection contains no duplicate elements
  2. *
  3. Set和Collection拥有一模一样的接口名称
  4. *
*
{@link java.util.HashSet HashSet} *
    *
  1. backed by a HashMap instance.
  2. *
  3. makes no guarantees as to the iteration order of the set; 不保证顺序
  4. *
  5. permits the null element.允许空元素
  6. *
*
{@link java.util.LinkedHashSet LinkedHashSet} *
    *
  1. Hash Map and linked list implementation of the Set interface,
  2. *
  3. with predictable iteration order
  4. *
*
{@link java.util.TreeSet TreeSet} *
    *
  1. A NavigableSet implementation based on a TreeMap.
  2. *
  3. ordered using their natural ordering, or by a Comparator provided at set creation time
  4. *
*
{@link java.util.EnumSet EnumSet} *
    *
  1. A specialized Set implementation for use with enum types.
  2. *
  3. Null elements are not permitted.
  4. *
  5. natural order (the order in which the enum constants are declared.
  6. *
  7. abstract class.
  8. *
  9. 以位向量的形式存储,这种存储形式非常紧凑,高效,占用内存很小,运行效率很好.
  10. *
*
*
* *
* *

关于 {@link java.util.Queue Queue}:

* *
* * * * * * * * * *
interface/class说明
{@link java.util.Queue Queue} *
    *
  1. Queues typically, but do not necessarily,order elements in a FIFO (first-in-first-out) manner
  2. *
*
*
* *

SET-MAP现代诗一首

* *
*
    *
  • 天下人都知道Set,Map不能重复
  • *
  • 80%人知道hashCode,equals是判断重复的法则 
  • *
  • 40%人知道Set添加重复元素时,旧元素不会被覆盖
  • *
  • 20%人知道Map添加重复键时,旧键不会被覆盖,而值会覆盖
  • *
*
* *

guava 实用方法:

*
*
    *
  1. com.google.common.collect.Iterables.concat({@code Iterable>})
  2. *
*
* * @author feilong * @see java.util.Collections * @see com.feilong.lib.collection4.ListUtils * @see com.feilong.lib.collection4.IterableUtils * @see com.feilong.lib.collection4.CollectionUtils * @see "org.springframework.util.CollectionUtils" * @see "com.google.common.collect.Sets" * @see "com.google.common.collect.Lists" * @see "com.google.common.collect.Queues" * @see "com.google.common.collect.Iterators" * @see "com.google.common.collect.Iterables" * @since 1.0.2 * * @since jdk1.5 */ @SuppressWarnings("squid:S1192") //String literals should not be duplicated public final class CollectionsUtil{ /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(CollectionsUtil.class); /** Don't let anyone instantiate this class. */ private CollectionsUtil(){ //AssertionError不是必须的. 但它可以避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化. //see 《Effective Java》 2nd throw new AssertionError("No " + getClass().getName() + " instances for you!"); } //----------------------------------------------------------------------- /** * Returns consecutive {@link List#subList(int, int) sublists} of a * list, each of the same size (the final list may be smaller). For example, * partitioning a list containing {@code [a, b, c, d, e]} with a partition * size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list containing * two inner lists of three and two elements, all in the original order. *

* The outer list is unmodifiable, but reflects the latest state of the * source list. The inner lists are sublist views of the original list, * produced on demand using {@link List#subList(int, int)}, and are subject * to all the usual caveats about modification as explained in that API. *

* Adapted from http://code.google.com/p/guava-libraries/ * * @param * the element type * @param list * the list to return consecutive sublists of * @param size * the desired size of each sublist (the last may be smaller) * @return a list of consecutive sublists * @throws NullPointerException * if list is null * @throws IllegalArgumentException * if size is not strictly positive * @since 3.0.6 */ public static List> partition(List list,int size){ return ListUtils.partition(list, size); } //--------------------------------------------------------------- /** * 返回object 元素的大小. * *

* 支持object 如下类型: *

* *
    *
  • Collection - the collection size *
  • Map - the map size *
  • Array - the array size *
  • Iterator - the number of elements remaining in the iterator *
  • Iterable - the number of elements remaining in the iterator *
  • Enumeration - the number of elements remaining in the enumeration *
* * 如果 object 不是上述类型,将抛出异常 {@link IllegalArgumentException}
* * @param object * the object to get the size of, may be null * @return object中包含的元素的数量
* 如果 object 是null 返回 0
* @since 3.0.6 */ public static int size(final Object object){ return CollectionUtils.size(object); } /** * Shortcut for {@code get(iterator, 0)}. *

* Returns the first value in the iterable's {@link Iterator}, throwing * IndexOutOfBoundsException if there is no such element. *

*

* If the {@link Iterable} is a {@link List}, then it will use {@link List#get(int)}. *

* * @param * the type of object in the {@link Iterable}. * @param iterable * the {@link Iterable} to get a value from, may be null * @return the first object * @throws IndexOutOfBoundsException * if the request is invalid * @since 3.0.6 */ public static T first(final Iterable iterable){ return get(iterable, 0); } /** * Returns the index-th value in the iterable's {@link Iterator}, throwing * IndexOutOfBoundsException if there is no such element. *

* If the {@link Iterable} is a {@link List}, then it will use {@link List#get(int)}. * * @param * the type of object in the {@link Iterable}. * @param iterable * the {@link Iterable} to get a value from, may be null * @param index * the index to get * @return the object at the specified index * @throws IndexOutOfBoundsException * if the index is invalid * @since 3.0.6 */ public static T get(final Iterable iterable,final int index){ return IterableUtils.get(iterable, index); } //--------------------------------------------------------------- /** * 循环将beanIterable每个元素的每个指定属性 propertyName的值改成 propertyValue. * *

示例:

* *
* * 对于以下购物车全选的代码: * *
     *
     * //找到需要处理的对象list
     * List{@code } toDoNeedChangeCheckedCommandList = select(
     *                 needChangeCheckedCommandList,
     *                 toggleCheckStatusShoppingCartLinePredicateBuilder.build(shoppingCartLineCommandList, checkStatus));
     *
     * // 将状态修改成对应状态
     * for (ShoppingCartLineCommand shoppingCartLineCommand : toDoNeedChangeCheckedCommandList){
     *     shoppingCartLineCommand.setSettlementState(1);
     * }
     *
     * 
* * 此时你还可以: * *
     * //找到需要处理的对象list
     * List{@code } toDoNeedChangeCheckedCommandList = select(
     *                 needChangeCheckedCommandList,
     *                 toggleCheckStatusShoppingCartLinePredicateBuilder.build(shoppingCartLineCommandList, checkStatus));
     *
     * // 将状态修改成对应状态
     * CollectionsUtil.forEach(toDoNeedChangeCheckedCommandList, "settlementState", 1);
     * 
* *
* *

说明:

*
*
    *
  1. 如果 beanIterable 是null或者empty,什么都不做
  2. *
  3. 如果 beanIterable 中有元素是null,将跳过去
  4. *
*
* * @param * the element type * @param beanIterable * beanIterable * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param propertyValue * 指定属性的属性值 * @throws NullPointerException * 如果 propertyName 是null * @throws IllegalArgumentException * 如果 propertyName 是blank * @see com.feilong.lib.collection4.IterableUtils#forEach(Iterable, org.apache.commons.collections4.Closure) * @see BeanPropertyValueChangeClosure * @since 1.10.2 */ public static void forEach(final Iterable beanIterable,String propertyName,Object propertyValue){ if (isNotNullOrEmpty(beanIterable)){ IterableUtils.forEach(beanIterable, new BeanPropertyValueChangeClosure(propertyName, propertyValue)); } } /** * 添加所有的{@link Iterable}元素到指定的objectCollection,如果 {@code iterable}是null将忽略. * *

示例:

* *
* *
     *
     * List{@code } list = toList("xinge", "feilong1");
     * CollectionsUtil.addAllIgnoreNull(list, null); = false
     * 
* *
* *

重构:

* *
*

* 对于以下代码: *

* *
     *
     * private Set{@code } getItemComboIds(List{@code } lines){
     *     Set{@code } set = new HashSet{@code <>}();
     *     if ({@code null != lines && lines.size() > 0}){
     *         for (ShoppingCartLineCommand line : lines){
     *             if (line.getComboIds() != null){
     *                 set.addAll(line.getComboIds());
     *             }
     *         }
     *     }
     *     return set;
     * }
     *
     * 
* * 可以重构成: * *
     *
     * private Set{@code } getItemComboIds(List{@code } lines){
     *     if (isNullOrEmpty(lines)){
     *         return Collections.emptySet();
     *     }
     *     Set{@code } set = new HashSet{@code <>}();
     *     for (ShoppingCartLineCommand line : lines){
     *         CollectionsUtil.addAllIgnoreNull(set, line.getComboIds());
     *     }
     *     return set;
     * }
     * 
* *

* 重构之后,方法的复杂度会更小,阅读性更高 *

*
* * @param * the type of object the {@link Collection} contains * @param objectCollection * the collection to add to, 不能为null * @param iterable * the iterable of elements to add * @return a boolean 标识 objectCollection 是否改变,如果改变了,返回true.
* 如果 objectCollection 是null,抛出 {@link NullPointerException}
* 如果 iterable 是null,直接返回false
* 否则调用{@link CollectionUtils#addAll(Collection, Iterable)} * @see com.feilong.lib.collection4.CollectionUtils#addIgnoreNull(Collection, Object) * @see com.feilong.lib.collection4.CollectionUtils#addAll(Collection, Iterable) * @see com.feilong.lib.collection4.CollectionUtils#addAll(Collection, Iterator) * @since 1.6.3 */ public static boolean addAllIgnoreNull(final Collection objectCollection,final Iterable iterable){ Validate.notNull(objectCollection, "objectCollection can't be null!"); return null != iterable && CollectionUtils.addAll(objectCollection, iterable); } /** * 添加 element元素到指定的objectCollection,如果 element 是null或者 empty将忽略. * *

重构:

* *
* * 对于以下代码: * *
     *
     * List{@code } dataList = new ArrayList{@code <>}();
     * for (T bean : iterable){
     *     Object[] objectArray = toObjectArray(bean, propertyNameList);
     *     if (isNotNullOrEmpty(objectArray)){
     *         dataList.add(objectArray);
     *     }
     * }
     * return dataList;
     *
     * 
* * 可以重构成: * *
     *
     * List{@code } dataList = new ArrayList{@code <>}();
     * for (T bean : iterable){
     *     addIgnoreNullOrEmpty(dataList, toObjectArray(bean, propertyNameList));
     * }
     * return dataList;
     * 
* * 重构之后,方法的复杂度会更小,阅读性更高 * *
* * @param * the generic type * @param objectCollection * the collection to add to, 不能为null * @param element * element to add * @return a boolean 标识 objectCollection 是否改变,如果改变了,返回true.
* 如果 objectCollection 是null,抛出 {@link NullPointerException}
* 如果 element 是null 或者 empty,直接返回false
* 否则调用objectCollection.add(object) * @see com.feilong.lib.collection4.CollectionUtils#addIgnoreNull(Collection, Object) * @since 1.8.2 */ public static boolean addIgnoreNullOrEmpty(final Collection objectCollection,final T element){ Validate.notNull(objectCollection, "objectCollection can't be null!"); return isNotNullOrEmpty(element) && objectCollection.add(element); } //--------------------------------------------------------------- /** * 在list中,查找第一个属性 propertyName 值是指定值 propertyValue 对象的索引位置. * *

示例:

* *
* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     *
     * CollectionsUtil.indexOf(list, "name", "张飞")                          =   0
     *
     * CollectionsUtil.indexOf(null, "age", 24)                             =   -1
     * CollectionsUtil.indexOf(new ArrayList{@code }(), "age", 24)    =   -1
     * 
* *
* *

说明:

*
*
    *
  1. 常用于 浏览历史记录,当前的商品id是否在历史记录中第一条位置,如果是,可能就不会操作Cookie,诸如此类的操作
  2. *
*
* * @param * the generic type * @param * the generic type * @param list * the list * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param propertyValue * 指定属性的属性值 * @return 如果 list是null 或者 empty,返回 -1
* 如果指定属性propertyName的值 propertyValue在 list 查找不到,返回 -1
* @throws NullPointerException * 如果 propertyName 是null * @throws IllegalArgumentException * 如果 propertyName 是blank * @see com.feilong.lib.collection4.ListUtils#indexOf(List, Predicate) * @see BeanPredicateUtil#equalPredicate(String, Object) * @since 1.5.5 */ public static int indexOf(List list,String propertyName,V propertyValue){ return ListUtils.indexOf(list, BeanPredicateUtil. equalPredicate(propertyName, propertyValue)); } //***********************删除**************************************************** /** * 从 objectCollection中删除所有的 removeCollection (原集合对象不变). * *

说明:

*
*
    *
  1. 返回剩余的集合 (原集合对象objectCollection不变),如果你不想修改 objectCollection的话,不能直接调用 * collection.removeAll(remove);,这个方法非常有用.
  2. *
  3. 底层实现是调用的 {@link ListUtils#removeAll(Collection, Collection)},将不是removeElement的元素加入到新的list返回.
  4. *
*
* *

示例:

* *
* *

* 场景: 从list中删除 "feilong2","feilong1"元素 *

* *
     * List{@code } list = toList("xinge", "feilong1", "feilong2", "feilong2");
     * List{@code } removeList = CollectionsUtil.removeAll(list, toList("feilong2", "feilong1"));
     * 
* * 返回: * *
     * ["xinge"]
     * 
* *
* * @param * the generic type * @param objectCollection * the collection from which items are removed (in the returned collection) * @param removeCollection * the items to be removed from the returned collection * @return 从 objectCollection中排除掉 removeCollection 元素的新的 list * @throws NullPointerException * 如果 objectCollection 是null,或者 removeCollection 是null * @see ListUtils#removeAll(Collection, Collection) * @since Commons Collections 4 * @since 1.0.8 */ public static List removeAll(Collection objectCollection,Collection removeCollection){ Validate.notNull(objectCollection, "objectCollection can't be null!"); Validate.notNull(removeCollection, "removeCollection can't be null!"); return ListUtils.removeAll(objectCollection, removeCollection); } /** * 从 objectCollection中删除所有的 null元素 (原集合对象不变). * *

说明:

*
* *
    *
  1. 返回剩余的集合 (原集合对象objectCollection不变),如果你不想修改 objectCollection的话,不能直接调用 * collection.removeAll(remove);,这个方法非常有用.
  2. *
  3. 底层实现是调用的 {@link ListUtils#removeAll(Collection, Collection)},将不是removeElement的元素加入到新的list返回.
  4. *
* *
* *

示例:

* *
* *

* 场景: 从list中删除 null 元素 *

* *
     * List{@code } list = toList("xinge", null, "feilong2", null, "feilong2");
     * List{@code } removeList = CollectionsUtil.removeAllNull(list);
     * 
* * 返回: * *
     * "xinge", "feilong2", "feilong2"
     * 
* *
* * @param * the generic type * @param objectCollection * the collection from which items are removed (in the returned collection) * @return 从 objectCollection中排除掉 null 元素的新的 list * @throws NullPointerException * 如果 objectCollection 是null * @see ListUtils#removeAll(Collection, Collection) * @since Commons Collections 4 * @since 1.11.0 */ public static List removeAllNull(Collection objectCollection){ Validate.notNull(objectCollection, "objectCollection can't be null!"); return remove(objectCollection, toArray((O) null)); } //--------------------------------------------------------------- /** * 从 objectCollection中 删除removeElements (原集合对象不变). * *

说明:

*
*
    *
  1. 返回剩余的集合 (原集合对象不变),这个方法非常有用,如果你不想修改 collection的话,不能调用 * collection.remove(removeElements);.
  2. *
  3. 底层实现是调用的 {@link ListUtils#removeAll(Collection, Collection)},将不是removeElements 的元素加入到新的list返回.
  4. *
*
* *

示例:

*
* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add("xinge");
     * list.add("feilong1");
     * list.add("feilong2");
     * list.add("feilong2");
     *
     * LOGGER.info(JsonUtil.format(CollectionsUtil.remove(list, "feilong2")));
     * 
* * 返回: * *
     * ["xinge","feilong1"]
     * 
* * 此时,原来的list不变: * *
     * LOGGER.info(JsonUtil.format(list));
     * 
* * 输出 : * *
     * ["xinge","feilong1","feilong2","feilong2"]
     * 
* *
* * @param * the generic type * @param objectCollection * the object collection * @param removeElements * 需要被删除的元素 * @return a List containing all the elements of c except any elements that also occur in remove. * @throws NullPointerException * 如果 objectCollection 是null * @see #removeAll(Collection, Collection) * @see ListUtils#removeAll(Collection, Collection) * @since Commons Collections 4 * @since 1.0.8 * @since 1.10.7 change param to Varargs */ @SafeVarargs public static List remove(Collection objectCollection,O...removeElements){ return removeAll(objectCollection, toList(removeElements)); } //--------------------------------------------------------------- /** * 去重,返回没有重复元素的新list (原集合对象不变). * *

示例:

*
* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add("feilong1");
     * list.add("feilong2");
     * list.add("feilong2");
     * list.add("feilong3");
     *
     * LOGGER.info(JsonUtil.format(CollectionsUtil.removeDuplicate(list)));
     * 
* * 返回: * *
     * ["feilong1","feilong2","feilong3"]
     * 
* *
* *

注意:

*
*
    *
  1. 如果原 objectCollection 是有序的,那么返回的结果参照原 objectCollection元素顺序
  2. *
  3. objectCollection不变
  4. *
*
* * @param * the generic type * @param objectCollection * the object collection * @return 如果 objectCollection 是null或者empty,返回 {@link Collections#emptyList()}
* 否则先转换成 {@link LinkedHashSet},再转换成{@link ArrayList}返回 * @see LinkedHashSet#LinkedHashSet(Collection) * @see com.feilong.core.bean.ConvertUtil#toList(Collection) * @see "org.apache.commons.collections4.IterableUtils#uniqueIterable(Iterable)" * @see http://www.oschina.net/code/snippet_117714_2991?p=2#comments * */ public static List removeDuplicate(Collection objectCollection){ return isNullOrEmpty(objectCollection) ? Collections. emptyList() : toList(new LinkedHashSet(objectCollection)); } /** * 去重,返回指定属性 propertyName的值没有重复元素的新list (原集合对象不变). * *

示例:

*
* *
     * User user1 = new User(1L);
     * User user2 = new User(1L);
     * List{@code } list = toList(user1, user2);
     *
     * List{@code } removeDuplicate = CollectionsUtil.removeDuplicate(list, "id");
     *
     * assertThat(removeDuplicate, contains(user1));
     * assertSame(1, removeDuplicate.size());
     * 
* *
* *

注意:

*
*
    *
  1. 如果原 objectCollection 是有序的,那么返回的结果参照原 objectCollection元素顺序
  2. *
  3. objectCollection不变
  4. *
*
* * @param * the generic type * @param objectCollection * the object collection * @param propertyName * 包含的属性数组名字数组,(can be nested/indexed/mapped/combo),
* 如果是null或者empty,那么直接调用 {@link #removeDuplicate(Collection)}
* @return 如果 propertyNames 是null或者empty,那么直接调用 {@link #removeDuplicate(Collection)}
* 如果 objectCollection 是null或者empty,返回 {@link Collections#emptyList()}
* @see LinkedHashSet#LinkedHashSet(Collection) * @see com.feilong.core.bean.ConvertUtil#toList(Collection) * @see "org.apache.commons.collections4.IterableUtils#uniqueIterable(Iterable)" * @see http://www.oschina.net/code/snippet_117714_2991?p=2#comments * * @since 2.1.0 */ public static List removeDuplicate(Collection objectCollection,String propertyName){ if (isNullOrEmpty(propertyName)){ return removeDuplicate(objectCollection); } if (isNullOrEmpty(objectCollection)){ return Collections. emptyList(); } //--------------------------------------------------------------- Map map = groupOne(objectCollection, propertyName); return toList(map.values()); } /** * 去重,返回指定属性 propertyNames 组合的值都不重复元素的新list (原集合对象不变). * *

示例:

*
* *
     * User user1 = new User(1L);
     * user1.setUserInfo(new UserInfo(15));
     *
     * User user2 = new User(1L);
     * user2.setUserInfo(new UserInfo(16));
     *
     * User user3 = new User(1L);
     * user3.setUserInfo(new UserInfo(15));
     *
     * List{@code } list = toList(user1, user2, user3);
     *
     * List{@code } removeDuplicate = CollectionsUtil.removeDuplicate(list, "id", "userInfo.age");
     *
     * assertThat(removeDuplicate, contains(user1, user2));
     * assertSame(2, removeDuplicate.size());
     * 
* * *
* *

注意:

*
*
    *
  1. 如果原 objectCollection 是有序的,那么返回的结果参照原 objectCollection元素顺序
  2. *
  3. objectCollection不变
  4. *
*
* * @param * the generic type * @param objectCollection * the object collection * @param propertyNames * 包含的属性数组名字数组,(can be nested/indexed/mapped/combo),
* 如果是null或者empty,那么直接调用 {@link #removeDuplicate(Collection)}
* @return 如果 propertyNames 是null或者empty,那么直接调用 {@link #removeDuplicate(Collection)}
* 如果 objectCollection 是null或者empty,返回 {@link Collections#emptyList()}
* @see LinkedHashSet#LinkedHashSet(Collection) * @see com.feilong.core.bean.ConvertUtil#toList(Collection) * @see "org.apache.commons.collections4.IterableUtils#uniqueIterable(Iterable)" * @see http://www.oschina.net/code/snippet_117714_2991?p=2#comments * * @since 2.1.0 */ public static List removeDuplicate(Collection objectCollection,String...propertyNames){ if (isNullOrEmpty(propertyNames)){ return removeDuplicate(objectCollection); } if (isNullOrEmpty(objectCollection)){ return Collections. emptyList(); } //--------------------------------------------------------------- //用来识别是否重复 List> mapList = newArrayList(); //用来存放返回list List returnList = new ArrayList<>(size(objectCollection)); for (O o : objectCollection){ Map propertyNameAndValueMap = PropertyUtil.describe(o, propertyNames); boolean isNotExist = !isExist(mapList, propertyNameAndValueMap, propertyNames); if (isNotExist){ returnList.add(o); mapList.add(propertyNameAndValueMap); } } return returnList; } /** * 判断mapList 中,是否含有 指定 key-value 的map. * * @param mapList * the map list * @param propertyNameAndValueMap * the property name and value map * @param keys * the keys * @return 存在,返回true * @since 2.1.0 */ private static boolean isExist(List> mapList,Map propertyNameAndValueMap,String...keys){ for (Map map : mapList){ if (eqauls(map, propertyNameAndValueMap, keys)){ return true; } } return false; } /** * 判断两个map ,提取每个属性 keys 值, 看看是否一致, 如果有不一致的返回false; 如果都一致那么返回true. * * @param map * the map * @param propertyNameAndValueMap * the property name and value map * @param keys * the property names * @return true, if successful * @since 2.1.0 */ private static boolean eqauls(Map map,Map propertyNameAndValueMap,String...keys){ for (String propertyName : keys){ if (!Objects.equals(map.get(propertyName), propertyNameAndValueMap.get(propertyName))){ return false; } } return true; } //----------------------获得 属性值----------------------------------------- /** * 循环集合 beanIterable,取到对象指定的属性 propertyName的值,拼成List({@link ArrayList}). * *

示例:

* *
* *

* 场景: 获取user list每个元素的id属性值,组成新的list返回 *

* *
     *
     * List{@code } list = toList(//
     *                 new User(2L),
     *                 new User(5L),
     *                 new User(5L));
     *
     * List{@code } resultList = CollectionsUtil.getPropertyValueList(list, "id");
     * LOGGER.debug(JsonUtil.format(resultList));
     *
     * 
* * 返回: * *
     * [2,5,5]
     * 
* *
* *

对于参数 propertyName:

* *
* *

* 对于以下的数据结构: *

* *
     *
     * //***************list****************************************
     * List{@code } userAddresseList = new ArrayList{@code <>}();
     *
     * UserAddress userAddress = new UserAddress();
     * userAddress.setAddress("中南海");
     * userAddresseList.add(userAddress);
     *
     * //***************map****************************************
     * Map{@code } attrMap = new HashMap{@code <>}();
     * attrMap.put("蜀国", "赵子龙");
     * attrMap.put("魏国", "张文远");
     * attrMap.put("吴国", "甘兴霸");
     *
     * //---------------------------------------------------------------
     * UserInfo userInfo1 = new UserInfo();
     * userInfo1.setAge(28);
     *
     * User user1 = new User(2L);
     * user1.setLoves(new String[] { "sanguo1", "xiaoshuo1" });
     * user1.setUserInfo(userInfo1);
     * user1.setAttrMap(attrMap);
     * user1.setUserAddresseList(userAddresseList);
     *
     * //---------------------------------------------------------------
     * UserInfo userInfo2 = new UserInfo();
     * userInfo2.setAge(null);
     *
     * User user2 = new User(3L);
     * user2.setLoves(new String[] { "sanguo2", "xiaoshuo2" });
     * user2.setUserInfo(userInfo2);
     * user2.setAttrMap(attrMap);
     * user2.setUserAddresseList(userAddresseList);
     *
     * List{@code } userList = toList(user1,user2);
     * 
* *

* 以下情况: *

* *
     * //数组,取userList 每个元素的 loves属性第2个元素的值
     * CollectionsUtil.getPropertyValueList(userList, "loves[1]")                   =   ["xiaoshuo1","xiaoshuo2"]
    
     * //级联对象,取userList 每个元素的 userInfo属性的 age 属性的值
     * CollectionsUtil.getPropertyValueList(userList, "userInfo.age")               =   [28,null]
     *
     * //Map,取userList 每个元素的 attrMap属性中的key是 "蜀国" 的值
     * CollectionsUtil.getPropertyValueList(userList, "attrMap(蜀国)")                =   ["赵子龙","赵子龙"]
     *
     * //集合,取userList 每个元素的 userAddresseList属性中的第一个元素
     * CollectionsUtil.getPropertyValueList(userList, "userAddresseList[0]")        = [{"address": "中南海"},{"address": "中南海"}]
     * 
* *
* *

关于参数 beanIterable

*
* 支持以下类型: *
*
bean Iterable
*
诸如List{@code },Set{@code }等
* *
map Iterable
*
* 比如 {@code List>} * * 示例: * *
     * List{@code >} list = newArrayList();
     * list.add(toMap("key", "value1"));
     * list.add(toMap("key", "value2"));
     * list.add(toMap("key", "value3"));
     *
     * List{@code } resultList = CollectionsUtil.getPropertyValueList(list, "(key)");
     * assertThat(resultList, contains("value1", "value2", "value3"));
     * 
* *
* *
list Iterable
*
* 比如 {@code List>} * * 示例: * *
     * List{@code >} list = newArrayList();
     * list.add(toList("小明", "18"));
     * list.add(toList("小宏", "18"));
     * list.add(toList("小振", "18"));
     *
     * List{@code } resultList = CollectionsUtil.getPropertyValueList(list, "[0]");
     * assertThat(resultList, contains("小明", "小宏", "小振"));
     * 
* *
* *
数组 Iterable
*
* 比如 {@code List} * * 示例: * *
     * List{@code } list = newArrayList();
     * list.add(toArray("三国", "水浒"));
     * list.add(toArray("西游", "金瓶梅"));
     *
     * List{@code } resultList = CollectionsUtil.getPropertyValueList(list, "[0]");
     * assertThat(resultList, contains("三国", "西游"));
     * 
* *
*
* *
* * @param * 返回集合类型 generic type * @param * 可迭代对象类型 generic type * @param beanIterable * 支持 * *
    *
  • bean Iterable,比如List{@code },Set{@code }等
  • *
  • map Iterable,比如{@code List>}
  • *
  • list Iterable , 比如 {@code List>}
  • *
  • 数组 Iterable ,比如 {@code List}
  • *
* * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @return 如果参数 beanIterable是null或者empty,会返回empty ArrayList
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException}
* @see PropertyValueObtainer#getPropertyValueCollection(Iterable, String, Collection) * @since jdk1.5 */ public static List getPropertyValueList(Iterable beanIterable,String propertyName){ if (isNullOrEmpty(beanIterable)){//避免null point return emptyList(); } return PropertyValueObtainer.getPropertyValueCollection(beanIterable, propertyName, new ArrayList(size(beanIterable))); } /** * 解析迭代集合 beanIterable ,取到对象指定的属性 propertyName的值,拼成{@link Set}({@link LinkedHashSet}). * *

说明:

*
*
    *
  1. 返回的是 {@link LinkedHashSet},顺序是参数 beanIterable 元素的顺序
  2. *
*
* *

示例:

*
* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User(2L));
     * list.add(new User(5L));
     * list.add(new User(5L));
     *
     * LOGGER.info(JsonUtil.format(CollectionsUtil.getPropertyValueSet(list, "id")));
     * 
* * 返回: * *
     * [2,5]
     * 
* *
* * @param * the generic type * @param * the generic type * @param beanIterable * 支持 * *
    *
  • bean Iterable,比如List{@code },Set{@code }等
  • *
  • map Iterable,比如{@code List>}
  • *
  • list Iterable , 比如 {@code List>}
  • *
  • 数组 Iterable ,比如 {@code List}
  • *
* @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @return 如果参数 beanIterable是null或者empty,会返回empty {@link LinkedHashSet}
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException}
* @see PropertyValueObtainer#getPropertyValueCollection(Iterable, String, Collection) * @since 1.0.8 */ public static Set getPropertyValueSet(Iterable beanIterable,String propertyName){ if (isNullOrEmpty(beanIterable)){//避免null point return emptySet(); } return PropertyValueObtainer.getPropertyValueCollection(beanIterable, propertyName, new LinkedHashSet(size(beanIterable))); } //----------------------------getPropertyValueMap----------------------------------- /** * 循环 beanIterable ,以 keyPropertyName属性值为key, valuePropertyName属性值为value,组成map返回. * *

说明:

*
*
    *
  1. 返回的是 {@link LinkedHashMap},顺序是参数 beanIterable 元素的顺序
  2. *
  3. 如果有元素 keyPropertyName属性值相同,那么后面的值会覆盖前面的值
  4. *
*
* *

示例:

*
* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     *
     * LOGGER.info(JsonUtil.format(CollectionsUtil.getPropertyValueMap(list, "name", "age")));
     * 
* * 返回: * *
     * {
     * "张飞": 23,
     * "关羽": 24,
     * "刘备": 25
     * }
     * 
* *
*

* 如果有元素 keyPropertyName属性值相同,那么后面的值会覆盖前面的值 *

* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("张飞", 25));
     *
     * LOGGER.info(JsonUtil.format(CollectionsUtil.getPropertyValueMap(list, "name", "age")));
     * 
* * 返回: * *
     * {
     * "张飞": 25,
     * "关羽": 24,
     * }
     * 
* *
* * @param * the key type * @param * the value type * @param * 可迭代对象类型 generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param keyPropertyName * 泛型O对象指定的属性名称,取到的值将作为返回的map的key,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param valuePropertyName * 泛型O对象指定的属性名称,取到的值将作为返回的map的value,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyMap()}
* 如果 keyPropertyName 是null,抛出 {@link NullPointerException}
* 如果 keyPropertyName 是blank,抛出 {@link IllegalArgumentException}
* 如果 valuePropertyName 是null,抛出 {@link NullPointerException}
* 如果 valuePropertyName 是blank,抛出 {@link IllegalArgumentException}
* @see com.feilong.core.bean.PropertyUtil#getProperty(Object, String) */ public static Map getPropertyValueMap(Iterable beanIterable,String keyPropertyName,String valuePropertyName){ if (isNullOrEmpty(beanIterable)){ return emptyMap(); } //--------------------------------------------------------------- Validate.notBlank(keyPropertyName, "keyPropertyName can't be null/empty!"); Validate.notBlank(valuePropertyName, "valuePropertyName can't be null/empty!"); Map map = newLinkedHashMap(size(beanIterable)); for (O bean : beanIterable){ map.put(PropertyUtil. getProperty(bean, keyPropertyName), PropertyUtil. getProperty(bean, valuePropertyName)); } return map; } //--------------------------------------------------------------- /** * 判断iterable中,是否存在 propertyName属性名称值是 propertyValue 的元素. * *

示例:

*
* *

* 场景: list中查找是否存在name是 关羽 的User对象 *

* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     * list.add(new User("关羽", 50));
     *
     * LOGGER.info(CollectionsUtil.exist(list, "name", "关羽"));
     * 
* * 返回: * *
     * true
     * 
* *
* * @param * the generic type * @param * the value type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param propertyValue * 指定的值 * @return 如果 iterable是null, 返回false
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException}
* 如果 iterable中没有相关元素的属性propertyName 值是propertyValue,返回false * @since 3.0.8 */ public static boolean exist(Iterable beanIterable,String propertyName,V propertyValue){ return null != find(beanIterable, propertyName, propertyValue); } /** * 判断是否存在 iterable中, propertyName属性名称和值是 propertyValue是 propertyNameAndPropertyValueMap 的对应元素. * *

示例:

*
* *

* 场景: 判断list中是否存在 name是 关羽,且年龄是24 的User对象 *

* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     * list.add(new User("关羽", 50));
     *
     * Map{@code } map = toMap("name", "关羽", "age", 24);
     * LOGGER.info(JsonUtil.format(CollectionsUtil.exist(list, map)));
     * 
* * 返回: * *
     * true
     * 
* *
* * @param * the generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyNameAndPropertyValueMap * 属性和指定属性值对应的map,其中key是泛型T对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @return 如果 iterable是null, 返回null
* 如果 propertyNameAndPropertyValueMap 是null,抛出 {@link NullPointerException}
* 如果 propertyNameAndPropertyValueMap 是empty,抛出{@link IllegalArgumentException}
* 如果 propertyNameAndPropertyValueMap 中有key是null,抛出{@link NullPointerException}
* 如果 propertyNameAndPropertyValueMap 中有key是blank,抛出{@link IllegalArgumentException}
* 如果 iterable中没有相关元素的属性propertyName 值是propertyValue,返回false * @since 3.0.8 */ public static boolean exist(Iterable beanIterable,Map propertyNameAndPropertyValueMap){ return null != find(beanIterable, propertyNameAndPropertyValueMap); } /** * 判断是否存在匹配predicate 的元素. * *

示例:

* *
* *

* 场景: 从list中查找name是 关羽,并且 age等于30的User对象是否存在 *

* *
     * List{@code } list = toList(//
     *                 new User("张飞", 23),
     *                 new User("关羽", 24),
     *                 new User("刘备", 25),
     *                 new User("关羽", 30));
     *
     * Map{@code } map = new HashMap{@code <>}();
     * map.put("name", "关羽");
     * map.put("age", 30);
     *
     * Predicate{@code } predicate = BeanPredicateUtil.equalPredicate(map);
     *
     * LOGGER.debug(JsonUtil.format(CollectionsUtil.exist(list, predicate)));
     * 
* * 返回: * *
     * true
     * 
* *
* * @param * the generic type * @param iterable * the iterable to search, may be null * @param predicate * the predicate to use, may not be null * @return 如果 predicate 是 null,将抛出{@link NullPointerException}
* 如果 iterable是null, 返回null
* 如果 iterable中没有相关元素匹配 predicate,返回false * @since 3.0.8 */ public static boolean exist(Iterable iterable,Predicate predicate){ return null != find(iterable, predicate); } //*************************find**************************************************************** /** * 找到 iterable中,第一个 propertyName属性名称值是 propertyValue 的对应元素. * *

示例:

*
* *

* 场景: 从list中查找name是 关羽 的User对象 *

* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     * list.add(new User("关羽", 50));
     *
     * LOGGER.info(JsonUtil.format(CollectionsUtil.find(list, "name", "关羽")));
     * 
* * 返回: * *
     * {
     * "age": 24,
     * "name": "关羽"
     * }
     * 
* *
* *

说明:

*
*
    *
  1. 返回第一个匹配对象
  2. *
*
* * @param * the generic type * @param * the value type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param propertyValue * 指定的值 * @return 如果 iterable是null, 返回null
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException}
* 如果 iterable中没有相关元素的属性propertyName 值是propertyValue,返回null * @see #find(Iterable, Predicate) * @see com.feilong.core.util.predicate.BeanPredicateUtil#equalPredicate(String, Object) */ public static O find(Iterable beanIterable,String propertyName,V propertyValue){ return null == beanIterable ? null : find(beanIterable, BeanPredicateUtil. equalPredicate(propertyName, propertyValue)); } /** * 找到 iterable中,第一个 propertyName属性名称和值是 propertyValue是 propertyNameAndPropertyValueMap 的对应元素. * *

示例:

*
* *

* 场景: 从list中查找name是 关羽,且年龄是24 的User对象 *

* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     * list.add(new User("关羽", 50));
     *
     * Map{@code } map = toMap("name", "关羽", "age", 24);
     * LOGGER.info(JsonUtil.format(CollectionsUtil.find(list, map)));
     * 
* * 返回: * *
     * {
     * "age": 24,
     * "name": "关羽"
     * }
     * 
* *
* *

说明:

*
*
    *
  1. 返回第一个匹配对象
  2. *
*
* * @param * the generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyNameAndPropertyValueMap * 属性和指定属性值对应的map,其中key是泛型T对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @return 如果 iterable是null, 返回null
* 如果 propertyNameAndPropertyValueMap 是null,抛出 {@link NullPointerException}
* 如果 propertyNameAndPropertyValueMap 是empty,抛出{@link IllegalArgumentException}
* 如果 propertyNameAndPropertyValueMap 中有key是null,抛出{@link NullPointerException}
* 如果 propertyNameAndPropertyValueMap 中有key是blank,抛出{@link IllegalArgumentException}
* 如果 iterable中没有相关元素的属性propertyName 值是propertyValue,返回null * @see #find(Iterable, Predicate) * @see com.feilong.core.util.predicate.BeanPredicateUtil#equalPredicate(String, Object) * @since 2.1.0 */ public static O find(Iterable beanIterable,Map propertyNameAndPropertyValueMap){ return null == beanIterable ? null : find(beanIterable, BeanPredicateUtil. equalPredicate(propertyNameAndPropertyValueMap)); } /** * 迭代查找匹配predicate 的第一个元素并返回. * *

示例:

* *
* *

* 场景: 从list中查找name是 关羽,并且 age等于30的User对象 *

* *
     * List{@code } list = toList(//
     *                 new User("张飞", 23),
     *                 new User("关羽", 24),
     *                 new User("刘备", 25),
     *                 new User("关羽", 30));
     *
     * Map{@code } map = new HashMap{@code <>}();
     * map.put("name", "关羽");
     * map.put("age", 30);
     *
     * Predicate{@code } predicate = BeanPredicateUtil.equalPredicate(map);
     *
     * User user = CollectionsUtil.find(list, predicate);
     * LOGGER.debug(JsonUtil.format(user));
     * 
* * 返回: * *
     * {
     * "age": 30,
     * "name": "关羽"
     * }
     * 
* *
* *

说明:

*
*
    *
  1. 返回第一个匹配对象
  2. *
*
* * @param * the generic type * @param iterable * the iterable to search, may be null * @param predicate * the predicate to use, may not be null * @return 如果 predicate 是 null,将抛出{@link NullPointerException}
* 如果 iterable是null, 返回null
* 如果 iterable中没有相关元素匹配 predicate,返回null * @see IterableUtils#find(Iterable, Predicate) * @since 1.5.5 */ public static O find(Iterable iterable,Predicate predicate){ return IterableUtils.find(iterable, predicate); } //**************************select***************************************************************** /** * 循环 beanIterable,获得元素 beanpropertyName的值,判断是否在propertyValues * 数组中;如果在,将该对象存入list中返回. * *

注意:

* *
*

* 查询的结果的顺序按照原来 beanIterable里面的顺序,和参数 propertyValues 无关,如果你需要结果里面的元素按照指定的propertyValues * 顺序排序的话,可以将结果再调用{@link SortUtil#sortListByFixedOrderPropertyValueArray(List, String, Object...)} *

*
* *

示例:

* *
* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     *
     * String[] array = { "刘备", "关羽" };
     * LOGGER.info(JsonUtil.format(CollectionsUtil.select(list, "name", array)));
     *
     * 
* * 返回: * *
       [{
               "age": 24,
               "name": "关羽"
           },{
               "age": 25,
               "name": "刘备"
       }]
     * 
* *
* * @param * the generic type * @param * the value type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param propertyValues * the values * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyList()}
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException}
* 如果 propertyValues 是null,返回 {@code new ArrayList}
* @see BeanPredicateUtil#containsPredicate(String, Object...) */ @SafeVarargs public static List select(Iterable beanIterable,String propertyName,V...propertyValues){ return isNullOrEmpty(beanIterable) ? Collections. emptyList() : select(beanIterable, BeanPredicateUtil. containsPredicate(propertyName, propertyValues)); } /** * 循环 beanIterable,获得元素 beanpropertyName的值,判断是否在propertyValueList * 集合中;如果在,将该对象存入list中返回. * *

说明:

*
*
    *
  1. 查询的结果的顺序按照原来 beanIterable里面的顺序,和参数 propertyValueList 无关,如果你需要结果里面的元素按照指定的 * propertyValueList顺序排序的话,可以将结果再调用{@link SortUtil#sortListByFixedOrderPropertyValueList(List, String, List)}
  2. *
  3. 和该方法正好相反的是 {@link #selectRejected(Iterable, String, Collection)}
  4. *
*
* *

示例:

* *
* *

* 场景: 查询 name属性是"张飞"或者是"刘备"的 User list *

* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     *
     * List{@code } propertyValueList = new ArrayList{@code <>}();
     * propertyValueList.add("张飞");
     * propertyValueList.add("刘备");
     * LOGGER.info(JsonUtil.format(CollectionsUtil.select(list, "name", propertyValueList)));
     * 
* * 返回: * *
    [{
                "age": 23,
                "name": "张飞"
            },{
                "age": 25,
                "name": "刘备"
     }]
     *
     * 
* *
* *

重构:

* *
*

* 对于以下代码: *

* *
     *
     * // 当前店铺 的物流方式Id set
     * Set{@code } distributionModeIdSet = new HashSet{@code <>}();
     * for (TemeplateDistributionMode tdCmd : temeplateDistributionModeList){
     *     distributionModeIdSet.add(tdCmd.getDistributionModeId());
     * }
     *
     * // 拿到所有的物流方式 列表
     * List{@code } distributionCommandList = freigthMemoryManager.getDistributionList();
     *
     * // 根据 物流方式ID 找出 支持本商铺的 DistributionCommand
     * List{@code } curShopDistributionCommandList = new ArrayList{@code <>}();
     *
     * for (Long modeId : distributionModeIdSet){
     *     for (DistributionCommand distributionCmd : distributionCommandList){
     *         if (modeId.equals(distributionCmd.getDistributionModeId())){
     *             curShopDistributionCommandList.add(distributionCmd);
     *         }
     *     }
     * }
     * 
* * 可以重构成: * *
     * // 当前店铺 的物流方式Id set
     * Set{@code } distributionModeIdSet = CollectionsUtil.getPropertyValueSet(temeplateDistributionModeList, "distributionModeId");
     * // 拿到所有的物流方式 列表
     * List{@code } distributionCommandList = freigthMemoryManager.getDistributionList();
     *
     * // 根据 物流方式ID 找出 支持本商铺的 DistributionCommand
     * List{@code } curShopDistributionCommandList = CollectionsUtil.select(distributionCommandList, "distributionModeId", distributionModeIdSet);
     * 
* *
* * @param * the generic type * @param * the value type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param propertyValueList * the values * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyList()}
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException}
* 否则调用 {@link #select(Iterable, Predicate)} * @see #select(Iterable, Predicate) * @see BeanPredicateUtil#containsPredicate(String, Collection) * @since 1.5.0 */ public static List select(Iterable beanIterable,String propertyName,Collection propertyValueList){ return isNullOrEmpty(beanIterable) ? Collections. emptyList() : select(beanIterable, BeanPredicateUtil. containsPredicate(propertyName, propertyValueList)); } /** * 按照指定的 {@link Predicate},返回查询出来的集合. * *

说明:

*
*
    *
  1. 和该方法正好相反的是 {@link #selectRejected(Iterable, Predicate)}
  2. *
*
* *

示例1:

*
* *

* 场景: 查找等于 1的元素 *

* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(1L);
     * list.add(1L);
     * list.add(2L);
     * list.add(3L);
     * LOGGER.info(JsonUtil.format(CollectionsUtil.select(list, new EqualPredicate{@code }(1L))));
     * 
* * 返回: * *
     * [1,1]
     * 
* *
* *

示例2:

*
* *

* 场景: 查找大于 10的元素 *

* *
     * Comparator{@code } comparator = ComparatorUtils.naturalComparator();
     * Predicate{@code } predicate = new ComparatorPredicate{@code }(10, comparator, Criterion.LESS);
     *
     * List{@code } select = CollectionsUtil.select(toList(1, 5, 10, 30, 55, 88, 1, 12, 3), predicate);
     * LOGGER.debug(JsonUtil.format(select, 0, 0));
     * 
* * 返回: * *
     * [30,55,88,12]
     * 
* *
* * @param * the generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param predicate * 接口封装了对输入对象的判断,返回true或者false,可用的实现类有 *
    *
  • {@link com.feilong.lib.collection4.functors.EqualPredicate EqualPredicate}
  • *
  • {@link com.feilong.lib.collection4.functors.IdentityPredicate IdentityPredicate}
  • *
  • {@link com.feilong.lib.collection4.functors.FalsePredicate FalsePredicate}
  • *
  • {@link com.feilong.lib.collection4.functors.TruePredicate TruePredicate}
  • *
  • ....
  • *
* @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyList()}
* 否则返回 {@link CollectionUtils#select(Iterable, Predicate)} * @see com.feilong.lib.collection4.CollectionUtils#select(Iterable, Predicate) */ public static List select(Iterable beanIterable,Predicate predicate){ return isNullOrEmpty(beanIterable) ? Collections. emptyList() : (List) CollectionUtils.select(beanIterable, predicate); } //***************************selectRejected********************************************************************* /** * 循环 beanIterable,获得元素 beanpropertyName 属性值都不在 * propertyValues 时候的list. * *

示例:

* *
* *

* 场景: 查询name 不是刘备 也不是张飞的 User list元素 *

* *
     *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     *
     * List{@code } selectRejected = CollectionsUtil.selectRejected(list, "name", "刘备", "张飞");
     * LOGGER.info(JsonUtil.format(selectRejected));
     *
     * 
* * 返回: * *
     * [{
     * "age": 24,
     * "name": "关羽"
     * }]
     * 
* *
* * @param * the generic type * @param * the value type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param propertyValues * the values * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyList()}
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException}
* @see BeanPredicateUtil#containsPredicate(String, Object...) * @see #selectRejected(Iterable, Predicate) */ @SafeVarargs public static List selectRejected(Iterable beanIterable,String propertyName,V...propertyValues){ return isNullOrEmpty(beanIterable) ? Collections. emptyList() : selectRejected(beanIterable, BeanPredicateUtil. containsPredicate(propertyName, propertyValues)); } /** * 循环 beanIterable,获得元素 beanpropertyName的值,判断是否不在propertyValueList * 集合中;如果不在,将该对象存入list中返回. * *

示例:

* *
* *

* 场景: 查询 name属性是不是"张飞",也不是"刘备"的 User list *

* *
     *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("关羽", 24));
     * list.add(new User("刘备", 25));
     *
     * List{@code } propertyValueList = new ArrayList{@code <>}();
     * propertyValueList.add("张飞");
     * propertyValueList.add("刘备");
     * LOGGER.info(JsonUtil.format(CollectionsUtil.selectRejected(list, "name", propertyValueList)));
     *
     * 
* * 返回: * *
     * [{
     * "age": 24,
     * "name": "关羽"
     * }]
     * 
* *
* *

说明:

*
*
    *
  1. 和该方法正好相反的是 {@link #select(Iterable, String, Collection)}
  2. *
*
* * @param * the generic type * @param * the value type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param propertyValueList * the values * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyList()}
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException} * @see BeanPredicateUtil#containsPredicate(String, Collection) * @see #selectRejected(Iterable, Predicate) * @since 1.5.0 */ public static List selectRejected(Iterable beanIterable,String propertyName,Collection propertyValueList){ return isNullOrEmpty(beanIterable) ? Collections. emptyList() : selectRejected(beanIterable, BeanPredicateUtil. containsPredicate(propertyName, propertyValueList)); } /** * 循环 beanIterable,获得元素 bean,判断是否不匹配predicate,如果不匹配 * ,将该对象存入list中返回. * *

说明:

*
*
    *
  1. 和该方法正好相反的是 {@link #select(Iterable, Predicate)}
  2. *
*
* *

示例:

* *
* *

* 场景: 从list中查找不等于1的元素 *

* *
     * List{@code } list = toList(1L, 1L, 2L, 3L);
     * CollectionsUtil.selectRejected(list, new EqualPredicate{@code }(1L))
     * 
* * 返回: * *
     * 2L, 3L
     * 
* *
* * @param * the generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param predicate * the predicate * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyMap()}
* @see com.feilong.lib.collection4.CollectionUtils#selectRejected(Iterable, Predicate) * @since 1.4.0 */ public static List selectRejected(Iterable beanIterable,Predicate predicate){ return isNullOrEmpty(beanIterable) ? Collections. emptyList() : (List) CollectionUtils.selectRejected(beanIterable, predicate); } //--------------------------------------------------------------- /** * 循环 inputIterable,将每个元素使用 transformer 转换成新的对象,返回新的list. * *

示例:

* *
* *
     *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add("xinge");
     * list.add("feilong1");
     * list.add("feilong2");
     * list.add("feilong2");
     *
     * Transformer{@code } nullTransformer = TransformerUtils.nullTransformer();
     * List{@code } collect = CollectionsUtil.collect(list, nullTransformer);
     * LOGGER.info(JsonUtil.format(collect, 0, 0));
     *
     * 
     *
     * 返回:
     *
     * 
     * [null,null,null,null]
     * 
* * * *

更多的,使用这个方法来处理两个不同类型的转换:

* *
*

* 比如购物车功能,有游客购物车CookieShoppingCartLine以及内存购物车对象 * ShoppingCartLineCommand,两个数据结构部分元素相同,
* 用户登陆需要把cookie中的购物车转成内存购物车ShoppingCartLineCommand list,这时我们可以先创建ToShoppingCartLineCommandTransformer *

* *

* 代码示例: *

* *
     *
     * class ToShoppingCartLineCommandTransformer implements Transformer{@code }{
     *
     *     private static final String[] COPY_PROPERTY_NAMES = {"skuId","extentionCode","quantity","createTime","settlementState","lineGroup" };
     *
     *     public ShoppingCartLineCommand transform(CookieShoppingCartLine cookieShoppingCartLine){
     *         // 将cookie中的购物车 转换为 shoppingCartLineCommand
     *         ShoppingCartLineCommand shoppingLineCommand = new ShoppingCartLineCommand();
     *         PropertyUtil.copyProperties(shoppingLineCommand, cookieShoppingCartLine, COPY_PROPERTY_NAMES);
     *
     *         shoppingLineCommand.setId(cookieShoppingCartLine.getId());
     *         shoppingLineCommand.setGift(null == cookieShoppingCartLine.getIsGift() ? false : cookieShoppingCartLine.getIsGift());
     *
     *         return shoppingLineCommand;
     *     }
     * }
     *
     * 
* *

* 然后调用: *

* *
     *
     * public List{@code } load(HttpServletRequest request){
     *     // 获取cookie中的购物车行集合
     *     List{@code } cookieShoppingCartLineList = getCookieShoppingCartLines(request);
     *     if (isNullOrEmpty(cookieShoppingCartLineList)){
     *         return null;
     *     }
     *
     *     return CollectionsUtil.collect(cookieShoppingCartLineList, new ToShoppingCartLineCommandTransformer());
     * }
     * 
* *
* * @param * the type of object in the input collection * @param * the type of object in the output collection * @param inputIterable * the inputIterable to get the input from * @param transformer * the transformer to use, may be null * @return 如果 inputIterable 是null,返回 null
* 如果 transformer 是null,返回 empty list * @see com.feilong.lib.collection4.CollectionUtils#collect(Iterable, Transformer) * @see com.feilong.lib.collection4.CollectionUtils#transform(Collection, Transformer) * @since 1.5.5 */ @SuppressWarnings("unchecked") public static List collect(final Iterable inputIterable,final Transformer transformer){ return null == inputIterable ? null : (List) CollectionUtils.collect(inputIterable, transformer); } /** * 循环 inputBeanIterable,将每个元素使用转换程成新的 outputListBeanType 类型对象(如有需要只copy传入的includePropertyNames属性) * 返回新的list. * *

示例:

* *
* 已知有以下两个类 User 和 Customer * *
     *
     * public class User{
     *
     *     // The id.
     *     private Long id = 0L;
     *
     *     //** The name.
     *     private String name = "feilong";
     *
     *     //** 年龄.
     *     private Integer age;
     *
     *     //setter /getter
     *
     *     public User(Long id, String name){
     *         this.id = id;
     *         this.name = name;
     *     }
     *
     * }
     *
     * 
* *
     *
     * public class Customer{
     *
     *     //** The id.
     *     private long id;
     *
     *     //* The name.
     *     private String name;
     *
     *     //setter /getter
     *
     * }
     *
     * 
* * 此时有以下的 List{@code } 需要转换成List{@code } * *
     *
     * List{@code } list = toList(//
     *                 new User(23L, "张飞"),
     *                 new User(24L, "关羽"),
     *                 new User(25L, "刘备"));
     * 
* * 以前你需要如此这般写: * *
     * List{@code } customerList = new ArrayList{@code <>}();
     * for (User user : list){
     *     Customer customer = new Customer();
     *     customer.setId(user.getId());
     *     customer.setName(user.getName());
     *     customerList.add(customer);
     * }
     * 
* *

* 如果属性很多,书写代码很繁琐 *

* *

* 此时你可以这么写: *

* *
     *  List{@code } customerList = CollectionsUtil.collect(list, Customer.class);
     * 
* *

* 一行代码搞定集合转换问题 *

* *

* 如果你只想转换id属性,你可以: *

* *
     *  List{@code } customerList = CollectionsUtil.collect(list, Customer.class,"id");
     * 
* *
* *

说明:

*
*
    *
  1. outputListBeanType 需要有默认的构造函数
  2. *
*
* * @param * the generic type * @param * the generic type * @param inputBeanIterable * 输入的input bean Iterable * @param outputListBeanType * 要转成Bean list的类型. * @param includePropertyNames * 包含的属性数组名字数组,(can be nested/indexed/mapped/combo),
* 如果是null或者empty,那么复制所有的属性
*
    *
  1. 如果传入的includePropertyNames,含有 inputBeanIterable bean 没有的属性名字,将会抛出异常
  2. *
  3. 如果传入的includePropertyNames,含有 inputBeanIterable * bean有,但是outputListBeanType没有的属性名字,会抛出异常,see * org.apache.commons.beanutils.PropertyUtilsBean#setSimpleProperty(Object, String, Object) copyProperties Line2078 *
  4. *
* @return 如果 inputBeanIterable 是null,返回 null
* 如果 inputBeanIterable 中有元素是null,那么返回的list对应位置的元素也是null
* 如果 outputListBeanType 是null,抛出 {@link NullPointerException}
* @since 1.10.1 */ public static List collect( final Iterable inputBeanIterable, final Class outputListBeanType, final String...includePropertyNames){ Validate.notNull(outputListBeanType, "outListBeanType can't be null!"); return collect(inputBeanIterable, new BeanTransformer<>(outputListBeanType, includePropertyNames)); } /** * 循环 inputIterator,将每个元素使用 transformer 转换成新的对象 返回新的list. * *

示例:

* *
* *

* 场景: 一个简单的将list中的所有元素转成null *

* *
     * List{@code } list = toList("xinge", "feilong1", "feilong2", "feilong2");
     *
     * Transformer{@code } nullTransformer = TransformerUtils.nullTransformer();
     * List{@code } collect = CollectionsUtil.collect(list.iterator(), nullTransformer);
     * LOGGER.info(JsonUtil.format(collect, 0, 0));
     * 
     *
     * 返回:
     *
     * 
     * [null,null,null,null]
     * 
* * * * @param * the type of object in the output collection * @param * the type of object in the input collection * @param inputIterator * the iterator to get the input from * @param transformer * the transformer to use, may be null * @return 如果 inputIterator 是null,返回 null
* 如果 transformer 是null,返回 {@code new ArrayList<>} * @see com.feilong.lib.collection4.CollectionUtils#collect(java.util.Iterator, Transformer) * @since 1.5.5 */ @SuppressWarnings("unchecked") public static List collect(final Iterator inputIterator,final Transformer transformer){ return null == inputIterator ? null : (List) CollectionUtils.collect(inputIterator, transformer); } //----------------------------group----------------------------------- /** * 循环 beanIterable,以 元素的 propertyName属性值为key,相同值的元素组成list作为value,封装成map返回. * *

说明:

*
*
    * *
  1. * 返回的{@link LinkedHashMap},key是 beanIterable中的元素对象中 propertyName的值,value是beanIterable * 中的元素对象; *
  2. * *
  3. 顺序是 beanIterable propertyName的值顺序,如果需要排序,可自行调用 {@link SortUtil#sortMapByKeyAsc(Map)}, * {@link SortUtil#sortMapByKeyDesc(Map)}, {@link SortUtil#sortMapByValueAsc(Map)}, {@link SortUtil#sortMapByValueDesc(Map)}或者, * {@link SortUtil#sortMap(Map, java.util.Comparator)}
  4. * *
  5. 属性propertyName值相同的元素,组成集合 list
  6. *
  7. 如果value只需要单值的话,可以调用 {@link #groupOne(Iterable, String)}方法
  8. *
*
* * *

示例:

*
* *
     * List{@code } list = toList(
     *                 new User("张飞", 23),
     *                 new User("刘备", 25),
     *                 new User("刘备", 30));
     *
     * Map{@code >} map = CollectionsUtil.group(list, "name");
     * LOGGER.debug(JsonUtil.format(map));
     * 
* * 返回: * *
    {
        "张飞": [ {
            "age": 23,
            "name": "张飞",
        }],
        "刘备": [
            {
                "age": 25,
                "name": "刘备",
            },
            {
                "age": 30,
                "name": "刘备",
            }
        ]
    }
     * 
* *
* * @param * 注意,此处的T是属性值,Object类型,如果从excel中读取的类型是String,那么不能简简单单的使用Integer来接收,不能强制转换 * @param * the generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyMap()}
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException} * @see #group(Iterable, String, Predicate) * @since 1.0.8 */ public static Map> group(Iterable beanIterable,String propertyName){ return group(beanIterable, propertyName, null); } /** * 循环 beanIterable,找到符合条件的 includePredicate的元素,以元素的 propertyName * 属性值为key,相同值的元素组成list作为value,封装成map返回. * *

说明:

*
*
    * *
  1. * 返回的{@link LinkedHashMap},key是 beanIterable中的元素对象中 propertyName的值,value是beanIterable * 中的元素对象; *
  2. * *
  3. * 顺序是 beanIterable propertyName的值顺序,如果需要排序,可自行调用 {@link SortUtil#sortMapByKeyAsc(Map)}, * {@link SortUtil#sortMapByKeyDesc(Map)}, {@link SortUtil#sortMapByValueAsc(Map)}, {@link SortUtil#sortMapByValueDesc(Map)}或者, * {@link SortUtil#sortMap(Map, java.util.Comparator)} *
  4. * *
*
* *

示例:

*
* *

* 场景: 将age {@code >} 20的User,按照name 进行 group *

* *
        List{@code } list = new ArrayList{@code <>}();
        list.add(new User("张飞", 10));
        list.add(new User("张飞", 28));
        list.add(new User("刘备", 32));
        list.add(new User("刘备", 30));
        list.add(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;
            }
        });
        LOGGER.info(JsonUtil.format(map));
     * 
* * 返回: * *
    {
        "张飞": [{
            "age": 28,
            "name": "张飞"
        }],
        "刘备": [{
                "age": 32,
                "name": "刘备"
            },{
                "age": 30,
                "name": "刘备"
            }
        ]
    }
     * 
* *

* 当然,对于上述代码,你还可以优化成: *

* *
     * Predicate{@code } comparatorPredicate = BeanPredicateUtil.comparatorPredicate("age", 20, Criterion.LESS);
     * Map{@code >} map = CollectionsUtil.group(list, "name", comparatorPredicate);
     * 
* * 参见 * {@link BeanPredicateUtil#comparatorPredicate(String, Comparable, com.feilong.lib.collection4.functors.ComparatorPredicate.Criterion)} * *
* * @param * 注意,此处的T是属性值,Object类型,如果从excel中读取的类型是String,那么不能简简单单的使用Integer来接收,不能强制转换 * @param * the generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @param includePredicate * the include predicate * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyMap()}
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException}
* 如果没有任何element match includePredicate,返回 empty {@link LinkedHashMap}
* 如果 includePredicate 是null,那么以所有的元素进行分组 * @see PropertyUtil#getProperty(Object, String) * @see #groupOne(Iterable, String) * @since 1.5.5 */ public static Map> group(Iterable beanIterable,final String propertyName,Predicate includePredicate){ if (isNullOrEmpty(beanIterable)){ return emptyMap(); } Validate.notBlank(propertyName, "propertyName can't be null/empty!"); //--------------------------------------------------------------- //org.apache.commons.beanutils.BeanToPropertyValueTransformer 但是实现的是 commons-collection3 return group( beanIterable, includePredicate, // input -> PropertyUtil.getProperty(input, propertyName)); } /** * 循环 beanIterable,将元素使用keyTransformer转成key,相同值的元素组成list作为value,封装成map返回. * *

说明:

*
*
    *
  1. * 返回的{@link LinkedHashMap},key是 beanIterable中的元素 使用keyTransformer转换的值,value是 * beanIterable中的元素对象(相同key值,组成list); *
  2. * *
  3. * 返回的{@link LinkedHashMap}顺序,是 beanIterable 元素顺序,如果需要排序,可自行调用 {@link SortUtil#sortMapByKeyAsc(Map)}, * {@link SortUtil#sortMapByKeyDesc(Map)}, {@link SortUtil#sortMapByValueAsc(Map)}, {@link SortUtil#sortMapByValueDesc(Map)}或者, * {@link SortUtil#sortMap(Map, java.util.Comparator)} *
  4. * *
*
* * *

示例:

* *
* *

* 场景: 从user list中,提取user的姓名的姓为key,user组成list,返回map *

* *
     *
     * User mateng55 = new User("马腾", 55);
     * User machao28 = new User("马超", 28);
     * User madai27 = new User("马岱", 27);
     * User maxiu25 = new User("马休", 25);
     * User zhangfei28 = new User("张飞", 28);
     * User liubei32 = new User("刘备", 32);
     * User guanyu50 = new User("关羽", 50);
     * User guanping32 = new User("关平", 32);
     * User guansuo31 = new User("关索", 31);
     * User guanxing20 = new User("关兴", 18);
     *
     * //---------------------------------------------------------------
     * List{@code } list = toList(mateng55, machao28, madai27, maxiu25, zhangfei28, liubei32, guanyu50, guanping32, guansuo31, guanxing20);
     *
     * //---------------------------------------------------------------
     *
     * Map{@code >} map = CollectionsUtil.group(list,new Transformer{@code }(){
     *
     *     @Override
     *     public String transform(User user){
     *         //提取名字 的姓
     *         return user.getName().substring(0, 1);
     *     }
     * });
     *
     * LOGGER.debug(JsonUtil.format(map));
     *
     * 
* * 返回: * *
    {
        "马":[{
                "age": 55,
                "name": "马腾",
            },{
                "age": 28,
                "name": "马超",
            },{
                "age": 27,
                "name": "马岱",
            },{
                "age": 25,
                "name": "马休",
            }
        ],
        "张": [{
            "age": 28,
            "name": "张飞",
        }],
        "刘": [{
            "age": 32,
            "name": "刘备",
        }],
        "关": [{
                "age": 50,
                "name": "关羽",
            },{
                "age": 32,
                "name": "关平",
            },{
                "age": 31,
                "name": "关索",
            },{
                "age": 18,
                "name": "关兴",
            }
        ]
    }
     * 
* *
* * @param * the generic type * @param * the generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param keyTransformer * 返回的map,key转换器 * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyMap()}
* 如果 keyTransformer 是null,抛出 {@link NullPointerException}
* @see List to Map 实现类似矩阵的逻辑 by ananbeike * @since 1.8.8 */ public static Map> group(Iterable beanIterable,Transformer keyTransformer){ return group(beanIterable, null, keyTransformer); } /** * 循环 beanIterable,找到符合条件的 includePredicate的元素,将元素使用keyTransformer转成key * ,相同值的元素组成list作为value,封装成map返回. * *

说明:

*
*
    *
  1. * 返回的{@link LinkedHashMap},key是 beanIterable中的元素 使用keyTransformer转换的值,value是 * beanIterable中的元素对象(相同key值,组成list); *
  2. * *
  3. * 返回的{@link LinkedHashMap}顺序,是 beanIterable 元素顺序,如果需要排序,可自行调用 {@link SortUtil#sortMapByKeyAsc(Map)}, * {@link SortUtil#sortMapByKeyDesc(Map)}, {@link SortUtil#sortMapByValueAsc(Map)}, {@link SortUtil#sortMapByValueDesc(Map)}或者, * {@link SortUtil#sortMap(Map, java.util.Comparator)} *
  4. * *
*
* * *

示例:

* *
* *

* 场景: 从user list中,提取 年龄 大于20的user,user的姓名的姓为key,user组成list,返回map *

* *
     *
     * User mateng55 = new User("马腾", 55);
     * User machao28 = new User("马超", 28);
     * User madai27 = new User("马岱", 27);
     * User maxiu25 = new User("马休", 25);
     * User zhangfei28 = new User("张飞", 28);
     * User liubei32 = new User("刘备", 32);
     * User guanyu50 = new User("关羽", 50);
     * User guanping32 = new User("关平", 32);
     * User guansuo31 = new User("关索", 31);
     * User guanxing20 = new User("关兴", 18);
     *
     * //---------------------------------------------------------------
     * List{@code } list = toList(mateng55, machao28, madai27, maxiu25, zhangfei28, liubei32, guanyu50, guanping32, guansuo31, guanxing20);
     *
     * //---------------------------------------------------------------
     *
     * Predicate{@code } comparatorPredicate = BeanPredicateUtil.comparatorPredicate("age", 20, Criterion.LESS);
     * Map{@code >} map = CollectionsUtil.group(list, comparatorPredicate, new Transformer{@code }(){
     *
     *     @Override
     *     public String transform(User user){
     *         //提取名字 的姓
     *         return user.getName().substring(0, 1);
     *     }
     * });
     *
     * LOGGER.debug(JsonUtil.format(map));
     *
     * 
* * 返回: * *
    {
            "马":[{
                    "age": 55,
                    "name": "马腾",
                },{
                    "age": 28,
                    "name": "马超",
                },{
                    "age": 27,
                    "name": "马岱",
                },{
                    "age": 25,
                    "name": "马休"
                }],
            "张": [{
                "age": 28,
                "name": "张飞"
            }],
            "刘": [{
                "age": 32,
                "name": "刘备"
            }],
            "关": [{
                    "age": 50,
                    "name": "关羽"
                },{
                    "age": 32,
                    "name": "关平"
                },{
                    "age": 31,
                    "name": "关索"
                }]
        }
     * 
* *
* * @param * the generic type * @param * the generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param includePredicate * the include predicate * @param keyTransformer * 返回的map,key转换器 * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyMap()}
* 如果 keyTransformer 是null,抛出 {@link NullPointerException}
* 如果 includePredicate 是null,那么以所有的元素进行分组
* 如果没有任何element match includePredicate,返回 empty {@link LinkedHashMap}
* @see org.apache.commons.collections4.Transformer#transform(Object) * @see List to Map 实现类似矩阵的逻辑 by ananbeike * @since 1.8.8 */ public static Map> group(Iterable beanIterable,Predicate includePredicate,Transformer keyTransformer){ if (isNullOrEmpty(beanIterable)){ return emptyMap(); } Validate.notNull(keyTransformer, "keyTransformer can't be null!"); //--------------------------------------------------------------- Map> map = newLinkedHashMap(size(beanIterable)); for (O obj : beanIterable){ if (null != includePredicate && !includePredicate.evaluate(obj)){ continue; } MapUtil.putMultiValue(map, keyTransformer.transform(obj), obj); } return map; } /** * 循环 iterable,以元素的 propertyName属性值为key,元素为value,封装成map返回(map只put第一个匹配的元素,后面出现相同的元素将会忽略). * *

说明:

*
*
    *
  1. 返回的{@link LinkedHashMap},key是 iterable中的元素对象中 propertyName的值,value是 * beanIterable中的元素对象;
  2. * *
  3. 顺序是 beanIterable propertyName的值 顺序,如果需要排序,可自行调用 {@link SortUtil#sortMapByKeyAsc(Map)}, * {@link SortUtil#sortMapByKeyDesc(Map)}, {@link SortUtil#sortMapByValueAsc(Map)}, {@link SortUtil#sortMapByValueDesc(Map)}或者, * {@link SortUtil#sortMap(Map, java.util.Comparator)}
  4. * *
  5. 间接的可以做到基于某个属性值去重的效果
  6. *
  7. 如果value需要是集合的话,可以调用 {@link #group(Iterable, String)}方法
  8. *
*
* *

示例:

*
* *
     * List{@code } list = new ArrayList{@code <>}();
     * list.add(new User("张飞", 23));
     * list.add(new User("刘备", 25));
     * list.add(new User("刘备", 30));
     *
     * Map{@code } map = CollectionsUtil.groupOne(list, "name");
     * LOGGER.info(JsonUtil.format(map));
     * 
* * 返回: * *
     * {
        "张飞":         {
            "age": 23,
            "name": "张飞"
        },
        "刘备":         {
            "age": 25,
            "name": "刘备"
        }
    }
     * 
* *
* * @param * the generic type * @param * the generic type * @param beanIterable * bean Iterable,诸如List{@code },Set{@code }等 * @param propertyName * 泛型O对象指定的属性名称,Possibly indexed and/or nested name of the property to be modified,参见 * propertyName * @return 如果 beanIterable 是null或者empty,返回 {@link Collections#emptyMap()}
* 如果 propertyName 是null,抛出 {@link NullPointerException}
* 如果 propertyName 是blank,抛出 {@link IllegalArgumentException} * @see #group(Iterable, String) * @since 1.0.8 */ public static Map groupOne(Iterable beanIterable,String propertyName){ if (isNullOrEmpty(beanIterable)){ return emptyMap(); } Validate.notBlank(propertyName, "propertyName can't be null/empty!"); //--------------------------------------------------------------- Map map = newLinkedHashMap(size(beanIterable)); for (O o : beanIterable){ T key = PropertyUtil.getProperty(o, propertyName); if (!map.containsKey(key)){ map.put(key, o); }else{ if (LOGGER.isTraceEnabled()){ LOGGER.trace("map:[{}] already has the key:[{}],ignore!", map.keySet(), key); } } } return map; } //------------------list--------------------------------------------- /** * 创建 a mutable, empty {@code ArrayList} instance . * * @param * the element type * @return the array list * @since 1.10.7 */ public static List newArrayList(){ return new ArrayList<>(); } /** * 创建 a mutable, empty {@code LinkedList} instance . * * @param * the element type * @return the linked list * @since 1.10.7 */ public static List newLinkedList(){ return new LinkedList<>(); } /** * 创建 a mutable, empty {@code CopyOnWriteArrayList} instance . * * @param * the element type * @return a new, empty {@code CopyOnWriteArrayList} * @since 1.10.7 */ public static List newCopyOnWriteArrayList(){ return new CopyOnWriteArrayList<>(); } //--------------------set------------------------------------------- /** * 创建 a mutable, empty {@code newHashSet} instance . * * @param * the element type * @return the hash set * @since 1.10.7 */ public static Set newHashSet(){ return new HashSet<>(); } /** * 创建 a mutable, empty {@code LinkedHashSet} instance . * * @param * the element type * @return a new, empty {@code LinkedHashSet} * @since 1.10.7 */ public static Set newLinkedHashSet(){ return new LinkedHashSet<>(); } }