Java tutorial
/* * 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.discovery.darchrow.util; import java.io.Serializable; import java.lang.reflect.Array; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.collections.Predicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.discovery.darchrow.bean.BeanUtilException; import com.discovery.darchrow.bean.PropertyUtil; import com.discovery.darchrow.lang.ArrayUtil; import com.discovery.darchrow.lang.NumberUtil; import com.discovery.darchrow.lang.ToStringConfig; import com.discovery.darchrow.tools.jsonlib.JsonUtil; import com.discovery.darchrow.util.predicate.ArrayContainsPredicate; import com.discovery.darchrow.util.predicate.ObjectPropertyEqualsPredicate; /** * {@link Collection} , {@link Collections} .<br> * * <h3>{@link <a href="http://stamen.iteye.com/blog/2003458">SET-MAP</a>}</h3> * * <blockquote> * <p> * <ul> * <li>?SetMap???</li> * <li>80%?hashCode,equals??</li> * <li>40%?Set???</li> * <li>20%?Map???</li> * </ul> * </p> * </blockquote> * * @author feilong * @version 1.0 Sep 2, 2010 8:08:40 PM * @since 1.0.0 * @since jdk1.5 */ 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!"); } /** * <code>collection</code> <code>remove</code>. ?,?(???) * <p> * The cardinality of an element <code>e</code> in the returned collection is the same as the cardinality of <code>e</code> in * <code>collection</code> unless <code>remove</code> contains <code>e</code>, in which case the cardinality is zero. * </p> * <p> * ?,? <code>collection</code>?,? <code>collection.removeAll(remove);</code>. * </p> * <p> * {@link org.apache.commons.collections.ListUtils#removeAll(Collection, Collection)},?<code>removeElement</code> * list. * </p> * * @param <T> * the generic type * @param collection * the collection from which items are removed (in the returned collection) * @param remove * the items to be removed from the returned <code>collection</code> * @return a <code>List</code> containing all the elements of <code>c</code> except * any elements that also occur in <code>remove</code>. * @see org.apache.commons.collections.ListUtils#removeAll(Collection, Collection) * @since Commons Collections 3.2 * @since 1.0.8 */ @SuppressWarnings("unchecked") public static <T> List<T> removeAll(Collection<T> collection, Collection<T> remove) { return org.apache.commons.collections.ListUtils.removeAll(collection, remove); } /** * <code>collection</code> <code>removeElement</code>,?(???). * <p> * ?,? <code>collection</code>?,? <code>collection.remove(removeElement);</code>. * </p> * <p> * {@link org.apache.commons.collections.ListUtils#removeAll(Collection, Collection)},?<code>removeElement</code> * list. * </p> * * @param <T> * the generic type * @param collection * the collection from which items are removed (in the returned collection) * @param removeElement * the remove element * @return a <code>List</code> containing all the elements of <code>c</code> except * any elements that also occur in <code>remove</code>. * @see org.apache.commons.collections.ListUtils#removeAll(Collection, Collection) * @since Commons Collections 3.2 * @since 1.0.8 */ public static <T> List<T> remove(Collection<T> collection, T removeElement) { Collection<T> remove = new ArrayList<T>(); remove.add(removeElement); return removeAll(collection, remove); } /** * ?(collection?,?collection?). * * @param <T> * the generic type * @param collection * the item src list * @return if Validator.isNullOrEmpty(collection) null<br> * else {@link ArrayList} * @see ArrayList#ArrayList(java.util.Collection) * @see LinkedHashSet#LinkedHashSet(Collection) * @see <a * href="http://www.oschina.net/code/snippet_117714_2991?p=2#comments">http://www.oschina.net/code/snippet_117714_2991?p=2#comments</a> */ public static <T> List<T> removeDuplicate(Collection<T> collection) { if (Validator.isNullOrEmpty(collection)) { return null; } // contains??. // 100Wlist0.546contains?.10W2??. // [foo1] 100000 -> 50487 : 48610 ms. // [foo2] 100000 -> 50487 : 47 ms. return new ArrayList<T>(new LinkedHashSet<T>(collection)); } /** * ???. * * @param <T> * the generic type , {@link Serializable} ? * @param collection * ?, ?,collection * @param toStringConfig * * @return collection isNullOrEmpty,null<br> * toStringConfig null, {@link ToStringConfig#DEFAULT_CONNECTOR} <br> * ?null,,toStringConfig.getConnector() * @see com.baozun.nebulaplus.lang.ArrayUtil#toString(ToStringConfig, T...) */ public static final <T extends Serializable> String toString(final Collection<T> collection, ToStringConfig toStringConfig) { if (Validator.isNullOrEmpty(collection)) { return null; } return ArrayUtil.toString(toStringConfig, toArray(collection)); } /** * ??. * * @param <T> * the generic type * @param collection * ? * @return Enumeration * @see Collections#enumeration(Collection) */ public static final <T> Enumeration<T> toEnumeration(final Collection<T> collection) { return Collections.enumeration(collection); } /** * ??. * * @param <T> * the generic type * @param enumeration * the enumeration * @return if Validator.isNullOrEmpty(enumeration), return {@link Collections#emptyList()},emptyList???<br> * else return {@link Collections#list(Enumeration)} * @see Collections#emptyList() * @see Collections#EMPTY_LIST * @see Collections#list(Enumeration) * @see org.apache.commons.collections.EnumerationUtils#toList(Enumeration) * @since 1.0.7 * @since JDK 1.5 */ public static final <T> List<T> toList(final Enumeration<T> enumeration) { if (Validator.isNullOrEmpty(enumeration)) { return Collections.emptyList(); } ArrayList<T> list = Collections.list(enumeration); return list; } /** * ??. * * <p style="color:red"> * note:T , ??,???null. * </p> * * @param <T> * the generic type * @param collection * collection * @return ,if Validator.isNullOrEmpty(collection),return null * @see java.lang.reflect.Array#newInstance(Class, int) * @see java.lang.reflect.Array#newInstance(Class, int...) * @see java.util.Collection#toArray() * @see java.util.Collection#toArray(Object[]) * @see java.util.List#toArray() * @see java.util.List#toArray(Object[]) * @see java.util.Vector#toArray() * @see java.util.Vector#toArray(Object[]) * @see java.util.LinkedList#toArray() * @see java.util.LinkedList#toArray(Object[]) * @see java.util.ArrayList#toArray() * @see java.util.ArrayList#toArray(Object[]) */ public static <T> T[] toArray(Collection<T> collection) { if (Validator.isNullOrEmpty(collection)) { return null; } //********************************************************************** Iterator<T> iterator = collection.iterator(); T firstT = iterator.next(); //list.get(0); //TODO ?? if (Validator.isNullOrEmpty(firstT)) { throw new IllegalArgumentException("list's first item can't be null/empty!"); } //********************************************************************** Class<?> compontType = firstT.getClass(); int size = collection.size(); @SuppressWarnings("unchecked") T[] tArray = (T[]) Array.newInstance(compontType, size); // alength0,???API??size,?. // ?alengthCollectionsize????API?. //?toArray(new Object[0]) toArray() ?. return collection.toArray(tArray); } /** * ??, {@link com.baozun.nebulaplus.bean.PropertyUtil#getProperty(Object, String)}?,?List(ArrayList). <br> * ???,?,?,map,bean * * <h3>:</h3> * * <blockquote> * * <pre> * List<User> testList = new ArrayList<User>(); * * User user; * UserInfo userInfo; * * //******************************************************* * List<UserAddress> userAddresseList = new ArrayList<UserAddress>(); * UserAddress userAddress = new UserAddress(); * userAddress.setAddress("?"); * userAddresseList.add(userAddress); * * //******************************************************* * Map<String, String> attrMap = new HashMap<String, String>(); * attrMap.put("", "?"); * attrMap.put("?", ""); * attrMap.put("?", ""); * * //******************************************************* * String[] lovesStrings1 = { "sanguo1", "xiaoshuo1" }; * userInfo = new UserInfo(); * userInfo.setAge(28); * * user = new User(2L); * user.setLoves(lovesStrings1); * user.setUserInfo(userInfo); * user.setUserAddresseList(userAddresseList); * * user.setAttrMap(attrMap); * testList.add(user); * * //***************************************************** * String[] lovesStrings2 = { "sanguo2", "xiaoshuo2" }; * userInfo = new UserInfo(); * userInfo.setAge(30); * * user = new User(3L); * user.setLoves(lovesStrings2); * user.setUserInfo(userInfo); * user.setUserAddresseList(userAddresseList); * user.setAttrMap(attrMap); * testList.add(user); * * // * List<String> fieldValueList1 = ListUtil.getFieldValueList(testList, "loves[1]"); * LOGGER.info(JsonUtil.format(fieldValueList1)); * * //? * List<Integer> fieldValueList2 = ListUtil.getFieldValueList(testList, "userInfo.age"); * LOGGER.info(JsonUtil.format(fieldValueList2)); * * //Map * List<Integer> attrList = ListUtil.getFieldValueList(testList, "attrMap()"); * LOGGER.info(JsonUtil.format(attrList)); * * //? * List<String> addressList = ListUtil.getFieldValueList(testList, "userAddresseList[0]"); * LOGGER.info(JsonUtil.format(addressList)); * </pre> * * </blockquote> * * @param <T> * ? generic type * @param <O> * ? generic type * @param objectCollection * ? * @param propertyName * ??,Possibly indexed and/or nested name of the property to be extracted * @return ??,?,?List(ArrayList) * @see com.baozun.nebulaplus.bean.BeanUtil#getProperty(Object, String) * @see org.apache.commons.beanutils.PropertyUtils#getProperty(Object, String) * @see #getPropertyValueCollection(Collection, String, Collection) * @since jdk1.5 */ public static <T, O> List<T> getPropertyValueList(Collection<O> objectCollection, String propertyName) { List<T> list = new ArrayList<T>(); return getPropertyValueCollection(objectCollection, propertyName, list); } /** * property value set. * * @param <T> * the generic type * @param <O> * the generic type * @param objectCollection * the object collection * @param propertyName * the property name * @return the property value set * @see #getPropertyValueCollection(Collection, String, Collection) * @since 1.0.8 */ public static <T, O> Set<T> getPropertyValueSet(Collection<O> objectCollection, String propertyName) { Set<T> set = new LinkedHashSet<T>(); return getPropertyValueCollection(objectCollection, propertyName, set); } /** * objectCollection, {@link PropertyUtil#getProperty(Object, String)} propertyName <code>returnCollection</code> . * * @param <T> * the generic type * @param <O> * the generic type * @param <K> * the key type * @param objectCollection * the object collection * @param propertyName * the property name * @param returnCollection * the return collection * @return the property value collection * @see com.baozun.nebulaplus.bean.PropertyUtil#getProperty(Object, String) * @since 1.0.8 */ private static <T, O, K extends Collection<T>> K getPropertyValueCollection(Collection<O> objectCollection, String propertyName, K returnCollection) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection is null or empty!"); } if (Validator.isNullOrEmpty(propertyName)) { throw new NullPointerException("propertyName is null or empty!"); } if (null == returnCollection) { throw new NullPointerException("returnCollection is null!"); } try { for (O bean : objectCollection) { @SuppressWarnings("unchecked") T property = (T) PropertyUtil.getProperty(bean, propertyName); returnCollection.add(property); } } catch (BeanUtilException e) { LOGGER.error(e.getClass().getName(), e); } return returnCollection; } /** * Finds the first element in the given collection which matches the given predicate. * <p> * If the input collection or predicate is null, or no element of the collection matches the predicate, null is returned. * </p> * * @param <O> * the generic type * @param <V> * the value type * @param objectCollection * the object collection * @param propertyName * the property name * @param value * the value * @return the first element of the collection which matches the predicate or null if none could be found * @see org.apache.commons.collections.CollectionUtils#find(Collection, Predicate) */ @SuppressWarnings("unchecked") public static <O, V> O find(Collection<O> objectCollection, String propertyName, V value) { Predicate predicate = new ObjectPropertyEqualsPredicate(propertyName, value); return (O) org.apache.commons.collections.CollectionUtils.find(objectCollection, predicate); } /** * ?? <code>objectCollection</code>, bean propertyName equals value list. * * @param <O> * the generic type * @param <V> * the value type * @param objectCollection * the object list * @param propertyName * the property name * @param value * the value * @return the property value list * @see org.apache.commons.collections.CollectionUtils#select(Collection, org.apache.commons.collections.Predicate) */ public static <O, V> List<O> select(Collection<O> objectCollection, String propertyName, V value) { Object[] values = { value }; return select(objectCollection, propertyName, values); } /** * {@link PropertyUtil#getProperty(Object, String)} <code>propertyName</code>? {@link ArrayUtil#isContain(Object[], Object)} * <code>values</code>,list. * * @param <O> * the generic type * @param <V> * the value type * @param objectCollection * the object collection * @param propertyName * the property name * @param values * the values * @return {@link PropertyUtil#getProperty(Object, String)} <code>propertyName</code>? * {@link ArrayUtil#isContain(Object[], Object)} <code>values</code>,list */ @SuppressWarnings("unchecked") public static <O, V> List<O> select(Collection<O> objectCollection, String propertyName, V... values) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection is null or empty!"); } if (Validator.isNullOrEmpty(propertyName)) { throw new NullPointerException("propertyName is null or empty!"); } Predicate predicate = new ArrayContainsPredicate(propertyName, values); return (List<O>) org.apache.commons.collections.CollectionUtils.select(objectCollection, predicate); } /** * Select. * * @param <O> * the generic type * @param objectCollection * the object collection * @param predicate * the predicate * @return the list< o> */ @SuppressWarnings("unchecked") public static <O> List<O> select(Collection<O> objectCollection, Predicate predicate) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection is null or empty!"); } return (List<O>) org.apache.commons.collections.CollectionUtils.select(objectCollection, predicate); } /** * ?? <code>objectCollection</code> , bean propertyName ? equals value list. * * @param <O> * the generic type * @param <V> * the value type * @param objectCollection * the object list * @param propertyName * the property name * @param value * the value * @return the property value list * @see org.apache.commons.collections.CollectionUtils#selectRejected(Collection, org.apache.commons.collections.Predicate) */ public static <O, V> List<O> selectRejected(Collection<O> objectCollection, String propertyName, V value) { Object[] values = { value }; return selectRejected(objectCollection, propertyName, values); } /** * ?? <code>objectCollection</code> , bean propertyName ?values list. * * @param <O> * the generic type * @param <V> * the value type * @param objectCollection * the object collection * @param propertyName * the property name * @param values * the values * @return the list< o> */ @SuppressWarnings("unchecked") public static <O, V> List<O> selectRejected(Collection<O> objectCollection, String propertyName, V... values) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection is null or empty!"); } if (Validator.isNullOrEmpty(propertyName)) { throw new NullPointerException("propertyName is null or empty!"); } Predicate predicate = new ArrayContainsPredicate(propertyName, values); return (List<O>) org.apache.commons.collections.CollectionUtils.selectRejected(objectCollection, predicate); } /** * ??, <code>keyPropertyName</code>key <code>valuePropertyName</code>?map<br> * * <p> * ?: {@link LinkedHashMap} * </p> * <br> * {@link com.baozun.nebulaplus.bean.PropertyUtil#getProperty(Object, String)}?. <br> * ???,?,?,map,bean * * <h3>:</h3> * * <blockquote> * * <pre> * List<User> testList = new ArrayList<User>(); * testList.add(new User("", 23)); * testList.add(new User("", 24)); * testList.add(new User("", 25)); * * Map<String, Integer> map = CollectionsUtil.getFieldValueMap(testList, "name", "age"); * * : * * "": 24, * "": 23, * "": 25 * </pre> * * </blockquote> * * @param <K> * the key type * @param <V> * the value type * @param <O> * ? generic type * @param objectCollection * ? * @param keyPropertyName * the key property name * @param valuePropertyName * the value property name * @return ??,?,?List(ArrayList) * @see com.baozun.nebulaplus.bean.BeanUtil#getProperty(Object, String) * @see org.apache.commons.beanutils.PropertyUtils#getProperty(Object, String) * @since jdk1.5 */ public static <K, V, O> Map<K, V> getPropertyValueMap(Collection<O> objectCollection, String keyPropertyName, String valuePropertyName) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection is null or empty!"); } if (Validator.isNullOrEmpty(keyPropertyName)) { throw new NullPointerException("keyPropertyName is null or empty!"); } if (Validator.isNullOrEmpty(valuePropertyName)) { throw new NullPointerException("valuePropertyName is null or empty!"); } Map<K, V> map = new LinkedHashMap<K, V>(); for (O bean : objectCollection) { @SuppressWarnings("unchecked") K key = (K) PropertyUtil.getProperty(bean, keyPropertyName); @SuppressWarnings("unchecked") V value = (V) PropertyUtil.getProperty(bean, valuePropertyName); map.put(key, value); } return map; } /** * Group (propertyName ?list? putmap). * * @param <T> * ?T Object ?excel?String???Integer? ?? * @param <O> * the generic type * @param objectCollection * the object list * @param propertyName * ???? * @return the map< t, list< o>> * @see com.baozun.nebulaplus.bean.PropertyUtil#getProperty(Object, String) * @see com.baozun.nebulaplus.lang.ArrayUtil#group(O[], String) * @see #groupOne(Collection, String) * @since 1.0.8 */ public static <T, O> Map<T, List<O>> group(Collection<O> objectCollection, String propertyName) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/empty!"); } if (Validator.isNullOrEmpty(propertyName)) { throw new NullPointerException("the propertyName is null or empty!"); } // ??? HashMap TreeMap Map<T, List<O>> map = new LinkedHashMap<T, List<O>>(objectCollection.size()); for (O o : objectCollection) { T t = PropertyUtil.getProperty(o, propertyName); List<O> valueList = map.get(t); if (null == valueList) { valueList = new ArrayList<O>(); } valueList.add(o); map.put(t, valueList); } return map; } /** * <code>objectCollection</code> {@code propertyName}. * * @param <T> * the generic type * @param <O> * the generic type * @param objectCollection * the object collection * @param propertyName * the property name * @return {@link LinkedHashMap} */ public static <T, O> Map<T, Integer> groupCount(Collection<O> objectCollection, String propertyName) { return groupCount(objectCollection, null, propertyName); } /** * <code>objectCollection</code>,? ? <code>includePredicate</code> {@code propertyName}. * * @param <T> * the generic type * @param <O> * the generic type * @param objectCollection * the object collection * @param includePredicate * ? ? <code>includePredicate</code>null ?Object * @param propertyName * the property name * @return the map< t, integer> * @since 1.2.0 */ public static <T, O> Map<T, Integer> groupCount(Collection<O> objectCollection, Predicate includePredicate, String propertyName) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/empty!"); } if (Validator.isNullOrEmpty(propertyName)) { throw new NullPointerException("the propertyName is null or empty!"); } Map<T, Integer> map = new LinkedHashMap<T, Integer>(); for (O o : objectCollection) { if (null != includePredicate) { // boolean continueFlag = !includePredicate.evaluate(o); if (continueFlag) { continue; } } T t = PropertyUtil.getProperty(o, propertyName); Integer count = map.get(t); if (null == count) { count = 0; } count = count + 1; map.put(t, count); } return map; } /** * Group one(map?put?). * * @param <T> * the generic type * @param <O> * the generic type * @param objectCollection * the object collection * @param propertyName * the property name * @return the map< t, o> * @see #group(Collection, String) * @since 1.0.8 */ public static <T, O> Map<T, O> groupOne(Collection<O> objectCollection, String propertyName) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/empty!"); } if (Validator.isNullOrEmpty(propertyName)) { throw new NullPointerException("the propertyName is null or empty!"); } // ??? HashMap TreeMap Map<T, O> map = new LinkedHashMap<T, O>(objectCollection.size()); for (O o : objectCollection) { T key = PropertyUtil.getProperty(o, propertyName); if (!map.containsKey(key)) { map.put(key, o); } else { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Abandoned except the first value outside,map:{},containsKey key:[{}],", JsonUtil.format(map.keySet()), key); } } } return map; } /** * ?. * * @param <O> * the generic type * @param objectCollection * the object collection * @param scale * ? * @param propertyNames * ???? * @return the map< string, list< o>> * @see #sum(Collection, String...) */ public static <O> Map<String, Number> avg(Collection<O> objectCollection, int scale, String... propertyNames) { // Map<String, Number> sumMap = sum(objectCollection, propertyNames); int size = objectCollection.size(); // ??? HashMap TreeMap Map<String, Number> map = new LinkedHashMap<String, Number>(size); for (Map.Entry<String, Number> entry : sumMap.entrySet()) { String key = entry.getKey(); Number value = entry.getValue(); map.put(key, NumberUtil.getDivideValue(new BigDecimal(value.toString()), size, scale)); } return map; } /** * ?. * * @param <O> * the generic type * @param objectCollection * the object collection * @param propertyNames * the property names * @return the map< string, list< o>> */ public static <O> Map<String, Number> sum(Collection<O> objectCollection, String... propertyNames) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/empty!"); } if (Validator.isNullOrEmpty(propertyNames)) { throw new NullPointerException("propertyNames is null or empty!"); } //************************************************************************** int size = objectCollection.size(); // Map<String, Number> sumMap = new LinkedHashMap<String, Number>(size); for (O o : objectCollection) { for (String propertyName : propertyNames) { //?? Number propertyValue = PropertyUtil.getProperty(o, propertyName); //map Number mapPropertyNameValue = sumMap.get(propertyName); if (null == mapPropertyNameValue) { mapPropertyNameValue = 0; } sumMap.put(propertyName, NumberUtil.getAddValue(mapPropertyNameValue, propertyValue)); } } //************************************************************************** return sumMap; } }