Java tutorial
/* * Copyright (C) 2008 feilong (venusdrogon@163.com) * * 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.commons.core.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.feilong.commons.core.bean.BeanUtilException; import com.feilong.commons.core.bean.PropertyUtil; import com.feilong.commons.core.entity.JoinStringEntity; import com.feilong.commons.core.lang.ObjectUtil; /** * {@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 <a href="mailto:venusdrogon@163.com"></a> * @version 1.0 Sep 2, 2010 8:08:40 PM * @since 1.0.0 * @since jdk1.5 */ public final class CollectionsUtil { /** The Constant log. */ private static final Logger log = 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!"); } /** * ???. * * @param <T> * the generic type , {@link Serializable} ? * @param collection * ?, ?,collection * @param joinStringEntity * * @return collection isNullOrEmpty,null<br> * joinStringEntity null, {@link JoinStringEntity#DEFAULT_CONNECTOR} <br> * ?null,,joinStringEntity.getConnector() */ // XXX ? public static final <T extends Serializable> String toString(final Collection<T> collection, final JoinStringEntity joinStringEntity) { if (Validator.isNotNullOrEmpty(collection)) { String connector = JoinStringEntity.DEFAULT_CONNECTOR; if (Validator.isNotNullOrEmpty(joinStringEntity)) { connector = joinStringEntity.getConnector(); } StringBuilder sb = new StringBuilder(); int i = 0; for (T t : collection) { sb.append(t); // if (i < collection.size() - 1) { sb.append(connector); } i++; } return sb.toString(); } return null; } /** * ??. * * @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; } /** * ??<br> * note:T , ??,???null. * * @param <T> * the generic type * @param collection * collection * @return ,if Validator.isNullOrEmpty(collection),return null * @throws IllegalArgumentException * list isNullOrEmpty * @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) throws IllegalArgumentException { 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.feilong.commons.core.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]"); * log.info(JsonUtil.format(fieldValueList1)); * * //? * List<Integer> fieldValueList2 = ListUtil.getFieldValueList(testList, "userInfo.age"); * log.info(JsonUtil.format(fieldValueList2)); * * //Map * List<Integer> attrList = ListUtil.getFieldValueList(testList, "attrMap()"); * log.info(JsonUtil.format(attrList)); * * //? * List<String> addressList = ListUtil.getFieldValueList(testList, "userAddresseList[0]"); * log.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) * @throws NullPointerException * if Validator.isNullOrEmpty(objectCollection) or Validator.isNullOrEmpty(propertyName) * @see com.feilong.commons.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) throws NullPointerException { 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 * @throws NullPointerException * the null pointer exception * @see #getPropertyValueCollection(Collection, String, Collection) * @since 1.0.8 */ public static <T, O> Set<T> getPropertyValueSet(Collection<O> objectCollection, String propertyName) throws NullPointerException { 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 * @throws NullPointerException * if Validator.isNullOrEmpty(objectCollection) or Validator.isNullOrEmpty(propertyName) or (null == returnCollection) * @see com.feilong.commons.core.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) throws NullPointerException { 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) { log.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 * @throws NullPointerException * the null pointer exception * @see org.apache.commons.collections.CollectionUtils#find(Collection, Predicate) */ @SuppressWarnings("unchecked") public static <O, V> O find(Collection<O> objectCollection, String propertyName, V value) throws NullPointerException { Predicate predicate = getObjectEqualsPredicate(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 * @throws NullPointerException * if Validator.isNullOrEmpty(objectCollection) || Validator.isNullOrEmpty(propertyName) * @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) throws NullPointerException { 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 * @throws NullPointerException * if Validator.isNullOrEmpty(objectCollection) || Validator.isNullOrEmpty(propertyName) */ @SuppressWarnings("unchecked") public static <O, V> List<O> select(Collection<O> objectCollection, String propertyName, V... values) throws NullPointerException { 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 = getArrayContainsPredicate(propertyName, values); return (List<O>) org.apache.commons.collections.CollectionUtils.select(objectCollection, predicate); } /** * {@link PropertyUtil#getProperty(Object, String)} <code>propertyName</code>? {@link ArrayUtil#isContain(V[], V)} * <code>values</code>. * * @param <V> * the value type * @param propertyName * the property name * @param values * the values * @return the array predicate * @see com.feilong.commons.core.bean.PropertyUtil#getProperty(Object, String) * @see com.feilong.commons.core.util.ArrayUtil#isContain(V[], V) * @since 1.0.9 */ //@SafeVarargs private static <V> Predicate getArrayContainsPredicate(final String propertyName, final V... values) { Predicate predicate = new Predicate() { @Override public boolean evaluate(Object object) { V property = PropertyUtil.getProperty(object, propertyName); return ArrayUtil.isContain(values, property); } }; return predicate; } /** * object equals predicate. * * @param <V> * the value type * @param propertyName * the property name * @param value * the value * @return the object equals predicate * @since 1.0.9 */ private static <V> Predicate getObjectEqualsPredicate(final String propertyName, final V value) { Predicate predicate = new Predicate() { @Override public boolean evaluate(Object object) { V property = PropertyUtil.getProperty(object, propertyName); return ObjectUtil.equals(property, value, true); } }; return predicate; } /** * Select. * * @param <O> * the generic type * @param objectCollection * the object collection * @param predicate * the predicate * @return the list< o> * @throws NullPointerException * the null pointer exception */ @SuppressWarnings("unchecked") public static <O> List<O> select(Collection<O> objectCollection, Predicate predicate) throws NullPointerException { 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 * @throws NullPointerException * the null pointer exception * @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) throws NullPointerException { 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> * @throws NullPointerException * the null pointer exception */ @SuppressWarnings("unchecked") public static <O, V> List<O> selectRejected(Collection<O> objectCollection, String propertyName, V... values) throws NullPointerException { 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 = getArrayContainsPredicate(propertyName, values); return (List<O>) org.apache.commons.collections.CollectionUtils.selectRejected(objectCollection, predicate); } /** * ??, <code>keyPropertyName</code>key <code>valuePropertyName</code>?map * * <br> * {@link com.feilong.commons.core.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) * @throws NullPointerException * if Validator.isNullOrEmpty(objectCollection) or Validator.isNullOrEmpty(propertyName) or * Validator.isNullOrEmpty(valuePropertyName) * @see com.feilong.commons.core.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) throws NullPointerException { 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>(); try { 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); } } catch (BeanUtilException e) { log.error(e.getClass().getName(), e); } 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>> * @throws BeanUtilException * the bean util exception * @throws NullPointerException * if Validator.isNullOrEmpty(propertyName) * @see com.feilong.commons.core.bean.PropertyUtil#getProperty(Object, String) * @see com.feilong.commons.core.util.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) throws BeanUtilException, NullPointerException { 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; } /** * Group count. * * @param <T> * the generic type * @param <O> * the generic type * @param objectCollection * the object collection * @param propertyName * the property name * @return the map< t, integer> * @throws BeanUtilException * the bean util exception * @throws NullPointerException * the null pointer exception */ public static <T, O> Map<T, Integer> groupCount(Collection<O> objectCollection, String propertyName) throws BeanUtilException, NullPointerException { 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) { 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> * @throws BeanUtilException * the bean util exception * @throws NullPointerException * the null pointer exception * @see #group(Collection, String) * @since 1.0.8 */ public static <T, O> Map<T, O> groupOne(Collection<O> objectCollection, String propertyName) throws BeanUtilException, NullPointerException { 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 t = PropertyUtil.getProperty(o, propertyName); O valueList = map.get(t); if (null == valueList) { map.put(t, o); } else { if (log.isDebugEnabled()) { log.debug("when propertyName:{},multiple value:{},Abandoned except the first value outside.", propertyName, valueList); } } } return map; } /** * ?. * * @param <O> * the generic type * @param objectCollection * the object collection * @param scale * ? * @param propertyNames * ???? * @return the map< string, list< o>> * @throws BeanUtilException * the bean util exception * @throws NullPointerException * the null pointer exception * @see #sum(Collection, String...) */ public static <O> Map<String, Number> avg(Collection<O> objectCollection, int scale, String... propertyNames) throws BeanUtilException, NullPointerException { // 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>> * @throws BeanUtilException * the bean util exception * @throws NullPointerException * the null pointer exception */ public static <O> Map<String, Number> sum(Collection<O> objectCollection, String... propertyNames) throws BeanUtilException, NullPointerException { 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; } }