
com.feilong.core.util.CollectionsUtil Maven / Gradle / Ivy
Show all versions of feilong Show documentation
/*
* 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 java.util.function.Function;
import java.util.stream.Collectors;
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.lang.StringUtil;
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;
import com.feilong.lib.lang3.tuple.Pair;
/**
* {@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现代诗一首
*
*
*
* - 天下人都知道Set,Map不能重复
* - 80%人知道hashCode,equals是判断重复的法则
* - 40%人知道Set添加重复元素时,旧元素不会被覆盖
* - 20%人知道Map添加重复键时,旧键不会被覆盖,而值会覆盖
*
*
*
* guava 实用方法:
*
*
* - com.google.common.collect.Iterables.concat({@code Iterable extends Iterable extends T>>})
*
*
*
* @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)}.
*
* 返回 iterable
{@link Iterator} 里面的第一个元素,如果没有,会抛出 IndexOutOfBoundsException
.
*
*
* 如果 {@link Iterable}是个 {@link List}, 会使用 {@link List#get(int)}.
*
*
*
* 示例:
*
*
*
*
*
* CollectionsUtil.first(toList(1, 2, 3)); = 1
*
*
*
*
*
* @param
* the type of object in the {@link Iterable}.
* @param iterable
* the {@link Iterable} to get a value from, may be null
* @return 如果 iterable
是null,抛出 {@link NullPointerException}
* @throws IndexOutOfBoundsException
* if the request is invalid
* @since 3.0.6
*/
public static T first(final Iterable iterable){
return get(iterable, 0);
}
/**
* 返回 iterable
{@link Iterator} 里面的最后元素,如果没有,会抛出 IndexOutOfBoundsException
.
*
* 如果 {@link Iterable}是个 {@link List}, 会使用 {@link List#get(int)}.
*
*
* 示例:
*
*
*
*
*
* CollectionsUtil.last(toList(1, 2, 3)); = 3
*
*
*
*
*
* @param
* the type of object in the {@link Iterable}.
* @param iterable
* the {@link Iterable} to get a value from, may be null
* @return 如果 iterable
是null,抛出 {@link NullPointerException}
* @throws IndexOutOfBoundsException
* if the request is invalid
* @since 3.5.0
*/
public static T last(final Iterable iterable){
return get(iterable, size(iterable) - 1);
}
/**
* Returns the index
-th value in the iterable
's {@link Iterator}, throwing
* IndexOutOfBoundsException
if there is no such element.
*
* 如果 {@link Iterable}是个 {@link List}, 会使用 {@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 如果 iterable
是null,抛出 {@link NullPointerException}
* @throws IndexOutOfBoundsException
* if the index is invalid
* @since 3.0.6
*/
public static T get(final Iterable iterable,final int index){
Validate.notNull(iterable, "iterable can't be null!");
return IterableUtils.get(iterable, index);
}
/**
* 循环 iterable
, 判断元素和参数 element
是否equals, 如果有equals,那么返回true,否则返回false.
*
*
* 使用循环每个元素,然后equals判断
*
*
* 示例:
*
*
*
*
*
* CollectionsUtil.contains(toList("track", "debug"), "debug") = true
*
*
*
*
*
* @param
*
* @param iterable
* the iterable
* @param element
* the element
* @return 如果 iterable
是null或者empty,返回 false
* @see com.feilong.lib.collection4.IterableUtils#contains(Iterable, Object, org.apache.commons.collections4.Equator)
* @see com.feilong.lib.collection4.IterableUtils#contains(Iterable, Object)
* @since 4.0.1
*/
public static boolean contains(final Iterable iterable,final T element){
if (isNullOrEmpty(iterable)){
return false;
}
for (T t : iterable){
if (Objects.equals(t, element)){
return true;
}
}
return false;
}
/**
* 循环 iterable
, 判断元素和参数 element
去空且忽视大小写后是否相等, 如果有相等的,那么返回true.
*
* 示例:
*
*
*
*
*
* CollectionsUtil.containsTrimAndIgnoreCase(toList("track", "debug"), " debug") = true
* CollectionsUtil.containsTrimAndIgnoreCase(toList("track", "DEBUG"), " debug") = true
* CollectionsUtil.containsTrimAndIgnoreCase(toList("track", " debug"), " debug") = true
*
*
*
*
*
* 重构:
*
*
*
* 对于以下代码:
*
*
*
* return (StringUtil.trimAndEqualsIgnoreCase(logLevel, "track") //
* || StringUtil.trimAndEqualsIgnoreCase(logLevel, "debug"));
*
*
*
* 可以重构成:
*
*
* return CollectionsUtil.containsTrimAndIgnoreCase(toList("track", "debug"), logLevel);
*
*
*
*
* @param iterable
* the iterable
* @param element
* the element
* @return 如果 iterable
是null或者empty,返回 false
* @since 3.3.4
*/
public static boolean containsTrimAndIgnoreCase(final Iterable iterable,final String element){
if (isNullOrEmpty(iterable)){
return false;
}
for (String string : iterable){
if (StringUtil.trimAndEqualsIgnoreCase(string, element)){
return true;
}
}
return false;
}
//---------------------------------------------------------------
/**
* 循环将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 extends O> iterable){
Validate.notNull(objectCollection, "objectCollection can't be null!");
return null != iterable && CollectionUtils.addAll(objectCollection, iterable);
}
/**
* 添加一堆 elements
元素到指定的objectCollection
,如果其中element
null或者 empty元素将忽略.
*
* 重构:
*
*
*
* 对于以下代码:
*
*
*
* List{@code
*
* 可以重构成:
*
*
*
* List{@code
*
* 重构之后,方法的复杂度会更小,阅读性更高
*
*
*
* 什么情况下元素不是null或者不是empty 但是没有添加进objectCollection
:
*
*
* (Returns false if this collection does not permit duplicates and already contains the specified element.)
*
* 如果 objectCollection
是个不允许重复元素,并且已经有了要加入的元素, 那么就添加不进去
*
*
*
* Collections that support this operation may place limitations on what elements may be added to this collection. In particular, some
* collections will refuse to add null elements, and others will impose restrictions on the type of elements that may be added.
* Collection classes should clearly specify in their documentation any restrictions on what elements may be added.
*
*
*
* If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an
* exception (rather than returning false). This preserves the invariant that a collection always contains the specified element after
* this call returns.
*
*
*
*
* @param
* the generic type
* @param objectCollection
* the collection to add to, 不能为null
* @param elements
* 循环要add 的元素
* @return a boolean 标识 objectCollection
是否改变,如果改变了,返回true.
* 如果 objectCollection
是null,抛出 {@link NullPointerException}
* 如果 elements
是null 或者 empty,直接返回false
* 否则循环调用objectCollection.add(object)
* @see com.feilong.lib.collection4.CollectionUtils#addIgnoreNull(Collection, Object)
* @since 1.8.2
* @since 3.2.1 change to variable argument
*/
public static boolean addIgnoreNullOrEmpty(final Collection objectCollection,final T...elements){
Validate.notNull(objectCollection, "objectCollection can't be null!");
if (isNullOrEmpty(elements)){
return false;
}
//---------------------------------------------------------------
//默认没有改变
boolean result = false;
for (T element : elements){
if (isNullOrEmpty(element)){
continue;
}
if (objectCollection.add(element)){
result = true; //添加进去了 表示改变了
}
}
return result;
}
/**
* 添加 elementIterable
里面的元素到指定的objectCollection
,如果其中element
null或者 empty元素将忽略.
*
* 什么情况下元素不是null或者不是empty 但是没有添加进objectCollection
:
*
*
* (Returns false if this collection does not permit duplicates and already contains the specified element.)
*
* 如果 objectCollection
是个不允许重复元素,并且已经有了要加入的元素, 那么就添加不进去
*
*
*
* Collections that support this operation may place limitations on what elements may be added to this collection. In particular, some
* collections will refuse to add null elements, and others will impose restrictions on the type of elements that may be added.
* Collection classes should clearly specify in their documentation any restrictions on what elements may be added.
*
*
*
* If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an
* exception (rather than returning false). This preserves the invariant that a collection always contains the specified element after
* this call returns.
*
*
*
*
* @param
* the generic type
* @param objectCollection
* the collection to add to, 不能为null
* @param elementIterable
* 循环要add 的元素
* @return a boolean 标识 objectCollection
是否改变,如果改变了,返回true.
* 如果 objectCollection
是null,抛出 {@link NullPointerException}
* 如果 elementIterable
是null 或者 empty,直接返回false
* 否则循环调用objectCollection.add(object)
* @see com.feilong.lib.collection4.CollectionUtils#addIgnoreNull(Collection, Object)
* @since 3.3.9
*/
public static boolean addIgnoreNullOrEmpty(final Collection objectCollection,final Iterable elementIterable){
Validate.notNull(objectCollection, "objectCollection can't be null!");
if (isNullOrEmpty(elementIterable)){
return false;
}
//默认没有改变
boolean result = false;
for (T element : elementIterable){
if (isNullOrEmpty(element)){
continue;
}
if (objectCollection.add(element)){
result = true; //添加进去了 表示改变了
}
}
return result;
}
/**
* 在condition 是true的情况下, 添加 element
元素到指定的objectCollection
.
*
* 重构:
*
*
*
* 对于以下代码:
*
*
*
* if (lib.getEnableXimaTeach() == 1){
* bookIds.add(ximaTeach);
* }
*
*
*
* 可以重构成:
*
*
*
* addIfCondition(bookIds, ximaTeach, lib.getEnableXimaTeach() == 1);
*
*
* 重构之后,一行可以搞定,代码阅读性更高
*
*
*
* 什么情况下condition是true, 但是没有添加进objectCollection
:
*
*
* (Returns false if this collection does not permit duplicates and already contains the specified element.)
*
* 如果 objectCollection
是个不允许重复元素,并且已经有了要加入的元素, 那么就添加不进去
*
*
*
* Collections that support this operation may place limitations on what elements may be added to this collection. In particular, some
* collections will refuse to add null elements, and others will impose restrictions on the type of elements that may be added.
* Collection classes should clearly specify in their documentation any restrictions on what elements may be added.
*
*
*
* If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an
* exception (rather than returning false). This preserves the invariant that a collection always contains the specified element after
* this call returns.
*
*
*
*
* @param
* the generic type
* @param objectCollection
* the collection to add to, 不能为null
* @param element
* 需要添加的元素
* @param condition
* the condition,仅当条件是true的情况下才会添加
* @return a boolean 标识 objectCollection
是否改变,如果改变了,返回true.
* 如果 objectCollection
是null,抛出 {@link NullPointerException}
* 如果 condition
是false,直接返回false
* 否则调用objectCollection.add(object)
* @see com.feilong.lib.collection4.CollectionUtils#addIgnoreNull(Collection, Object)
* @since 3.3.1
*/
public static boolean addIfCondition(final Collection objectCollection,final T element,boolean condition){
Validate.notNull(objectCollection, "objectCollection can't be null!");
if (!condition){
return false;
}
return objectCollection.add(element);
}
/**
* 在condition 是true的情况下, 设置objectList
指定index为 element
元素.
*
* 重构:
*
*
*
* 对于以下代码:
*
*
*
* String reason = getCategoryReason(appId, classifyCopyrightStrategyConfig);
* if (isNotNullOrEmpty(reason)){
* result.set(6, reason);
* }
*
*
*
* 可以重构成:
*
*
*
* setIfCondition(result, 6, reason, isNotNullOrEmpty(reason));
*
*
* 重构之后,一行可以搞定,代码阅读性更高
*
*
*
* @param
* the generic type
* @param objectList
* the collection to set, 不能为null
* @param index
* the index
* @param element
* 需要添加的元素
* @param condition
* the condition,仅当条件是true的情况下才会 set
* @since 3.5.1
*/
public static void setIfCondition(final List objectList,int index,final T element,boolean condition){
Validate.notNull(objectList, "objectList can't be null!");
if (!condition){
return;
}
objectList.set(index, 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
* 如果 objectCollection
是null,抛出 {@link NullPointerException}
* 如果 removeCollection
是null,直接返回 objectCollection
* @see ListUtils#removeAll(Collection, Collection)
* @since Commons Collections 4
* @since 1.0.8
* @since 3.3.6 如果 removeCollection
是null,直接返回 objectCollection
*/
public static List removeAll(Collection objectCollection,Collection removeCollection){
Validate.notNull(objectCollection, "objectCollection can't be null!");
if (null == removeCollection){
return toList(objectCollection);
}
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));
}
/**
* 去重,返回 objectCollection 指定属性 propertyName 没有重复值的新list (原集合对象不变).
*
* 示例:
*
*
* 有以下两个user 对象, id值都是1,这时去重,只保留一个
*
*
*
*
*
* 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
元素顺序
* - 出现
propertyName
值重复的话,只保留第一个元素
* - 原
objectCollection
不变
*
*
*
* @param
* the generic type
* @param objectCollection
* the object collection
* @param propertyName
* 包含的属性数组名字数组,(can be nested/indexed/mapped/combo),
* 如果是null或者empty,那么直接调用 {@link #removeDuplicate(Collection)}
* @return 如果 propertyName
是null或者empty,那么直接调用 {@link #removeDuplicate(Collection)}
* 如果 objectCollection
是null或者empty,返回 {@link Collections#emptyList()}
* 否则调用 {@link #group(Iterable, String)},将map 的values转成list返回
* @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