1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package de.fu_berlin.ties.util;
23
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Set;
32
33 import de.fu_berlin.ties.text.TextUtils;
34
35 /***
36 * A static class that provides utility methods for working with
37 * {@link java.util.Collection}s and arrays. No instances of this class can be
38 * created, only the static members should be used.
39 *
40 * @author Christian Siefkes
41 * @version $Revision: 1.10 $, $Date: 2006/10/21 16:04:27 $, $Author: siefkes $
42 */
43 public final class CollUtils {
44
45 /***
46 * Default separator used to {@linkplain #flatten(Object[]) flatten} array
47 * if no other separator is specified: {@value} (a single space).
48 */
49 public static final String SEPARATOR = " ";
50
51 /***
52 * Convenience method that adds all members of an array to a collection.
53 *
54 * @param <T> the type of the collection
55 * @param <E> the type of the array
56 * @param coll the collection to add to
57 * @param array the array to value to add
58 */
59 public static <T, E extends T> void addAll(final Collection<T> coll,
60 final E[] array) {
61 for (int i = 0; i < array.length; i++) {
62 coll.add(array[i]);
63 }
64 }
65
66 /***
67 * Wraps an array into a set. Duplicates will be ignored.
68 *
69 * @param <T> the type of the array
70 * @param array the array to wrap
71 * @return a set containing the contents of the set (in random order,
72 * without duplicates)
73 */
74 public static <T> Set<T> arrayAsSet(final T[] array) {
75 return new HashSet<T>(Arrays.asList(array));
76 }
77
78 /***
79 * Converts an object array into a boolean array, calling
80 * {@link Util#asBoolean(Object)} on each element.
81 *
82 * @param objArray the array of objects to convert
83 * @return the converted boolean array
84 * @throws IllegalArgumentException if an object's <code>toString()</code>
85 * output cannot be parsed as a boolean
86 */
87 public static boolean[] asBooleanArray(final Object[] objArray)
88 throws IllegalArgumentException {
89 final boolean[] result = new boolean[objArray.length];
90 for (int i = 0; i < objArray.length; i++) {
91 result[i] = Util.asBoolean(objArray[i]);
92 }
93 return result;
94 }
95
96 /***
97 * Converts a string into a boolean array, calling
98 * {@link Util#asBoolean(char)} on each character.
99 *
100 * @param input the input string to convert
101 * @return the converted boolean array
102 * @throws IllegalArgumentException if one of the characters does not
103 * contain a parsable boolean
104 */
105 public static boolean[] asBooleanArray(final String input)
106 throws IllegalArgumentException {
107 final char[] chars = input.toCharArray();
108 final boolean[] result = new boolean[chars.length];
109 for (int i = 0; i < chars.length; i++) {
110 result[i] = Util.asBoolean(chars[i]);
111 }
112 return result;
113 }
114
115 /***
116 * Converts an object array into a char array, calling
117 * {@link Util#asChar(Object)} on each element.
118 *
119 * @param objArray the array of objects to convert
120 * @return the converted char array
121 * @throws IndexOutOfBoundsException if the object's <code>toString()</code>
122 * output is the empty string (after trimming outer whitespace)
123 */
124 public static char[] asCharArray(final Object[] objArray)
125 throws IndexOutOfBoundsException {
126 final char[] result = new char[objArray.length];
127 for (int i = 0; i < objArray.length; i++) {
128 result[i] = Util.asChar(objArray[i]);
129 }
130 return result;
131 }
132
133 /***
134 * Converts a string array into a char array. This is just a convenience
135 * wrapper for {@link String#toCharArray()}.
136 *
137 * @param input the input string to convert
138 * @return the converted char array
139 */
140 public static char[] asCharArray(final String input) {
141 return input.toCharArray();
142 }
143
144 /***
145 * Converts an object array into a double array, calling
146 * {@link Util#asDouble(Object)} on each element.
147 *
148 * @param objArray the array of objects to convert
149 * @return the converted double array
150 * @throws NumberFormatException if an object's <code>toString()</code>
151 * output does not contain a parsable double
152 */
153 public static double[] asDoubleArray(final Object[] objArray)
154 throws NumberFormatException {
155 final double[] result = new double[objArray.length];
156 for (int i = 0; i < objArray.length; i++) {
157 result[i] = Util.asDouble(objArray[i]);
158 }
159 return result;
160 }
161
162 /***
163 * Converts a string into a double array, by {@linkplain
164 * TextUtils#splitString(CharSequence) splitting on whitespace} and calling
165 * {@link CollUtils#asDoubleArray(Object[])} on the result.
166 *
167 * @param input the input string to convert
168 * @return the converted double array
169 * @throws NumberFormatException if one of the tokens does not contain a
170 * parsable double
171 */
172 public static double[] asDoubleArray(final String input)
173 throws NumberFormatException {
174 return asDoubleArray(TextUtils.splitString(input));
175 }
176
177 /***
178 * Converts an object array into a float array, calling
179 * {@link Util#asFloat(Object)} on each element.
180 *
181 * @param objArray the array of objects to convert
182 * @return the converted float array
183 * @throws NumberFormatException if an object's <code>toString()</code>
184 * output does not contain a parsable float
185 */
186 public static float[] asFloatArray(final Object[] objArray)
187 throws NumberFormatException {
188 final float[] result = new float[objArray.length];
189 for (int i = 0; i < objArray.length; i++) {
190 result[i] = Util.asFloat(objArray[i]);
191 }
192 return result;
193 }
194
195 /***
196 * Converts a string into a float array, by {@linkplain
197 * TextUtils#splitString(CharSequence) splitting on whitespace} and calling
198 * {@link CollUtils#asFloatArray(Object[])} on the result.
199 *
200 * @param input the input string to convert
201 * @return the converted float array
202 * @throws NumberFormatException if one of the tokens does not contain a
203 * parsable float
204 */
205 public static float[] asFloatArray(final String input)
206 throws NumberFormatException {
207 return asFloatArray(TextUtils.splitString(input));
208 }
209
210 /***
211 * Converts an object array into an integer array, calling
212 * {@link Util#asInt(Object)} on each element.
213 *
214 * @param objArray the array of objects to convert
215 * @return the converted int array
216 * @throws NumberFormatException if an object's <code>toString()</code>
217 * output does not contain a parsable int
218 */
219 public static int[] asIntArray(final Object[] objArray)
220 throws NumberFormatException {
221 final int[] result = new int[objArray.length];
222 for (int i = 0; i < objArray.length; i++) {
223 result[i] = Util.asInt(objArray[i]);
224 }
225 return result;
226 }
227
228 /***
229 * Converts a string into an integer array, by {@linkplain
230 * TextUtils#splitString(CharSequence) splitting on whitespace} and calling
231 * {@link CollUtils#asIntArray(Object[])} on the result.
232 *
233 * @param input the input string to convert
234 * @return the converted integer array
235 * @throws NumberFormatException if one of the tokens does not contain a
236 * parsable integer
237 */
238 public static int[] asIntArray(final String input)
239 throws NumberFormatException {
240 return asIntArray(TextUtils.splitString(input));
241 }
242
243 /***
244 * Converts an object array into a long array, calling
245 * {@link Util#asLong(Object)} on each element.
246 *
247 * @param objArray the array of objects to convert
248 * @return the converted long array
249 * @throws NumberFormatException if an object's <code>toString()</code>
250 * output does not contain a parsable long
251 */
252 public static long[] asLongArray(final Object[] objArray)
253 throws NumberFormatException {
254 final long[] result = new long[objArray.length];
255 for (int i = 0; i < objArray.length; i++) {
256 result[i] = Util.asLong(objArray[i]);
257 }
258 return result;
259 }
260
261 /***
262 * Converts a string into a long array, by {@linkplain
263 * TextUtils#splitString(CharSequence) splitting on whitespace} and calling
264 * {@link CollUtils#asLongArray(Object[])} on the result.
265 *
266 * @param input the input string to convert
267 * @return the converted long array
268 * @throws NumberFormatException if one of the tokens does not contain a
269 * parsable long
270 */
271 public static long[] asLongArray(final String input)
272 throws NumberFormatException {
273 return asLongArray(TextUtils.splitString(input));
274 }
275
276 /***
277 * Converts an object array into a short array, calling
278 * {@link Util#asShort(Object)} on each element.
279 *
280 * @param objArray the array of objects to convert
281 * @return the converted short array
282 * @throws NumberFormatException if an object's <code>toString()</code>
283 * output does not contain a parsable short
284 */
285 public static short[] asShortArray(final Object[] objArray)
286 throws NumberFormatException {
287 final short[] result = new short[objArray.length];
288 for (int i = 0; i < objArray.length; i++) {
289 result[i] = Util.asShort(objArray[i]);
290 }
291 return result;
292 }
293
294 /***
295 * Converts a string into a short array, by {@linkplain
296 * TextUtils#splitString(CharSequence) splitting on whitespace} and calling
297 * {@link CollUtils#asShortArray(Object[])} on the result.
298 *
299 * @param input the input string to convert
300 * @return the converted short array
301 * @throws NumberFormatException if one of the tokens does not contain a
302 * parsable short
303 */
304 public static short[] asShortArray(final String input)
305 throws NumberFormatException {
306 return asShortArray(TextUtils.splitString(input));
307 }
308
309 /***
310 * Converts an object array into a String array, calling
311 * {@link Util#asString(Object)} on each element.
312 *
313 * @param objArray the array of objects to convert
314 * @return the converted String array
315 */
316 public static String[] asStringArray(final Object[] objArray) {
317 final String[] result = new String[objArray.length];
318 for (int i = 0; i < objArray.length; i++) {
319 result[i] = Util.asString(objArray[i]);
320 }
321 return result;
322 }
323
324 /***
325 * Converts a string into an array of whitespace-separated tokens. This is
326 * just a convenience wrapper for
327 * {@link TextUtils#splitString(CharSequence)}.
328 *
329 * @param input the input string to convert
330 * @return the converted token array
331 */
332 public static String[] asStringArray(final String input) {
333 return TextUtils.splitString(input);
334 }
335
336 /***
337 * Converts a string into an set of whitespace-separated tokens. This
338 * implementation converts the array returned by
339 * {@link #asShortArray(String)}} into a {@link LinkedHashSet}, so the
340 * original iteration order is preserved (but duplicates will be discarded).
341 *
342 * @param input the input string to convert
343 * @return the converted set of tokens, in original order
344 */
345 public static Set<String> asStringSet(final String input) {
346 final Set<String> result = new LinkedHashSet<String>();
347 final String[] tokens = asStringArray(input);
348
349 for (int i = 0; i < tokens.length; i++) {
350 result.add(tokens[i]);
351 }
352 return result;
353 }
354
355 /***
356 * Converts a raw set into a set of strings, calling the
357 * {@link Object#toString()} method for each non-<code>null</code> object.
358 *
359 * @param rawSet the set of objects to convert
360 * @return the converted set of strings, in original order
361 */
362 public static Set<String> asStringSet(final Set rawSet) {
363 final Set<String> result = new LinkedHashSet<String>();
364 final Iterator rawIter = rawSet.iterator();
365 Object obj;
366 String str;
367
368 while (rawIter.hasNext()) {
369 obj = rawIter.next();
370 str = (obj == null) ? null : obj.toString();
371 result.add(str);
372 }
373 return result;
374 }
375
376 /***
377 * Combines two array into a target array, inserting all elements of the
378 * first array and then all elements of the second array in the target
379 * array.
380 *
381 * @param array1 the first array to copy
382 * @param array2 the second array to copy
383 * @param targetArray the array to copy the two other array into; the
384 * type of this array must be suitable to accept elements from both array;
385 * the length of this array must be equal or greater than
386 * <code>array1.length + array2.length</code>
387 */
388 public static void combineArrays(final Object[] array1,
389 final Object[] array2,
390 final Object[] targetArray) {
391 final int lengthOfFirst = array1.length;
392 int i;
393
394 for (i = 0; i < lengthOfFirst; i++) {
395 targetArray[i] = array1[i];
396 }
397
398
399 for (i = 0; i < array2.length; i++) {
400 targetArray[i + lengthOfFirst] = array2[i];
401 }
402 }
403
404 /***
405 * Flattens the elements of the provided array into a single string
406 * of {@link Util#TRUE_CHAR} and {@link Util#FALSE_CHAR} characters,
407 * without using separator characters.
408 *
409 * @param array the array of values to join
410 * @return the flattened string
411 */
412 public static String flatten(final boolean[] array) {
413 final StringBuilder result = new StringBuilder();
414
415 for (int i = 0; i < array.length; i++) {
416 result.append(Util.toChar(array[i]));
417 }
418
419 return result.toString();
420 }
421
422 /***
423 * Flattens the elements of the provided array into a single string,
424 * without using separator characters.
425 *
426 * @param array the array of values to join
427 * @return the flattened string
428 */
429 public static String flatten(final char[] array) {
430 final StringBuilder result = new StringBuilder();
431
432 for (int i = 0; i < array.length; i++) {
433 result.append(array[i]);
434 }
435
436 return result.toString();
437 }
438
439 /***
440 * Flattens the elements of the provided array into a single string,
441 * separating elements by a space character.
442 *
443 * @param array the array of values to join
444 * @return the flattened string
445 */
446 public static String flatten(final double[] array) {
447 final StringBuilder result = new StringBuilder();
448
449 for (int i = 0; i < array.length; i++) {
450 if (i > 0) {
451 result.append(SEPARATOR);
452 }
453 result.append(array[i]);
454 }
455
456 return result.toString();
457 }
458
459 /***
460 * Flattens the elements of the provided array into a single string,
461 * separating elements by a space character.
462 *
463 * @param array the array of values to join
464 * @return the flattened string
465 */
466 public static String flatten(final float[] array) {
467 final StringBuilder result = new StringBuilder();
468
469 for (int i = 0; i < array.length; i++) {
470 if (i > 0) {
471 result.append(SEPARATOR);
472 }
473 result.append(array[i]);
474 }
475
476 return result.toString();
477 }
478
479 /***
480 * Flattens the elements of the provided array into a single string,
481 * separating elements by a space character.
482 *
483 * @param array the array of values to join
484 * @return the flattened string
485 */
486 public static String flatten(final int[] array) {
487 final StringBuilder result = new StringBuilder();
488
489 for (int i = 0; i < array.length; i++) {
490 if (i > 0) {
491 result.append(SEPARATOR);
492 }
493 result.append(array[i]);
494 }
495
496 return result.toString();
497 }
498
499 /***
500 * Flattens the elements of the provided array into a single string,
501 * separating elements by a space character.
502 *
503 * @param array the array of values to join
504 * @return the flattened string
505 */
506 public static String flatten(final long[] array) {
507 final StringBuilder result = new StringBuilder();
508
509 for (int i = 0; i < array.length; i++) {
510 if (i > 0) {
511 result.append(SEPARATOR);
512 }
513 result.append(array[i]);
514 }
515
516 return result.toString();
517 }
518
519 /***
520 * Flattens the objects returned by an iterator into a single string,
521 * separating elements by a space character.
522 *
523 * @param iterator the iterator over the elements to join
524 * @return the flattened string
525 */
526 public static String flatten(final Iterator iterator) {
527 return flatten(iterator, SEPARATOR);
528 }
529
530 /***
531 * Flattens the objects returned by an iterator into a single string,
532 * separating elements by the provided separator.
533 *
534 * @param iterator the iterator over the elements to join
535 * @param separator the separator string to use
536 * @return the flattened string
537 */
538 public static String flatten(final Iterator iterator,
539 final String separator) {
540 final StringBuilder result = new StringBuilder();
541
542 while (iterator.hasNext()) {
543 result.append(iterator.next().toString());
544 if (iterator.hasNext()) {
545 result.append(separator);
546 }
547 }
548 return result.toString();
549 }
550
551 /***
552 * Flattens the elements of the provided array into a single string,
553 * separating elements by a space character.
554 *
555 * @param array the array of values to join
556 * @return the flattened string
557 */
558 public static String flatten(final Object[] array) {
559 return flatten(array, SEPARATOR);
560 }
561
562 /***
563 * Flattens the elements of the provided array into a single string,
564 * separating elements by the provided separator.
565 *
566 * @param array the array of values to join
567 * @param separator the separator string to use
568 * @return the flattened string
569 */
570 public static String flatten(final Object[] array, final String separator) {
571 final StringBuilder result = new StringBuilder();
572
573 for (int i = 0; i < array.length; i++) {
574 if (i > 0) {
575 result.append(separator);
576 }
577 result.append(array[i]);
578 }
579 return result.toString();
580 }
581
582 /***
583 * Flattens the elements of the provided array into a single string,
584 * separating elements by a space character.
585 *
586 * @param array the array of values to join
587 * @return the flattened string
588 */
589 public static String flatten(final short[] array) {
590 final StringBuilder result = new StringBuilder();
591
592 for (int i = 0; i < array.length; i++) {
593 if (i > 0) {
594 result.append(SEPARATOR);
595 }
596 result.append(array[i]);
597 }
598
599 return result.toString();
600 }
601
602 /***
603 * Copied the last <em>n</em> elements from a list into a new list (or all
604 * elements, if the size of the input list is smaller or equal to
605 * <em>n</em>). Modifications of the returned list will not affect the
606 * original list and vice versa.
607 *
608 * <p>If <code>number</code> is 0 or negative or if the original list is
609 * <code>null</code> or empty, an empty list is returned.
610 *
611 * <p>Note that this is somewhat inefficient if the input list is a
612 * {@link java.util.LinkedList} because repeated calls to
613 * {@link List#get(int)} are necessary (unless the whole list is copied).
614 *
615 * @param <T> the type of the list
616 * @param list the input list
617 * @param number the number of elements to copy
618 * @return an ArrayList containing the last elements from the original list;
619 * or an empty ArrayList iff the <code>list</code> is <code>null</code>
620 */
621 public static <T> ArrayList<T> lastN(final List<? extends T> list,
622 final int number) {
623 final ArrayList<T> result;
624 if (list != null) {
625 final int size = list.size();
626 if (number <= size) {
627
628 result = new ArrayList<T>(list);
629 } else {
630
631 result = new ArrayList<T>(number);
632 for (int i = number; i > 0; i--) {
633 result.add(list.get(size - number));
634 }
635 }
636 } else {
637
638 result = new ArrayList<T>(0);
639 }
640 return result;
641 }
642
643 /***
644 * Removes an object from a collection (if it is present), using
645 * identity-based comparisons instead of the
646 * {@link Object#equals(Object) equals}-based comparisons used by
647 * {@link Collection#remove(Object)}.
648 *
649 * @param <T> the type of the collection
650 * @param coll the collection to use
651 * @param obj the object to remove
652 * @return <code>true</code> if the object has been removed from the
653 * collection
654 */
655 public static <T> boolean removeByIdentity(final Collection<T> coll,
656 final T obj) {
657 final Iterator<T> iter = coll.iterator();
658
659
660 while (iter.hasNext()) {
661
662 if (iter.next() == obj) {
663
664 iter.remove();
665 return true;
666 }
667 }
668
669
670 return false;
671 }
672
673
674 /***
675 * Private constructor prevents creation of instances.
676 */
677 private CollUtils() {
678 super();
679 }
680
681 }