CollectionUtil xref

View Javadoc
1 /**
2  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html 
3  */
4 package net.sourceforge.pmd.util;
5 
6 import java.lang.reflect.Array;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.Collection;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15 
16 /**
17  * Generic collection and array-related utility functions for java.util types. See ClassUtil 
18  * for comparable facilities for short name lookup.
19  *
20  * @author Brian Remedios
21  * @version $Revision$
22  */
23 public final class CollectionUtil {
24 
25 @SuppressWarnings("PMD.UnnecessaryFullyQualifiedName")
26 public static final TypeMap COLLECTION_INTERFACES_BY_NAMES = new TypeMap(new Class[] { java.util.List.class,
27 	 java.util.Collection.class, java.util.Map.class, java.util.Set.class, });
28 
29 @SuppressWarnings({"PMD.LooseCoupling", "PMD.UnnecessaryFullyQualifiedName"})
30 public static final TypeMap COLLECTION_CLASSES_BY_NAMES = new TypeMap(new Class[] { java.util.ArrayList.class,
31 	 java.util.LinkedList.class, java.util.Vector.class, java.util.HashMap.class, java.util.LinkedHashMap.class,
32 	 java.util.TreeMap.class, java.util.TreeSet.class, java.util.HashSet.class, java.util.LinkedHashSet.class,
33 	 java.util.Hashtable.class});
34 
35 private CollectionUtil() {
36 };
37 
38 	/**
39 	 * Add elements from the source to the target as long as they don't already exist there.
40 	 * Return the number of items actually added.
41 	 * 
42 	 * @param source
43 	 * @param target
44 	 * @return int
45 	 */
46 	public static int addWithoutDuplicates(Collection<String> source, Collection<String> target) {
47 		
48 		int added = 0;
49 		
50 		for (String item : source) {
51 			if (target.contains(item)) continue;
52 			target.add(item);
53 			added++;
54 		}
55 		
56 		return added;
57 	}
58 
59 /**
60  * Returns the collection type if we recognize it by its short name.
61  *
62  * @param shortName String
63  * @return Class
64  */
65 public static Class<?> getCollectionTypeFor(String shortName) {
66 	 Class<?> cls = COLLECTION_CLASSES_BY_NAMES.typeFor(shortName);
67 	 if (cls != null) {
68 	 return cls;
69 	 }
70 
71 	 return COLLECTION_INTERFACES_BY_NAMES.typeFor(shortName);
72 }
73 
74 /**
75  * Return whether we can identify the typeName as a java.util collection class
76  * or interface as specified.
77  *
78  * @param typeName String
79  * @param includeInterfaces boolean
80  * @return boolean
81  */
82 public static boolean isCollectionType(String typeName, boolean includeInterfaces) {
83 
84 	 if (COLLECTION_CLASSES_BY_NAMES.contains(typeName)) {
85 	 return true;
86 	 }
87 
88 	 return includeInterfaces && COLLECTION_INTERFACES_BY_NAMES.contains(typeName);
89 }
90 
91 /**
92  * Return whether we can identify the typeName as a java.util collection class
93  * or interface as specified.
94  *
95  * @param clazzType Class
96  * @param includeInterfaces boolean
97  * @return boolean
98  */
99 public static boolean isCollectionType(Class<?> clazzType, boolean includeInterfaces) {
100 
101 	 if (COLLECTION_CLASSES_BY_NAMES.contains(clazzType)) {
102 	 return true;
103 	 }
104 
105 	 return includeInterfaces && COLLECTION_INTERFACES_BY_NAMES.contains(clazzType);
106 }
107 
108 /**
109  * Returns the items as a populated set.
110  *
111  * @param items Object[]
112  * @return Set
113  */
114 public static <T> Set<T> asSet(T[] items) {
115 
116 	 return new HashSet<T>(Arrays.asList(items));
117 }
118 
119 /**
120  * Creates and returns a map populated with the keyValuesSets where
121  * the value held by the tuples are they key and value in that order.
122  *
123  * @param keys K[]
124  * @param values V[]
125  * @return Map
126  */
127 public static <K, V> Map<K, V> mapFrom(K[] keys, V[] values) {
128 	 if (keys.length != values.length) {
129 	 throw new RuntimeException("mapFrom keys and values arrays have different sizes");
130 	 }
131 	 Map<K, V> map = new HashMap<K, V>(keys.length);
132 	 for (int i = 0; i < keys.length; i++) {
133 	 map.put(keys[i], values[i]);
134 	 }
135 	 return map;
136 }
137 
138 /**
139  * Returns a map based on the source but with the key & values swapped.
140  *
141  * @param source Map
142  * @return Map
143  */
144 public static <K, V> Map<V, K> invertedMapFrom(Map<K, V> source) {
145 	 Map<V, K> map = new HashMap<V, K>(source.size());
146 	 for (Map.Entry<K, V> entry : source.entrySet()) {
147 	 map.put(entry.getValue(), entry.getKey());
148 	 }
149 	 return map;
150 }
151 
152 /**
153  * Returns true if the objects are array instances and each of their elements compares
154  * via equals as well.
155  *
156  * @param value Object
157  * @param otherValue Object
158  * @return boolean
159  */
160 public static boolean arraysAreEqual(Object value, Object otherValue) {
161 	 if (value instanceof Object[]) {
162 	 if (otherValue instanceof Object[]) {
163 		 return valuesAreTransitivelyEqual((Object[]) value, (Object[]) otherValue);
164 	 }
165 	 return false;
166 	 } 
167 	 return false;
168 }
169 
170 /**
171  * Returns whether the arrays are equal by examining each of their elements, even if they are
172  * arrays themselves.
173  *
174  * @param thisArray Object[]
175  * @param thatArray Object[]
176  * @return boolean
177  */
178 public static boolean valuesAreTransitivelyEqual(Object[] thisArray, Object[] thatArray) {
179 	 if (thisArray == thatArray) {
180 	 return true;
181 	 }
182 	 if (thisArray == null || thatArray == null) {
183 	 return false;
184 	 }
185 	 if (thisArray.length != thatArray.length) {
186 	 return false;
187 	 }
188 	 for (int i = 0; i < thisArray.length; i++) {
189 	 if (!areEqual(thisArray[i], thatArray[i])) {
190 	 	 return false; // recurse if req'd
191 	 }
192 	 }
193 	 return true;
194 }
195 
196 /**
197  * A comprehensive isEqual method that handles nulls and arrays safely.
198  *
199  * @param value Object
200  * @param otherValue Object
201  * @return boolean
202  */
203 @SuppressWarnings("PMD.CompareObjectsWithEquals")
204 public static boolean areEqual(Object value, Object otherValue) {
205 	if (value == otherValue) {
206 	 return true;
207 	}
208 	if (value == null) {
209 	 return false;
210 	}
211 	if (otherValue == null) {
212 	 return false;
213 	}
214 
215 	if (value.getClass().getComponentType() != null) {
216 	 return arraysAreEqual(value, otherValue);
217 	 }
218 	 return value.equals(otherValue);
219 }
220 
221 /**
222  * Returns whether the items array is null or has zero length.
223  * @param items
224  * @return boolean
225  */
226 public static boolean isEmpty(Object[] items) {
227 return items == null || items.length == 0;
228 }
229 
230 /**
231  * Returns whether the items array is non-null and has
232  * at least one entry.
233  * 
234  * @param items
235  * @return boolean
236  */
237 public static boolean isNotEmpty(Object[] items) {
238 return !isEmpty(items);
239 }
240 
241 /**
242  * Returns true if both arrays are if both are null or have zero-length,
243  * otherwise return the false if their respective elements are not
244  * equal by position.
245  *
246  * @param <T>
247  * @param a
248  * @param b
249  * @return boolean
250  */
251 public static <T> boolean areSemanticEquals(T[] a, T[] b) {
252 
253 if (a == null) { return isEmpty(b); }
254 if (b == null) { return isEmpty(a); }
255 
256 if (a.length != b.length) return false;
257 
258 for (int i=0; i<a.length; i++) {
259 	if (!areEqual(a[i], b[i])) return false;
260 }
261 
262 return true;
263 }
264 
265 /**
266  * If the newValue is already held within the values array then the values array
267  * is returned, otherwise a new array is created appending the newValue to the
268  * end.
269  *
270  * @param <T>
271  * @param values
272  * @param newValue
273  * @return an array containing the union of values and newValue
274  */
275 public static <T> T[] addWithoutDuplicates(T[] values, T newValue) {
276 
277 for (T value : values) {
278 if (value.equals(newValue)) {
279 return values;
280 }
281 }
282 
283 T[] largerOne = (T[])Array.newInstance(values.getClass().getComponentType(), values.length + 1);
284 System.arraycopy(values, 0, largerOne, 0, values.length);
285 largerOne[values.length] = newValue;
286 return largerOne;
287 }
288 
289 /**
290  * Returns an array of values as a union set of the two input arrays.
291  *
292  * @param <T>
293  * @param values
294  * @param newValues
295  * @return the union of the two arrays
296  */
297 public static <T> T[] addWithoutDuplicates(T[] values, T[] newValues) {
298 
299 Set<T> originals = new HashSet<T>(values.length);
300 for (T value : values) { originals.add(value); }
301 List<T> newOnes = new ArrayList<T>(newValues.length);
302 for (T value : newValues) {
303 if (originals.contains(value)) { continue; }
304 newOnes.add(value);
305 }
306 
307 T[] largerOne = (T[])Array.newInstance(values.getClass().getComponentType(), values.length + newOnes.size());
308 System.arraycopy(values, 0, largerOne, 0, values.length);
309 for (int i=values.length; i<largerOne.length; i++) { largerOne[i] = newOnes.get(i-values.length); }
310 return largerOne;
311 }
312 }

AltStyle によって変換されたページ (->オリジナル) /