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.sunchenbin.store.feilong.core.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; 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.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.collections4.Predicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sunchenbin.store.feilong.core.bean.BeanUtilException; import com.sunchenbin.store.feilong.core.bean.ConvertUtil; import com.sunchenbin.store.feilong.core.bean.PropertyUtil; import com.sunchenbin.store.feilong.core.lang.NumberUtil; import com.sunchenbin.store.feilong.core.tools.jsonlib.JsonUtil; import com.sunchenbin.store.feilong.core.util.predicate.ArrayContainsPredicate; import com.sunchenbin.store.feilong.core.util.predicate.ObjectPropertyEqualsPredicate; /** * {@link Collection} , {@link Collections} .<br> * * <h3>{@link <a href="http://stamen.iteye.com/blog/2003458">SET-MAP</a>}</h3> * * <blockquote> * <ul> * <li>?Set,Map???</li> * <li>80%?hashCode,equals??</li> * <li>40%?Set??,?</li> * <li>20%?Map??,?,</li> * </ul> * </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!"); } /** * iterator???. * * <p style="color:red"> * ?, {@link java.lang.Object#toString()} * </p> * * @param iterator * iterator * @param value * value * @return iterator???,iteratornull/empty,false * @see Iterator#hasNext() * @see Iterator#next() */ public static boolean contains(Iterator<?> iterator, Object value) { if (Validator.isNullOrEmpty(iterator)) { return false; } while (iterator.hasNext()) { Object object = iterator.next(); if (object.toString().equals(value.toString())) { return true; } } return false; } /** * <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 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 ListUtils#removeAll(Collection, Collection) * @since Commons Collections 3.2 * @since 1.0.8 */ public static <T> List<T> removeAll(Collection<T> collection, Collection<T> remove) { return ListUtils.removeAll(collection, remove); } /** * <code>collection</code> <code>removeElement</code>,?(???). * * <p> * ?,? <code>collection</code>?,? <code>collection.remove(removeElement);</code>. * </p> * * <p> * {@link 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 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); } /** * ?. * * <p> * <code>collection</code> ?,? <code>collection</code>? * </p> * * <h3>contains??.</h3> * * <blockquote> * <p> * 100Wlist0.546,contains,?.10W2??.<br> * [foo1] 100000 -> 50487 : 48610 ms.<br> * [foo2] 100000 -> 50487 : 47 ms.<br> * </p> * </blockquote> * * @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 Collections.emptyList(); } return new ArrayList<T>(new LinkedHashSet<T>(collection)); } /** * ??, {@link PropertyUtil#getProperty(Object, String)}?,?List(ArrayList). * * <p> * ???,?,?,map,bean * </p> * * <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.sunchenbin.store.feilong.core.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.sunchenbin.store.feilong.core.bean.PropertyUtil#getProperty(Object, String) * @see org.apache.commons.beanutils.BeanToPropertyValueTransformer * @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 can't be null/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 CollectionUtils#find(Iterable, Predicate) */ public static <O, V> O find(Collection<O> objectCollection, String propertyName, V value) { Predicate<O> predicate = new ObjectPropertyEqualsPredicate<O>(propertyName, value); return 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 CollectionUtils#select(Iterable, Predicate) */ public static <O, V> List<O> select(Collection<O> objectCollection, String propertyName, V value) { Object[] values = { value }; return select(objectCollection, propertyName, values); } /** * {@link ArrayContainsPredicate}, <code>propertyName</code>,? <code>values</code>;,list. * * <p> * ?? {@link ArrayContainsPredicate} * </p> * * @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> * @see com.sunchenbin.store.feilong.core.util.predicate.ArrayContainsPredicate#ArrayContainsPredicate(String, Object...) */ public static <O, V> List<O> select(Collection<O> objectCollection, String propertyName, V... values) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/empty!"); } if (Validator.isNullOrEmpty(propertyName)) { throw new NullPointerException("propertyName is null or empty!"); } Predicate<O> predicate = new ArrayContainsPredicate<O>(propertyName, values); return (List<O>) CollectionUtils.select(objectCollection, predicate); } /** * Select. * * @param <O> * the generic type * @param objectCollection * the object collection * @param predicate * the predicate * @return the list< o> */ public static <O> List<O> select(Collection<O> objectCollection, Predicate<O> predicate) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/empty!"); } return (List<O>) CollectionUtils.select(objectCollection, predicate); } /** * Select rejected. * * @param <O> * the generic type * @param objectCollection * the object collection * @param predicate * the predicate * @return the list< o> * @since 1.4.0 */ public static <O> List<O> selectRejected(Collection<O> objectCollection, Predicate<O> predicate) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/empty!"); } return (List<O>) CollectionUtils.selectRejected(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 CollectionUtils#selectRejected(Iterable, 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> */ public static <O, V> List<O> selectRejected(Collection<O> objectCollection, String propertyName, V... values) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/empty!"); } if (Validator.isNullOrEmpty(propertyName)) { throw new NullPointerException("propertyName is null or empty!"); } Predicate<O> predicate = new ArrayContainsPredicate<O>(propertyName, values); return (List<O>) CollectionUtils.selectRejected(objectCollection, predicate); } /** * ??, <code>keyPropertyName</code>key, <code>valuePropertyName</code>,?map. * * <p> * ?: {@link LinkedHashMap} * </p> * <br> * {@link 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 ??, <code>keyPropertyName</code>key, <code>valuePropertyName</code>,?map * @see com.sunchenbin.store.feilong.core.bean.BeanUtil#getProperty(Object, String) * @see org.apache.commons.beanutils.PropertyUtils#getProperty(Object, String) */ public static <K, V, O> Map<K, V> getPropertyValueMap(Collection<O> objectCollection, String keyPropertyName, String valuePropertyName) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/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.sunchenbin.store.feilong.core.bean.PropertyUtil#getProperty(Object, String) * @see com.sunchenbin.store.feilong.core.lang.ArrayUtil#group(Object[], 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("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<O> includePredicate, String propertyName) { if (Validator.isNullOrEmpty(objectCollection)) { throw new NullPointerException("objectCollection can't be null/empty!"); } if (Validator.isNullOrEmpty(propertyName)) { throw new NullPointerException("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("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(ConvertUtil.toBigDecimal(value), 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); Number mapPropertyNameValue = sumMap.get(propertyName); if (null == mapPropertyNameValue) { mapPropertyNameValue = 0; } sumMap.put(propertyName, NumberUtil.getAddValue(mapPropertyNameValue, propertyValue)); } } return sumMap; } }