Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
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.
/*
* 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关系图:
*
*
*
*
*
*
*
* 关于 {@link java.util.Collection}:
*
*
*
*
* 字段
* 说明
*
*
* {@link java.util.Collection Collection}
*
*
* 一组对象的集合,一般不直接使用
* 有 {@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}方法
* 没有get()方法.只能通过iterator()遍历元素
*
*
*
*
*
*
* 关于 {@link java.util.List}:
*
*
*
*
* interface/class
* 说明
*
*
* {@link java.util.List List}
*
*
* An ordered collection
* integer index for insert and search.
* 除了继承Collection接口方法外,有自己的方法定义: get(int) indexOf lastIndexOf listIterator set(int) subList(int,int)
* optional:可空,可重复
*
*
*
*
* {@link java.util.ArrayList ArrayList}
*
*
* Resizable-array implementation of the List interface
* 元素可空
* 有自己控制容量(数组大小)的方法
*
*
* 扩容:
*
*
*
* see {@link java.util.ArrayList#ensureCapacity(int)},
* 在jdk1.6里面,int newCapacity = (oldCapacity * 3)/2 + 1 通常是1.5倍
* 在jdk1.7+里面,代码进行了优化
*
*
*
*
*
* {@link java.util.LinkedList LinkedList}
*
*
* Linked list implementation,双向链表
* 元素可空
*
*
*
*
* {@link java.util.Vector Vector}
*
*
* growable array of objects
* 线程安全的动态数组 synchronized
* 操作基本和ArrayList相同
*
*
*
*
* {@link java.util.Stack Stack}
*
*
* last-in-first-out (LIFO) stack of objects
*
*
*
*
*
*
*
*
* 关于 {@link Set }:
*
*
*
*
* interface/class
* 说明
*
*
* {@link java.util.Set Set}
*
*
* A collection contains no duplicate elements
* Set和Collection拥有一模一样的接口名称
*
*
*
*
* {@link java.util.HashSet HashSet}
*
*
* backed by a HashMap instance.
* makes no guarantees as to the iteration order of the set; 不保证顺序
* permits the null element.允许空元素
*
*
*
*
* {@link java.util.LinkedHashSet LinkedHashSet}
*
*
* Hash Map and linked list implementation of the Set interface,
* with predictable iteration order
*
*
*
*
* {@link java.util.TreeSet TreeSet}
*
*
* A NavigableSet implementation based on a TreeMap.
* ordered using their natural ordering, or by a Comparator provided at set creation time
*
*
*
*
* {@link java.util.EnumSet EnumSet}
*
*
* A specialized Set implementation for use with enum types.
* Null elements are not permitted.
* natural order (the order in which the enum constants are declared.
* abstract class.
* 以位向量的形式存储,这种存储形式非常紧凑,高效,占用内存很小,运行效率很好.
*
*
*
*
*
*
*
*
* 关于 {@link java.util.Queue Queue}:
*
*
*
*
* interface/class
* 说明
*
*
* {@link java.util.Queue Queue}
*
*
* Queues typically, but do not necessarily,order elements in a FIFO (first-in-first-out) manner
*
*
*
*
*
*
*
*
*
*
* 天下人都知道Set,Map不能重复
* 80%人知道hashCode,equals是判断重复的法则
* 40%人知道Set添加重复元素时,旧元素不会被覆盖
* 20%人知道Map添加重复键时,旧键不会被覆盖,而值会覆盖
*
*
*
* guava 实用方法:
*
*
* com.google.common.collect.Iterables.concat({@code Iterable>})
*
*
*
* @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);
*
*
*
*
* 说明:
*
*
* 如果 beanIterable
是null或者empty,什么都不做
* 如果 beanIterable
中有元素是null,将跳过去
*
*
*
* @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
*
*
*
*
* 说明:
*
*
* 常用于 浏览历史记录,当前的商品id是否在历史记录中第一条位置,如果是,可能就不会操作Cookie,诸如此类的操作
*
*
*
* @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
(原集合对象不变) .
*
* 说明:
*
*
* 返回剩余的集合 (原集合对象objectCollection
不变) ,如果你不想修改 objectCollection
的话,不能直接调用
* collection.removeAll(remove);
,这个方法非常有用.
* 底层实现是调用的 {@link ListUtils#removeAll(Collection, Collection)},将不是removeElement
的元素加入到新的list返回.
*
*
*
* 示例:
*
*
*
*
* 场景: 从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
元素 (原集合对象不变) .
*
* 说明:
*
*
*
* 返回剩余的集合 (原集合对象objectCollection
不变) ,如果你不想修改 objectCollection
的话,不能直接调用
* collection.removeAll(remove);
,这个方法非常有用.
* 底层实现是调用的 {@link ListUtils#removeAll(Collection, Collection)},将不是removeElement
的元素加入到新的list返回.
*
*
*
*
* 示例:
*
*
*
*
* 场景: 从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
(原集合对象不变) .
*
* 说明:
*
*
* 返回剩余的集合 (原集合对象不变) ,这个方法非常有用,如果你不想修改 collection
的话,不能调用
* collection.remove(removeElements);
.
* 底层实现是调用的 {@link ListUtils#removeAll(Collection, Collection)},将不是removeElements
的元素加入到新的list返回.
*
*
*
* 示例:
*
*
*
* 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"]
*
*
*
*
* 注意:
*
*
* 如果原 objectCollection
是有序的,那么返回的结果参照原 objectCollection
元素顺序
* 原 objectCollection
不变
*
*
*
* @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());
*
*
*
*
* 注意:
*
*
* 如果原 objectCollection
是有序的,那么返回的结果参照原 objectCollection
元素顺序
* 原 objectCollection
不变
*
*
*
* @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());
*
*
*
*
*
* 注意:
*
*
* 如果原 objectCollection
是有序的,那么返回的结果参照原 objectCollection
元素顺序
* 原 objectCollection
不变
*
*
*
* @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}).
*
* 说明:
*
*
* 返回的是 {@link LinkedHashSet},顺序是参数 beanIterable
元素的顺序
*
*
*
* 示例:
*
*
*
* 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返回.
*
* 说明:
*
*
* 返回的是 {@link LinkedHashMap},顺序是参数 beanIterable
元素的顺序
* 如果有元素 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")));
*
*
* 返回:
*
*
* {
* "张飞": 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": "关羽"
* }
*
*
*
*
* 说明:
*
*
* 返回第一个匹配对象
*
*
*
* @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": "关羽"
* }
*
*
*
*
* 说明:
*
*
* 返回第一个匹配对象
*
*
*
* @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": "关羽"
* }
*
*
*
*
* 说明:
*
*
* 返回第一个匹配对象
*
*
*
* @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
,获得元素 bean
的 propertyName
的值,判断是否在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
,获得元素 bean
的propertyName
的值,判断是否在propertyValueList
* 集合中;如果在,将该对象存入list中返回.
*
* 说明:
*
*
* 查询的结果的顺序按照原来 beanIterable
里面的顺序,和参数 propertyValueList
无关,如果你需要结果里面的元素按照指定的
* propertyValueList
顺序排序的话,可以将结果再调用{@link SortUtil#sortListByFixedOrderPropertyValueList(List, String, List)}
* 和该方法正好相反的是 {@link #selectRejected(Iterable, String, Collection)}
*
*
*
* 示例:
*
*
*
*
* 场景: 查询 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},返回查询出来的集合.
*
* 说明:
*
*
* 和该方法正好相反的是 {@link #selectRejected(Iterable, Predicate)}
*
*
*
* 示例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
,获得元素 bean
的 propertyName
属性值都不在
* 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
,获得元素 bean
的 propertyName
的值,判断是否不在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": "关羽"
* }]
*
*
*
*
* 说明:
*
*
* 和该方法正好相反的是 {@link #select(Iterable, String, Collection)}
*
*
*
* @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中返回.
*
* 说明:
*
*
* 和该方法正好相反的是 {@link #select(Iterable, Predicate)}
*
*
*
* 示例:
*
*
*
*
* 场景: 从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");
*
*
*
*
* 说明:
*
*
* outputListBeanType 需要有默认的构造函数
*
*
*
* @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,那么复制所有的属性
*
* 如果传入的includePropertyNames
,含有 inputBeanIterable
bean 没有的属性名字,将会抛出异常
* 如果传入的includePropertyNames
,含有 inputBeanIterable
* bean有,但是outputListBeanType
没有的属性名字,会抛出异常,see
* org.apache.commons.beanutils.PropertyUtilsBean#setSimpleProperty(Object, String, Object) copyProperties Line2078
*
*
* @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返回.
*
* 说明:
*
*
*
*
* 返回的{@link LinkedHashMap},key是 beanIterable
中的元素对象中 propertyName
的值,value是beanIterable
* 中的元素对象;
*
*
* 顺序是 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)}
*
* 属性propertyName
值相同的元素,组成集合 list
* 如果value只需要单值的话,可以调用 {@link #groupOne(Iterable, String)}方法
*
*
*
*
* 示例:
*
*
*
* 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返回.
*
* 说明:
*
*
*
*
* 返回的{@link LinkedHashMap},key是 beanIterable
中的元素对象中 propertyName
的值,value是beanIterable
* 中的元素对象;
*
*
*
* 顺序是 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)}
*
*
*
*
*
* 示例:
*
*
*
* 场景: 将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返回.
*
* 说明:
*
*
*
* 返回的{@link LinkedHashMap},key是 beanIterable
中的元素 使用keyTransformer
转换的值,value是
* beanIterable
中的元素对象(相同key值,组成list);
*
*
*
* 返回的{@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)}
*
*
*
*
*
*
* 示例:
*
*
*
*
* 场景: 从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返回.
*
* 说明:
*
*
*
* 返回的{@link LinkedHashMap},key是 beanIterable
中的元素 使用keyTransformer
转换的值,value是
* beanIterable
中的元素对象(相同key值,组成list);
*
*
*
* 返回的{@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)}
*
*
*
*
*
*
* 示例:
*
*
*
*
* 场景: 从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第一个匹配的元素,后面出现相同的元素将会忽略 ).
*
* 说明:
*
*
* 返回的{@link LinkedHashMap},key是 iterable
中的元素对象中 propertyName
的值,value是
* beanIterable
中的元素对象;
*
* 顺序是 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)}
*
* 间接的可以做到基于某个属性值去重的效果
* 如果value需要是集合的话,可以调用 {@link #group(Iterable, String)}方法
*
*
*
* 示例:
*
*
*
* 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