Java tutorial
/* * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.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 jef.tools.collection; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.AbstractList; import java.util.AbstractMap; import java.util.AbstractQueue; import java.util.AbstractSet; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Queue; import java.util.Set; import javax.management.ReflectionException; import jef.common.log.LogUtil; import jef.tools.ArrayUtils; import jef.tools.Assert; import jef.tools.StringUtils; import jef.tools.reflect.BeanUtils; import jef.tools.reflect.BeanWrapper; import jef.tools.reflect.ClassEx; import jef.tools.reflect.FieldEx; import jef.tools.reflect.GenericUtils; import org.apache.commons.lang.ObjectUtils; import com.google.common.base.Function; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; public class CollectionUtil { /** * ?? * @author Administrator * @Date 2011-6-15 * @param <T> */ private static class FieldValueFilter<T> implements Function<T, Boolean> { private FieldEx field; private Object value; public FieldValueFilter(Class<?> clz, String fieldname, Object value) { ClassEx cw = new ClassEx(clz); this.field = cw.getField(fieldname); Assert.notNull(this.field, "the field " + fieldname + " is not found in class " + cw.getName()); this.value = value; } public Boolean apply(T input) { try { Object v = field.get(input); return ObjectUtils.equals(v, value); } catch (IllegalArgumentException e) { throw new IllegalAccessError(e.getMessage()); } } } public static <T> void setElement(List<T> list, int index, T value) { if (index == list.size()) { list.add(value); } else if (index > list.size()) { for (int i = list.size(); i < index; i++) { list.add(null); } list.add(value); } else { list.set(index, value); } } /** * ????property???list. * @param iterable * @param fieldName * @param type * @return */ @SuppressWarnings("unchecked") public static <T> List<T> getFieldValues(Object iterable, String fieldName, Class<T> type) { IterableAccessor<Object> iter = iterable(iterable); if (iter == null) return null; List<T> result = new ArrayList<T>(); for (Object bean : iter) { BeanWrapper bw = BeanWrapper.wrap(bean); Object value = bw.getPropertyValue(fieldName); result.add((T) value); } return result; } /** * ???????? * @param collection * @param function * @return */ public static <T, A> List<T> extract(Collection<A> collection, Function<A, T> function) { List<T> result = new ArrayList<T>(); if (collection != null) { for (A a : collection) { result.add(function.apply(a)); } } return result; } /** * ??????? */ @SuppressWarnings("unchecked") public static <T> List<T> getPropertyValues(Object iterable, String methodName, Class<T> type) { IterableAccessor<Object> iter = iterable(iterable); if (iter == null) return null; List<T> result = new ArrayList<T>(); Method me = null; for (Object bean : iter) { if (bean == null) { result.add(null); continue; } if (me == null) { try { me = bean.getClass().getMethod(methodName); } catch (Exception e) { throw new RuntimeException(e); } } Object value; try { value = me.invoke(bean); } catch (Exception e) { throw new RuntimeException(e); } result.add((T) value); } return result; } /** * ? * @param iterable * @param fieldName * @param type * @return */ public static List<String> toString(Object iterable, String fieldName) { IterableAccessor<Object> iter = iterable(iterable); if (iter == null) return null; List<String> result = new ArrayList<String>(); for (Object bean : iter) { result.add(StringUtils.toString(bean)); } return result; } /** * MapKey?Value,Value?key * * ?Map * <pre><tt>{tom: 100},{jack: 95},{king: 88}, {mar: 77}, {jim: 88}</tt></pre> * ?map * <pre><tt>{100:[tom]}, {95:[jack]}, {88: [king,jim]}, {77:[mar]}</tt></pre> * @param <K> * @param <V> * @param map * @return A new Multimap that reverse key and value */ public static <K, V> Multimap<V, K> inverse(Map<K, V> map) { Multimap<V, K> result = ArrayListMultimap.create(); for (Entry<K, V> e : map.entrySet()) { result.put(e.getValue(), e.getKey()); } return result; } /** * ??? * * @param <T> * @param collection * @param filter * @return */ public static <T> T findFirst(Collection<T> collection, Function<T, Boolean> filter) { if (collection == null || collection.isEmpty()) return null; for (T obj : collection) { if (filter.apply(obj)) { return obj; } } return null; } /** * ??? * * @param <T> * @param collection * @param fieldname * @param value * @return */ public static <T> T findFirst(Collection<T> collection, String fieldname, Object value) { if (collection == null || collection.isEmpty()) return null; Class<?> clz = collection.iterator().next().getClass(); FieldValueFilter<T> f = new FieldValueFilter<T>(clz, fieldname, value); return findFirst(collection, f); } /** * ??? * * @param <T> * @param collection * @param fieldname * @param value * @return */ public static <T> List<T> findAll(Collection<T> collection, String fieldname, Object value) { Class<?> clz = collection.iterator().next().getClass(); FieldValueFilter<T> f = new FieldValueFilter<T>(clz, fieldname, value); return find(collection, f); } /** * ??? * * @param <T> * @param collection * @param filter * @return */ public static <T> List<T> find(Collection<T> collection, Function<T, Boolean> filter) { List<T> list = new ArrayList<T>(); if (collection == null || collection.isEmpty()) return list; for (T obj : collection) { if (filter.apply(obj)) { list.add(obj); } } return list; } public static IterableAccessor<Object> iterable(Object data) { if (data == null) return null; if (isArrayOrCollection(data.getClass())) { return new IterableAccessor<Object>(data); } else { return null; } } /** * ?? * * @param type * @return */ public static boolean isArrayOrCollection(Type type) { if (type instanceof GenericArrayType) { return true; } else if (type instanceof Class) { Class<?> rawType = (Class<?>) type; return rawType.isArray() || Collection.class.isAssignableFrom(rawType); } Class<?> rawType = GenericUtils.getRawClass(type); return Collection.class.isAssignableFrom(rawType); } /** * ?Collection * * @param type * @return */ public static boolean isCollection(Type type) { if (type instanceof GenericArrayType) { return false; } else if (type instanceof Class) { Class<?> rawType = (Class<?>) type; return Collection.class.isAssignableFrom(rawType); } else if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; return isArrayOrCollection(pType.getRawType()); } return false; } /** * ? * * @param type * @return ??null,??? */ public static Type getComponentType(Type type) { if (type instanceof GenericArrayType) { return ((GenericArrayType) type).getGenericComponentType(); } else if (type instanceof Class) { Class<?> rawType = (Class<?>) type; if (rawType.isArray()) { return rawType.getComponentType(); } else if (Collection.class.isAssignableFrom(rawType)) { // ??Object return Object.class; } } else if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type rawType = pType.getRawType(); if (isCollection(rawType)) { return pType.getActualTypeArguments()[0]; } } return null; } /** * ? ?class * @param type * @return */ public static Class<?> getSimpleComponentType(Type type) { Type result = getComponentType(type); if (result instanceof Class<?>) { return (Class<?>) result; } // ??/???Class????? return null; } /** * * * @param collection ?? * @param function ?Key * @return */ public static <T, A> Multimap<A, T> groupBy(Collection<T> collection, Function<T, A> function) { Multimap<A, T> result = ArrayListMultimap.create(); for (T value : collection) { A attrib = function.apply(value); result.put(attrib, value); } return result; } /** * ?List * @param obj * @param index * @return */ @SuppressWarnings("rawtypes") public static Object listGet(List obj, int index) { int length = obj.size(); if (index < 0) index += length; return obj.get(index); } /** * List * @param obj * @param index * @param value */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static void listSet(List obj, int index, Object value) { int length = obj.size(); if (index < 0) index += length; obj.set(index, value); } /** * ? * @param obj * @return */ @SuppressWarnings("rawtypes") public static int length(Object obj) { if (obj.getClass().isArray()) { return Array.getLength(obj); } Assert.isTrue(obj instanceof Collection); return ((Collection) obj).size(); } /** * ? ??-1?-2 */ public static boolean isIndexValid(Object obj, int index) { int length = length(obj); if (index < 0) index += length; return index >= 0 && index < length; } @SuppressWarnings("rawtypes") public static void listSetAndExpand(List obj, int index, Object value) { int length = obj.size(); if (index < 0 && index + length >= 0) { index += length; } else if (index < 0) {// ? toFixedSize(obj, -index); } else if (index >= length) {// toFixedSize(obj, index + 1); } listSet(obj, index, value); } /** * list?? List??? list??null */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static void toFixedSize(List obj, int newsize) { int len = obj.size(); if (newsize == len) return; if (newsize > len) { for (int i = len; i < newsize; i++) { obj.add(null); } } else { for (int i = len; i > newsize; i--) { obj.remove(i - 1); } } } /** * ???? */ @SuppressWarnings("rawtypes") public static Object createContainerInstance(ClassEx collectionType, int size) { Class raw = collectionType.getWrappered(); try { if (collectionType.isArray()) { if (size < 0) size = 0; Object array = Array.newInstance(GenericUtils.getRawClass(collectionType.getComponentType()), size); return array; } else if (!Modifier.isAbstract(collectionType.getModifiers())) {// ?? Object c = raw.newInstance(); return c; } else if (Object.class == raw || raw == List.class || raw == AbstractList.class) { return new ArrayList(); } else if (raw == Set.class || raw == AbstractSet.class) { return new HashSet(); } else if (raw == Map.class || raw == AbstractMap.class) { return new HashMap(); } else if (raw == Queue.class || raw == AbstractQueue.class) { return new LinkedList(); } else { throw new IllegalArgumentException( "Unknown collection class for create:" + collectionType.getName()); } } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } /** * ??? ?Map?Collection * * @param ? */ public static Object findElementInstance(Object collection) { if (collection == null) return null; if (collection.getClass().isArray()) { for (int i = 0; i < Array.getLength(collection); i++) { Object o = Array.get(collection, i); if (o != null) { return o; } } } else if (collection instanceof Collection) { for (Object o : ((Collection<?>) collection)) { if (o != null) { return o; } } } return null; } /** * ??? * * @throws */ public static Object createElementByElement(Object collection) { Object o = findElementInstance(collection); try { if (o != null) { return BeanUtils.newInstanceAnyway(o.getClass()); } } catch (ReflectionException e) { LogUtil.exception(e); } return null; } /** * ? * @param obj * @return */ @SuppressWarnings("rawtypes") public static Object[] toArray(Object obj) { if (obj == null) return null; if (obj.getClass().isArray()) { return ArrayUtils.toObject(obj); } else if (obj instanceof Collection) { return ((Collection) obj).toArray(); } throw new IllegalArgumentException("The input object " + obj.getClass() + " is not array or collection !"); } /** * ? * @param collection * @param clz * @return */ @SuppressWarnings("unchecked") public static <T> T[] toArray(Collection<?> collection, Class<T> clz) { T[] result = (T[]) Array.newInstance(clz, collection.size()); int n = 0; for (Object o : collection) { result[n] = (T) o; n++; } return result; } /** * ?? * * @param <T> * @param a * @param b * @return */ public static <T> Collection<T> union(Collection<T> a, Collection<T> b) { HashSet<T> s = new HashSet<T>(a.size() + b.size()); s.addAll(a); s.addAll(b); return s; } /** * Return <code>true</code> if the supplied Collection is <code>null</code> * or empty. Otherwise, return <code>false</code>. * * @param collection * the Collection to check * @return whether the given Collection is empty */ public static boolean isEmpty(Collection<?> collection) { return (collection == null || collection.isEmpty()); } /** * Return <code>true</code> if the supplied Map is <code>null</code> or * empty. Otherwise, return <code>false</code>. * * @param map * the Map to check * @return whether the given Map is empty */ public static boolean isEmpty(Map<?, ?> map) { return (map == null || map.isEmpty()); } /** * Convert the supplied array into a List. A primitive array gets converted * into a List of the appropriate wrapper type. * <p> * A <code>null</code> source value will be converted to an empty List. * * @param source * the (potentially primitive) array * @return the converted List result * @see ObjectUtils#toObjectArray(Object) */ public static List<?> arrayToList(Object source) { return Arrays.asList(ArrayUtils.toObject(source)); } /** * Check whether the given Iterator contains the given element. * * @param iterator * the Iterator to check * @param element * the element to look for * @return <code>true</code> if found, <code>false</code> else */ public static boolean contains(Iterator<?> iterator, Object element) { if (iterator != null) { while (iterator.hasNext()) { Object candidate = iterator.next(); if (ObjectUtils.equals(candidate, element)) { return true; } } } return false; } /** * Check whether the given Enumeration contains the given element. * * @param enumeration * the Enumeration to check * @param element * the element to look for * @return <code>true</code> if found, <code>false</code> else */ public static boolean contains(Enumeration<?> enumeration, Object element) { if (enumeration != null) { while (enumeration.hasMoreElements()) { Object candidate = enumeration.nextElement(); if (ObjectUtils.equals(candidate, element)) { return true; } } } return false; } /** * Check whether the given Collection contains the given element instance. * <p> * Enforces the given instance to be present, rather than returning * <code>true</code> for an equal element as well. * * @param collection * the Collection to check * @param element * the element to look for * @return <code>true</code> if found, <code>false</code> else */ public static boolean fastContains(Collection<?> collection, Object element) { if (collection != null) { for (Object candidate : collection) { if (candidate == element) { return true; } } } return false; } /** * Return <code>true</code> if any element in '<code>candidates</code>' is * contained in '<code>source</code>'; otherwise returns <code>false</code>. * * @param source * the source Collection * @param candidates * the candidates to search for * @return whether any of the candidates has been found */ public static boolean containsAny(Collection<?> source, Collection<?> candidates) { if (isEmpty(source) || isEmpty(candidates)) { return false; } for (Object candidate : candidates) { if (source.contains(candidate)) { return true; } } return false; } /** * Return the first element in '<code>candidates</code>' that is contained * in '<code>source</code>'. If no element in '<code>candidates</code>' is * present in '<code>source</code>' returns <code>null</code>. Iteration * order is {@link Collection} implementation specific. * * @param source * the source Collection * @param candidates * the candidates to search for * @return the first present object, or <code>null</code> if not found */ public static Object findFirstMatch(Collection<?> source, Collection<?> candidates) { if (isEmpty(source) || isEmpty(candidates)) { return null; } for (Object candidate : candidates) { if (source.contains(candidate)) { return candidate; } } return null; } /** * Find the common element type of the given Collection, if any. * * @param collection * the Collection to check * @return the common element type, or <code>null</code> if no clear common * type has been found (or the collection was empty) * ??????null */ public static Class<?> findCommonElementType(Collection<?> collection) { if (isEmpty(collection)) { return null; } Class<?> candidate = null; for (Object val : collection) { if (val != null) { if (candidate == null) { candidate = val.getClass(); } else if (candidate != val.getClass()) { return null; } } } return candidate; } /** * Create a new identityHashSet. * @return */ public static <E> Set<E> identityHashSet() { return Collections.newSetFromMap(new IdentityHashMap<E, Boolean>()); } /** * Adapts an enumeration to an iterator. * * @param enumeration * the enumeration * @return the iterator */ public static <E> Iterator<E> toIterator(Enumeration<E> enumeration) { return new EnumerationIterator<E>(enumeration); } /** * Iterator wrapping an Enumeration. */ private static class EnumerationIterator<E> implements Iterator<E> { private Enumeration<E> enumeration; public EnumerationIterator(Enumeration<E> enumeration) { this.enumeration = enumeration; } public boolean hasNext() { return this.enumeration.hasMoreElements(); } public E next() { return this.enumeration.nextElement(); } public void remove() throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported"); } } /** * EnumerationCollection? * @param o * @return */ public Collection<?> toCollection(Object o) { if (o == null) return null; if (o instanceof Collection<?>) { return (Collection<?>) o; } if (o.getClass().isArray()) { return Arrays.asList(ArrayUtils.toObject(o)); } if (o instanceof Iterable<?>) { List<Object> list = new ArrayList<Object>(); for (Object x : (Iterable<?>) o) { list.add(x); } return list; } if (o instanceof Enumeration<?>) { List<Object> list = new ArrayList<Object>(); Enumeration<?> e = (Enumeration<?>) o; for (; e.hasMoreElements();) { list.add(e.nextElement()); } return list; } throw new IllegalArgumentException("The type " + o.getClass().getName() + " Can not cast to Collection."); } }