001/*-------------------------------------------------------------------------+
002|                                                                          |
003| Copyright 2005-2011 The ConQAT Project                                   |
004|                                                                          |
005| Licensed under the Apache License, Version 2.0 (the "License");          |
006| you may not use this file except in compliance with the License.         |
007| You may obtain a copy of the License at                                  |
008|                                                                          |
009|    http://www.apache.org/licenses/LICENSE-2.0                            |
010|                                                                          |
011| Unless required by applicable law or agreed to in writing, software      |
012| distributed under the License is distributed on an "AS IS" BASIS,        |
013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
014| See the License for the specific language governing permissions and      |
015| limitations under the License.                                           |
016+-------------------------------------------------------------------------*/
017package org.conqat.lib.commons.collections;
018
019import java.lang.reflect.Array;
020import java.util.ArrayDeque;
021import java.util.ArrayList;
022import java.util.Arrays;
023import java.util.Collection;
024import java.util.Collections;
025import java.util.Comparator;
026import java.util.Deque;
027import java.util.EnumSet;
028import java.util.HashMap;
029import java.util.HashSet;
030import java.util.Iterator;
031import java.util.List;
032import java.util.Map;
033import java.util.Objects;
034import java.util.Optional;
035import java.util.Random;
036import java.util.RandomAccess;
037import java.util.Set;
038import java.util.SortedMap;
039import java.util.SortedSet;
040import java.util.function.BiConsumer;
041import java.util.function.BiFunction;
042import java.util.function.Consumer;
043import java.util.function.Function;
044import java.util.function.Predicate;
045import java.util.function.Supplier;
046import java.util.stream.Collectors;
047
048import org.conqat.lib.commons.assertion.CCSMAssert;
049import org.conqat.lib.commons.string.StringUtils;
050
051/**
052 * This class offers utility methods for collections. In can be seen as an
053 * extension to {@link Collections}.
054 */
055public class CollectionUtils {
056
057        /** Empty unmodifiable list. */
058        private static final UnmodifiableList<?> EMPTY_LIST = new UnmodifiableList<>(Collections.emptyList());
059
060        /** Empty unmodifiable map. */
061        private static final UnmodifiableMap<?, ?> EMPTY_MAP = new UnmodifiableMap<>(Collections.emptyMap());
062
063        /** Empty unmodifiable set. */
064        private static final UnmodifiableSet<?> EMPTY_SET = new UnmodifiableSet<>(Collections.emptySet());
065
066        /** Delimiter used in strings to separate list values. */
067        public static final String MULTI_VALUE_DELIMITER = ",";
068
069        /**
070         * Create a hashed set from an array.
071         *
072         * @param <T>
073         *            type
074         * @param elements
075         *            elements in the set.
076         * @return the set.
077         * @see Arrays#asList(Object[])
078         */
079        @SafeVarargs
080        public static <T> HashSet<T> asHashSet(T... elements) {
081                HashSet<T> result = new HashSet<>(elements.length);
082                Collections.addAll(result, elements);
083                return result;
084        }
085
086        /** Creates a new unmodifiable {@link HashMap} based on given pairs. */
087        @SafeVarargs
088        public static <K, V> UnmodifiableMap<K, V> asMap(Pair<K, V>... pairs) {
089                return asMap(new HashMap<>(), pairs);
090        }
091
092        /**
093         * Extends the given map with the pairs and returns an unmodifiable version.
094         */
095        @SafeVarargs
096        public static <K, V> UnmodifiableMap<K, V> asMap(Map<K, V> baseMap, Pair<K, V>... pairs) {
097                for (Pair<K, V> pair : pairs) {
098                        baseMap.put(pair.getFirst(), pair.getSecond());
099                }
100                return asUnmodifiable(baseMap);
101        }
102
103        /** Creates an unmodifiable hash set from an array. */
104        @SafeVarargs
105        public static <T> UnmodifiableSet<T> asUnmodifiableHashSet(T... elements) {
106                return new UnmodifiableSet<>(CollectionUtils.asHashSet(elements));
107        }
108
109        /**
110         * Returns a new unmodifiable collection wrapping the given collection. This
111         * method is here to avoid retyping the generic argument for the collection
112         * class.
113         */
114        public static <T> UnmodifiableCollection<T> asUnmodifiable(Collection<T> c) {
115                return new UnmodifiableCollection<>(c);
116        }
117
118        /**
119         * Returns a new unmodifiable list wrapping the given list. This method is here
120         * to avoid retyping the generic argument for the list class.
121         */
122        public static <T> UnmodifiableList<T> asUnmodifiable(List<T> l) {
123                return new UnmodifiableList<>(l);
124        }
125
126        /**
127         * Returns a new unmodifiable map wrapping the given map. This method is here to
128         * avoid retyping the generic arguments for the map class.
129         */
130        public static <S, T> UnmodifiableMap<S, T> asUnmodifiable(Map<S, T> m) {
131                return new UnmodifiableMap<>(m);
132        }
133
134        /**
135         * Returns a new unmodifiable set wrapping the given set. This method is here to
136         * avoid retyping the generic argument for the set class.
137         */
138        public static <T> UnmodifiableSet<T> asUnmodifiable(Set<T> s) {
139                return new UnmodifiableSet<>(s);
140        }
141
142        /**
143         * Returns a new unmodifiable sorted map wrapping the given sorted map. This
144         * method is here to avoid retyping the generic arguments for the sorted map
145         * class.
146         */
147        public static <S, T> UnmodifiableSortedMap<S, T> asUnmodifiable(SortedMap<S, T> m) {
148                return new UnmodifiableSortedMap<>(m);
149        }
150
151        /**
152         * Returns a new unmodifiable sorted set wrapping the given sorted set. This
153         * method is here to avoid retyping the generic argument for the sorted set
154         * class.
155         */
156        public static <T> UnmodifiableSortedSet<T> asUnmodifiable(SortedSet<T> s) {
157                return new UnmodifiableSortedSet<>(s);
158        }
159
160        /**
161         * The way this method is defined allows to assign it to all parameterized
162         * types, i.e. both of the following statements are accepted by the compiler
163         * without warnings:
164         *
165         * <pre>
166         * UnmodifiableList&lt;String&gt; emptyList = CollectionUtils.emptyList();
167         *
168         * UnmodifiableList&lt;Date&gt; emptyList = CollectionUtils.emptyList();
169         * </pre>
170         *
171         * @return the empty list
172         */
173        @SuppressWarnings("unchecked")
174        public static final <T> UnmodifiableList<T> emptyList() {
175                return (UnmodifiableList<T>) EMPTY_LIST;
176        }
177
178        /** Returns an empty map. See {@link #emptyList()} for further details. */
179        @SuppressWarnings("unchecked")
180        public static final <S, T> UnmodifiableMap<S, T> emptyMap() {
181                return (UnmodifiableMap<S, T>) EMPTY_MAP;
182        }
183
184        /** Returns an empty set. See {@link #emptyList()} for further details. */
185        @SuppressWarnings("unchecked")
186        public static final <T> UnmodifiableSet<T> emptySet() {
187                return (UnmodifiableSet<T>) EMPTY_SET;
188        }
189
190        /**
191         * Sorts the specified list into ascending order, according to the <i>natural
192         * ordering</i> of its elements.
193         * <p>
194         * All elements in the list must implement the Comparable interface.
195         * Furthermore, all elements in the list must be mutually comparable (that is,
196         * e1.compareTo(e2) must not throw a <code>ClassCastException</code> for any
197         * elements e1 and e2 in the list).
198         * <p>
199         * This method does not modify the original collection.
200         */
201        public static <T extends Comparable<? super T>> ArrayList<T> sort(Collection<T> collection) {
202                ArrayList<T> list = new ArrayList<>(collection);
203                Collections.sort(list);
204                return list;
205        }
206
207        /**
208         * Returns a list that contains the elements of the specified list in reversed
209         * order.
210         * <p>
211         * This method does not modify the original collection.
212         */
213        public static <T> ArrayList<T> reverse(Collection<T> list) {
214                ArrayList<T> reversed = new ArrayList<>(list);
215                Collections.reverse(reversed);
216                return reversed;
217        }
218
219        /**
220         * Returns all values, which occur multiple times in the list.
221         * <p>
222         * It doesn't tell you how often it occurs, just that it is more than once.
223         */
224        public static <T> Set<T> getDuplicates(List<T> values) {
225                Set<T> duplicates = new HashSet<>();
226                Set<T> temp = new HashSet<>();
227                for (T key : values) {
228                        if (!temp.add(key)) {
229                                duplicates.add(key);
230                        }
231                }
232                return duplicates;
233        }
234
235        /**
236         * Applies the mapper {@link Function} to all items in the collection and
237         * returns the resulting {@link List}.
238         * <p>
239         * This method does not modify the original collection.
240         */
241        public static <T, R> List<R> map(Collection<T> list, Function<? super T, ? extends R> mapper) {
242                List<R> result = new ArrayList<>(list.size());
243                for (T entry : list) {
244                        result.add(mapper.apply(entry));
245                }
246                return result;
247        }
248
249        /**
250         * Applies the mapper {@link Function} to all items in the collection and
251         * returns the resulting {@link Set} only containing distinct mapped values.
252         * <p>
253         * This method does not modify the original collection.
254         */
255        public static <T, R> Set<R> mapToSet(Collection<T> list, Function<? super T, ? extends R> mapper) {
256                Set<R> result = new HashSet<>();
257                for (T entry : list) {
258                        result.add(mapper.apply(entry));
259                }
260                return result;
261        }
262
263        /**
264         * Applies the key and value mapper {@link Function}s to all keys/values in the
265         * collection and returns the resulting {@link Map}.
266         * <p>
267         * This method does not modify the original collection.
268         */
269        public static <K1, V1, K2, V2> Map<K2, V2> map(Map<K1, V1> map, Function<K1, ? extends K2> keyMapper,
270                        Function<V1, ? extends V2> valueMapper) {
271                Map<K2, V2> result = new HashMap<>(map.size());
272                map.forEach((key, value) -> result.put(keyMapper.apply(key), valueMapper.apply(value)));
273                return result;
274        }
275
276        /**
277         * Applies the mapper {@link Function} to all items in the array and returns the
278         * resulting {@link List}.
279         * <p>
280         * This method does not modify the original array.
281         */
282        public static <T, R> List<R> map(T[] array, Function<? super T, ? extends R> mapper) {
283                return map(Arrays.asList(array), mapper);
284        }
285
286        /**
287         * Applies the mapper {@link Function} to all items in the collection, but only
288         * adds the result item to the return list if it is not already in the list.
289         * Returns the resulting {@link List}.
290         * <p>
291         * This method does not modify the original collection.
292         */
293        public static <T, R> List<R> mapDistinct(Collection<T> list, Function<? super T, ? extends R> mapper) {
294                Set<R> encounteredItems = new HashSet<>();
295                List<R> result = new ArrayList<>();
296                for (T entry : list) {
297                        R resultItem = mapper.apply(entry);
298                        if (encounteredItems.add(resultItem)) {
299                                result.add(resultItem);
300                        }
301                }
302                return result;
303        }
304
305        /**
306         * Applies the mapper {@link FunctionWithException} to all items in the list and
307         * returns the resulting {@link List}.
308         * <p>
309         * This method does not modify the original collection.
310         *
311         * @throws E
312         *             if the mapper function throws this exception for any of the
313         *             elements of the original list.
314         */
315        public static <T, R, E extends Exception> List<R> mapWithException(Collection<T> list,
316                        FunctionWithException<? super T, ? extends R, ? extends E> mapper) throws E {
317                List<R> result = new ArrayList<>(list.size());
318                for (T entry : list) {
319                        result.add(mapper.apply(entry));
320                }
321                return result;
322        }
323
324        /** Returns a new List containing only the elements at the given indices. */
325        public static <T> ArrayList<T> getIndices(List<T> list, List<Integer> indices) {
326                ArrayList<T> filteredList = new ArrayList<>();
327                for (int index : indices) {
328                        filteredList.add(list.get(index));
329                }
330                return filteredList;
331        }
332
333        /**
334         * Returns a new List containing all elements of the given list except for those
335         * with the given indices.
336         */
337        public static <T> List<T> removeIndicesFrom(List<T> elements, Set<Integer> indices) {
338                List<T> result = new ArrayList<>();
339                for (int i = 0; i < elements.size(); i++) {
340                        if (!indices.contains(i)) {
341                                result.add(elements.get(i));
342                        }
343                }
344                return result;
345        }
346
347        /**
348         * Returns the indices of null elements in the given list. The returned list is
349         * strictly ordered (returnedList.get(x) is greater than returnedList.get(x-1)).
350         */
351        public static List<Integer> getNullIndices(List<?> list) {
352                List<Integer> nullIndices = new ArrayList<>();
353                for (int i = 0; i < list.size(); i++) {
354                        if (list.get(i) == null) {
355                                nullIndices.add(i);
356                        }
357                }
358                return nullIndices;
359        }
360
361        /**
362         * This interface is the same as {@link Supplier}, except it allows throwing a
363         * checked exception.
364         */
365        @FunctionalInterface
366        public interface SupplierWithException<T, E extends Exception> {
367
368                /**
369                 * Returns the supplied value. May throw a declared exception.
370                 */
371                T get() throws E;
372        }
373
374        /**
375         * This interface is the same as {@link Function}, except it allows throwing a
376         * checked exception.
377         */
378        @FunctionalInterface
379        public interface FunctionWithException<T, R, E extends Exception> {
380
381                /**
382                 * Applies the function to the given argument. May throw the declared exception.
383                 */
384                R apply(T t) throws E;
385
386        }
387
388        /**
389         * This interface is the same as {@link Consumer}, except it allows throwing a
390         * checked exception.
391         */
392        @FunctionalInterface
393        public interface ConsumerWithException<T, E extends Exception> {
394
395                /**
396                 * Performs this operation on the given argument.
397                 *
398                 * @param t
399                 *            the input argument
400                 */
401                void accept(T t) throws E;
402
403        }
404
405        /**
406         * This interface is the same as {@link Consumer}, except it allows throwing two
407         * checked exceptions.
408         */
409        @FunctionalInterface
410        public interface ConsumerWithTwoExceptions<T, E1 extends Exception, E2 extends Exception> {
411
412                /**
413                 * Performs this operation on the given argument.
414                 *
415                 * @param t
416                 *            the input argument
417                 */
418                void accept(T t) throws E1, E2;
419
420        }
421
422        /**
423         * This interface is the same as {@link BiConsumer}, except it allows throwing a
424         * checked exceptions.
425         */
426        @FunctionalInterface
427        public interface BiConsumerWithException<S, T, E extends Exception> {
428
429                /**
430                 * Performs this operation on the given argument.
431                 *
432                 * @param t
433                 *            the input argument
434                 */
435                void accept(S s, T t) throws E;
436
437        }
438
439        /**
440         * This interface is the same as {@link BiConsumer}, except it allows throwing
441         * two checked exceptions.
442         */
443        @FunctionalInterface
444        public interface BiConsumerWithTwoExceptions<S, T, E1 extends Exception, E2 extends Exception> {
445
446                /**
447                 * Performs this operation on the given argument.
448                 *
449                 * @param t
450                 *            the input argument
451                 */
452                void accept(S s, T t) throws E1, E2;
453
454        }
455
456        /**
457         * This interface is the same as {@link BiFunction}, except it allows throwing a
458         * checked exception.
459         */
460        @FunctionalInterface
461        public interface BiFunctionWithException<T, U, R, E extends Exception> {
462                /**
463                 * Returns the supplied value. May throw a declared exception.
464                 */
465                R apply(T t, U u) throws E;
466        }
467
468        /**
469         * Filters the collection by testing all items against the {@link Predicate} and
470         * returning a {@link List} of those for which it returns <code>true</code>.
471         *
472         * <p>
473         * This method does not modify the original collection.
474         */
475        public static <T> List<T> filter(Collection<T> collection, Predicate<? super T> filter) {
476                ArrayList<T> result = new ArrayList<>();
477                for (T entry : collection) {
478                        if (filter.test(entry)) {
479                                result.add(entry);
480                        }
481                }
482                return result;
483        }
484
485        /**
486         * Filters the collection by testing all items against the given predicate and
487         * returning a {@link List} of those for which it returns <code>true</code>.
488         * Propagates checked exceptions of the given predicate.
489         *
490         * <p>
491         * This method does not modify the original collection.
492         */
493        public static <T, E extends Exception> List<T> filterWithException(Collection<T> collection,
494                        FunctionWithException<? super T, Boolean, E> filter) throws E {
495                ArrayList<T> result = new ArrayList<>();
496                for (T entry : collection) {
497                        if (filter.apply(entry)) {
498                                result.add(entry);
499                        }
500                }
501                return result;
502        }
503
504        /**
505         * Filters the collection by testing all items against the {@link Predicate} and
506         * returning a {@link Set} of those for which it returns <code>true</code>.
507         *
508         * <p>
509         * This method does not modify the original collection.
510         */
511        public static <T> Set<T> filterToSet(Collection<T> collection, Predicate<? super T> filter) {
512                Set<T> result = new HashSet<>();
513                for (T entry : collection) {
514                        if (filter.test(entry)) {
515                                result.add(entry);
516                        }
517                }
518                return result;
519        }
520
521        /**
522         * Applies the mapper to all items in the list, for which the filter
523         * {@link Predicate} returns <code>true</code> and returns the results as a
524         * {@link List}.
525         * <p>
526         * This method does not modify the original collection.
527         */
528        public static <T, R> List<R> filterAndMap(Collection<T> list, Predicate<? super T> filter,
529                        Function<? super T, ? extends R> mapper) {
530                List<R> result = new ArrayList<>();
531                for (T entry : list) {
532                        if (filter.test(entry)) {
533                                result.add(mapper.apply(entry));
534                        }
535                }
536                return result;
537        }
538
539        /**
540         * Returns a list that contains all elements of the specified list <B>except</B>
541         * the element at the specified index. Removes the index from the new List.
542         * <p>
543         * This method does not modify the original list.
544         */
545        public static <T> List<T> remove(List<T> list, int index) {
546                ArrayList<T> result = new ArrayList<>(list);
547                result.remove(index);
548                return result;
549        }
550
551        /**
552         * Sorts the specified list according to the order induced by the specified
553         * comparator.
554         * <p>
555         * All elements in the list must implement the Comparable interface.
556         * Furthermore, all elements in the list must be mutually comparable (that is,
557         * e1.compareTo(e2) must not throw a <code>ClassCastException</code> for any
558         * elements e1 and e2 in the list).
559         * <p>
560         * This method does not modify the original collection.
561         */
562        public static <T> List<T> sort(Collection<T> collection, Comparator<? super T> comparator) {
563                ArrayList<T> list = new ArrayList<>(collection);
564                list.sort(comparator);
565                return list;
566        }
567
568        /** Returns a sorted unmodifiable list for a collection. */
569        public static <T extends Comparable<? super T>> UnmodifiableList<T> asSortedUnmodifiableList(
570                        Collection<T> collection) {
571                return asUnmodifiable(sort(collection));
572        }
573
574        /**
575         * Returns one object from an {@link Iterable} or <code>null</code> if the
576         * iterable is empty.
577         */
578        public static <T> T getAny(Iterable<T> iterable) {
579                Iterator<T> iterator = iterable.iterator();
580                if (!iterator.hasNext()) {
581                        return null;
582                }
583                return iterator.next();
584        }
585
586        /**
587         * Convert collection to array. This is a bit cleaner version of
588         * {@link Collection#toArray(Object[])}.
589         */
590        @SuppressWarnings("unchecked")
591        public static <T> T[] toArray(Collection<? extends T> collection, Class<T> type) {
592                T[] result = (T[]) java.lang.reflect.Array.newInstance(type, collection.size());
593
594                Iterator<? extends T> it = collection.iterator();
595                for (int i = 0; i < collection.size(); i++) {
596                        result[i] = it.next();
597                }
598
599                return result;
600        }
601
602        /**
603         * Copy an array. This is a shortcut for {@link Arrays#copyOf(Object[], int)}
604         * that does not require to specify the length.
605         */
606        public static <T> T[] copyArray(T[] original) {
607                return Arrays.copyOf(original, original.length);
608        }
609
610        /**
611         * Compute list of unordered pairs for all elements contained in a collection.
612         */
613        public static <T> List<ImmutablePair<T, T>> computeUnorderedPairs(Collection<T> collection) {
614                List<T> elements = new ArrayList<>(collection);
615                List<ImmutablePair<T, T>> pairs = new ArrayList<>();
616
617                int size = elements.size();
618                for (int firstIndex = 0; firstIndex < size; firstIndex++) {
619                        for (int secondIndex = firstIndex + 1; secondIndex < size; secondIndex++) {
620                                pairs.add(new ImmutablePair<>(elements.get(firstIndex), elements.get(secondIndex)));
621                        }
622                }
623                return pairs;
624        }
625
626        /**
627         * Returns the last element in list or <code>null</code>, if list is empty.
628         */
629        @SuppressWarnings("unchecked")
630        public static <T> T getLast(List<T> list) {
631                if (list.isEmpty()) {
632                        return null;
633                }
634                if (list instanceof Deque<?>) {
635                        return ((Deque<T>) list).getLast();
636                }
637                return list.get(list.size() - 1);
638        }
639
640        /**
641         * Returns the sublist of all but the first element in list or
642         * <code>null</code>, if list is empty.
643         */
644        public static <T> List<T> getRest(List<T> list) {
645                if (list.isEmpty()) {
646                        return null;
647                }
648                return list.subList(1, list.size());
649        }
650
651        /** Sorts the pair list by first index. */
652        public static <S extends Comparable<S>, T> void sortByFirst(PairList<S, T> list) {
653                sortByFirst(list, Comparator.naturalOrder());
654        }
655
656        /** Sorts the pair list with the given comparator. */
657        public static <S, T> void sortByFirst(PairList<S, T> list, Comparator<S> comparator) {
658                SortableDataUtils.sort(new ISortableData() {
659
660                        @Override
661                        public void swap(int i, int j) {
662                                list.swapEntries(i, j);
663                        }
664
665                        @Override
666                        public int size() {
667                                return list.size();
668                        }
669
670                        @Override
671                        public boolean isLess(int i, int j) {
672                                return comparator.compare(list.getFirst(i), list.getFirst(j)) < 0;
673                        }
674                });
675        }
676
677        /**
678         * Returns a list implementation that allows for efficient random access.
679         *
680         * If the passed collection already supports random access, it gets returned
681         * directly. Otherwise a list that supports random access is returned with the
682         * same content as the passed list.
683         */
684        public static <T> List<T> asRandomAccessList(Collection<T> list) {
685                // It is not guaranteed that implementations of RandomAccess also
686                // implement List. Hence, we check for both.
687                if (list instanceof List<?> && list instanceof RandomAccess) {
688                        return (List<T>) list;
689                }
690
691                return new ArrayList<>(list);
692        }
693
694        @SafeVarargs
695        private static <T, C extends Collection<T>> C unionCollection(Supplier<C> collectionSupplier,
696                        Collection<T> collection1, Collection<T>... furtherCollections) {
697                C result = collectionSupplier.get();
698                if (collection1 != null) {
699                        result.addAll(collection1);
700                }
701                for (Collection<T> collection : furtherCollections) {
702                        if (collection != null) {
703                                result.addAll(collection);
704                        }
705                }
706                return result;
707        }
708
709        /**
710         * Return a set containing the union of all provided collections. We use a
711         * {@link HashSet}, i.e. the elements should support hashing.
712         *
713         * We use two separate arguments to ensure on the interface level that at least
714         * one collection is provided. This is transparent for the caller.
715         *
716         * All arguments can be null. The result will always be non-null and will be an
717         * empty set if all arguments are null.
718         */
719        @SafeVarargs
720        public static <T> HashSet<T> unionSet(Collection<T> collection1, Collection<T>... furtherCollections) {
721                return unionCollection(HashSet::new, collection1, furtherCollections);
722        }
723
724        /**
725         * Return a set containing the union of all provided {@link EnumSet}s.
726         *
727         * We use two separate arguments to ensure on the interface level that at least
728         * one collection is provided. This is transparent for the caller.
729         *
730         * None of the arguments may be null.
731         */
732        @SafeVarargs
733        public static <T extends Enum<T>> EnumSet<T> enumUnionSet(EnumSet<T> initialSet, EnumSet<T>... otherSets) {
734                EnumSet<T> union = EnumSet.copyOf(initialSet);
735                for (EnumSet<T> other : otherSets) {
736                        union.addAll(other);
737                }
738                return union;
739        }
740
741        /**
742         * Return a set containing the union of all provided collections. We use a
743         * {@link ArrayList} and the result preserves duplicates between and within the
744         * collections.
745         *
746         * We use two separate arguments to ensure on the interface level that at least
747         * one collection is provided. This is transparent for the caller.
748         *
749         * All arguments can be null. The result will always be non-null and will be an
750         * empty set if all arguments are null.
751         */
752        @SafeVarargs
753        public static <T> ArrayList<T> unionList(Collection<T> collection1, Collection<T>... furtherCollections) {
754                return unionCollection(ArrayList::new, collection1, furtherCollections);
755        }
756
757        /**
758         * Return a set containing the union of all elements of the provided sets. We
759         * use a {@link HashSet}, i.e. the elements should support hashing.
760         */
761        public static <T> HashSet<T> unionSetAll(Collection<? extends Collection<T>> sets) {
762                HashSet<T> result = new HashSet<>();
763                for (Collection<T> set : sets) {
764                        result.addAll(set);
765                }
766                return result;
767        }
768
769        /**
770         * Creates a new set only containing those elements of the given collection that
771         * are not in elementsToRemove. Substracts elementsToRemove from collection.
772         * Both collections may be <code>null</code>.
773         */
774        public static <T> Set<T> subtract(Collection<T> collection, Collection<T> elementsToRemove) {
775                Set<T> result = new HashSet<>();
776                if (collection != null) {
777                        result.addAll(collection);
778                }
779                if (elementsToRemove != null) {
780                        result.removeAll(elementsToRemove);
781                }
782                return result;
783        }
784
785        /**
786         * Adds all elements of collection2 to collection1. collection2 may be
787         * <code>null</code>, in which case nothing happens.
788         */
789        public static <T> void addAllSafe(Collection<T> collection1, Collection<T> collection2) {
790                if (collection2 != null) {
791                        collection1.addAll(collection2);
792                }
793        }
794
795        /**
796         * Return a set containing the intersection of all provided collections. We use
797         * a {@link HashSet}, i.e. the elements should support hashing.
798         *
799         * We use two separate arguments to ensure on the interface level that at least
800         * one collection is provided. This is transparent for the caller.
801         */
802        @SafeVarargs
803        public static <T> HashSet<T> intersectionSet(Collection<T> collection1, Collection<T>... furtherCollections) {
804                HashSet<T> result = new HashSet<>(collection1);
805                for (Collection<T> collection : furtherCollections) {
806                        if (collection instanceof Set) {
807                                result.retainAll(collection);
808                        } else {
809                                // if the collection is not already a set, it will be
810                                // significantly faster to first build a set, to speed up the
811                                // containment query in the following call.
812                                result.retainAll(new HashSet<>(collection));
813                        }
814                }
815                return result;
816        }
817
818        /**
819         * Returns the set-theoretic difference between the first and the additional
820         * collections, i.e. a set containing all elements that occur in the first, but
821         * not in any of the other collections. We use a {@link HashSet}, so the
822         * elements should support hashing.
823         */
824        @SafeVarargs
825        public static <T> HashSet<T> differenceSet(Collection<T> collection1,
826                        Collection<? extends T>... furtherCollections) {
827                HashSet<T> result = new HashSet<>(collection1);
828                for (Collection<? extends T> collection : furtherCollections) {
829                        if (collection instanceof Set) {
830                                result.removeAll(collection);
831                        } else {
832                                // if the collection is not already a set, it will be
833                                // significantly faster to first build a set, to speed up the
834                                // containment query in the following call.
835                                result.removeAll(new HashSet<>(collection));
836                        }
837                }
838                return result;
839        }
840
841        /** Checks whether collection is null or empty */
842        public static boolean isNullOrEmpty(Collection<?> collection) {
843                return collection == null || collection.isEmpty();
844        }
845
846        /** Checks whether map is null or empty */
847        public static boolean isNullOrEmpty(Map<?, ?> map) {
848                return map == null || map.isEmpty();
849        }
850
851        /**
852         * Truncates the given list by removing elements from the end such that
853         * numElements entries remain. If the list has less than numElements entries, it
854         * remains unchanged. Thus, this method ensures that the size of the list is <=
855         * numElements.
856         */
857        public static void truncateEnd(List<?> list, int numElements) {
858                if (list.size() > numElements) {
859                        list.subList(numElements, list.size()).clear();
860                }
861        }
862
863        /**
864         * Divides the given set randomly but, as far as possible, evenly into k subsets
865         * of equal size, i.e., if set.size() is not a multiple of k, (k-(set.size()
866         * modulo k)) of the resulting sets have one element less.
867         *
868         * @param <S>
869         *            must support hashing.
870         */
871        public static <S> List<Set<S>> divideEvenlyIntoKSubsets(Set<S> set, int k, Random rnd) {
872                int n = set.size();
873                CCSMAssert.isTrue(n >= k, "The size of the set must be at least k");
874                CCSMAssert.isTrue(k > 0, "k must be greater than 0");
875
876                List<S> shuffled = new ArrayList<>(set);
877                Collections.shuffle(shuffled, rnd);
878
879                List<Set<S>> result = new ArrayList<>();
880
881                // we can fill (n%k) buckets with (n/k+1) elements
882                int subsetSize = n / k + 1;
883                for (int i = 0; i < n % k; i++) {
884                        result.add(new HashSet<>(shuffled.subList(i * subsetSize, (i + 1) * subsetSize)));
885                }
886
887                int offset = n % k * subsetSize;
888
889                // fill the rest of the buckets with (n/k) elements
890                subsetSize = n / k;
891                for (int i = 0; i < k - n % k; i++) {
892                        result.add(new HashSet<>(shuffled.subList(offset + i * subsetSize, offset + (i + 1) * subsetSize)));
893                }
894
895                return result;
896        }
897
898        /** Obtain all permutations of the provided elements. */
899        public static <T> List<List<T>> getAllPermutations(@SuppressWarnings("unchecked") T... elements) {
900                List<List<T>> result = new ArrayList<>();
901                permute(Arrays.asList(elements), 0, result);
902                return result;
903        }
904
905        /** Recursively creates permutations. */
906        private static <T> void permute(List<T> list, int index, List<List<T>> result) {
907                for (int i = index; i < list.size(); i++) {
908                        Collections.swap(list, i, index);
909                        permute(list, index + 1, result);
910                        Collections.swap(list, index, i);
911                }
912                if (index == list.size() - 1) {
913                        result.add(new ArrayList<>(list));
914                }
915        }
916
917        /**
918         * Returns the power set of the given input list. Note that elements are treated
919         * as unique, i.e. we do not really use set semantics here. Also note that the
920         * returned list has 2^n elements for n input elements, so the input list should
921         * not be too large.
922         */
923        public static <T> List<List<T>> getPowerSet(List<T> input) {
924                return getPowerSet(input, 0);
925        }
926
927        /**
928         * Returns the power set of the given input list, only considering elements at
929         * or after index <code>start</code>.
930         */
931        private static <T> List<List<T>> getPowerSet(List<T> input, int start) {
932                ArrayList<List<T>> result = new ArrayList<>();
933                if (start >= input.size()) {
934                        result.add(new ArrayList<>());
935                } else {
936                        T element = input.get(start);
937                        for (List<T> list : getPowerSet(input, start + 1)) {
938                                List<T> copy = new ArrayList<>();
939                                copy.add(element);
940                                copy.addAll(list);
941
942                                result.add(list);
943                                result.add(copy);
944                        }
945                }
946                return result;
947        }
948
949        /**
950         * Returns the input list, or {@link #emptyList()} if the input is null.
951         */
952        public static <T> List<T> emptyIfNull(List<T> input) {
953                if (input == null) {
954                        return emptyList();
955                }
956                return input;
957        }
958
959        /**
960         * Returns the input map, or uses the given supplier to create a new one.
961         */
962        public static <K, V, M extends Map<K, V>> M emptyIfNull(M input, Supplier<M> supplier) {
963                return Optional.ofNullable(input).orElseGet(supplier);
964        }
965
966        /** Removes an element from the array and returns the new array. */
967        @SuppressWarnings("unchecked")
968        public static <T> T[] removeElementFromArray(T element, T[] array) {
969                ArrayList<T> result = new ArrayList<>(Arrays.asList(array));
970                result.remove(element);
971                return toArray(result, (Class<T>) element.getClass());
972        }
973
974        /**
975         * Returns a new list containing only the non-null elements of the given list.
976         */
977        public static <T> List<T> filterNullEntries(List<T> list) {
978                return filter(list, Objects::nonNull);
979        }
980
981        /**
982         * Returns a new list containing only the non-null elements of the given array.
983         */
984        public static <T> List<T> filterNullEntries(T[] array) {
985                return filterNullEntries(Arrays.asList(array));
986        }
987
988        /**
989         * Concatenate two arrays to a new one. See also:
990         * http://stackoverflow.com/a/80503/205903
991         */
992        public static <T> T[] concatenateArrays(T[] a, T[] b) {
993                int length1 = a.length;
994                int length2 = b.length;
995
996                @SuppressWarnings("unchecked")
997                T[] newArray = (T[]) Array.newInstance(a.getClass().getComponentType(), length1 + length2);
998                System.arraycopy(a, 0, newArray, 0, length1);
999                System.arraycopy(b, 0, newArray, length1, length2);
1000
1001                return newArray;
1002        }
1003
1004        /** Returns if any element in the collection matches the predicate. */
1005        public static <T> boolean anyMatch(Collection<? extends T> collection, Predicate<T> predicate) {
1006                for (T element : collection) {
1007                        if (predicate.test(element)) {
1008                                return true;
1009                        }
1010                }
1011                return false;
1012        }
1013
1014        /** Returns if all elements in the collection match the predicate. */
1015        public static <T> boolean allMatch(Collection<? extends T> collection, Predicate<T> predicate) {
1016                for (T element : collection) {
1017                        if (!predicate.test(element)) {
1018                                return false;
1019                        }
1020                }
1021                return true;
1022        }
1023
1024        /**
1025         * Sorts the given collection topologically. The given
1026         * <code>getSuccessors</code> function must establish an order on the elements
1027         * of the collection (more details below).
1028         *
1029         * The sorting is stable if the stream() iterator on the given collection is
1030         * stable.
1031         *
1032         * The result of this function is a <code>Pair</code>. The first item of the
1033         * pair contains the sorted collection as a list. The second item contains a set
1034         * of elements that could not be fit into the topological order (in case there
1035         * are cycles in the partial order). This second item is empty if there are no
1036         * cycles. Elements of the second item are not contained in the sorted list, so
1037         * callers should check whether the second item is empty.
1038         *
1039         * Direction of the sorting: if <code>getSuccessors(A).contains(B)</code>, then
1040         * <code>A</code> will be before <code>B</code> in the sorted list.
1041         *
1042         * Details on the order established by <code>getSuccessors</code>: In
1043         * literature, this should be a partial order, but we don't seem to require the
1044         * properties of partial orders (reflexivity, transitivity, antisymmetry). We
1045         * just need an order relation that maps each element to its direct successors.
1046         * In fact this method will be faster when the order relation is smaller, so
1047         * forget reflexivity and transitivity. Antisymmetry would be nice (otherwise
1048         * you'll get a cycle for sure).
1049         *
1050         * If <code>getSuccessors</code> returns null for an element, we will treat this
1051         * as if it was an empty collection.
1052         *
1053         * @param collection
1054         *            the collection to be sorted
1055         * @param getSuccessors
1056         *            the order relation (described above)
1057         * @return a topologically sorted collection
1058         */
1059        public static <T> Pair<List<T>, List<T>> topSort(Collection<T> collection,
1060                        Function<T, Collection<T>> getSuccessors) {
1061                UnmodifiableSet<T> inputSet = CollectionUtils.asUnmodifiable(new HashSet<>(collection));
1062                // counts how many unhandled predecessors an element has
1063                // elements not in this list have no unhandled predecessors
1064                CounterSet<T> numUnhandledPredecessors = new CounterSet<>();
1065                for (T element : collection) {
1066                        Collection<? extends T> successors = getSuccessors.apply(element);
1067                        if (successors != null) {
1068                                successors.stream().filter(inputSet::contains).forEach(numUnhandledPredecessors::inc);
1069                        }
1070                }
1071                // elements that have no predecessors (they can be inserted in the
1072                // sorted list)
1073                Deque<T> freeElements = collection.stream().filter(element -> !numUnhandledPredecessors.contains(element))
1074                                .collect(Collectors.toCollection(ArrayDeque::new));
1075                List<T> result = new ArrayList<>(collection.size());
1076                while (!freeElements.isEmpty()) {
1077                        T element = freeElements.remove();
1078                        result.add(element);
1079                        handleTopSortElementSuccessors(getSuccessors.apply(element), numUnhandledPredecessors, freeElements,
1080                                        inputSet);
1081                }
1082                // need to sort for stable result
1083                List<T> cycle = numUnhandledPredecessors.getKeys().stream().sorted().collect(Collectors.toList());
1084                return new Pair<>(result, cycle);
1085        }
1086
1087        /**
1088         * This method is part of the {@link #topSort(Collection, Function)} algorithm.
1089         * It handles the successors of one element that has been inserted in the
1090         * top-sorted list.
1091         *
1092         * This method considers only successors that are part of the given filterSet.
1093         * For each of these successors, it decreases the numUnhandledPredecessors entry
1094         * by one. If a successor has no predecessors any more after the decrease, it is
1095         * added to the given freeElements.
1096         */
1097        private static <T> void handleTopSortElementSuccessors(Collection<? extends T> successors,
1098                        CounterSet<T> numUnhandledPredecessors, Deque<T> freeElements, UnmodifiableSet<T> filterSet) {
1099                if (successors != null) {
1100                        successors.stream().filter(filterSet::contains).forEach(successor -> {
1101                                numUnhandledPredecessors.inc(successor, -1);
1102                                if (numUnhandledPredecessors.getValue(successor) <= 0) {
1103                                        freeElements.add(successor);
1104                                        numUnhandledPredecessors.remove(successor);
1105                                }
1106                        });
1107                }
1108        }
1109
1110        /**
1111         * Sorts the given collection topologically, even if it contains cycles
1112         * (deterministically random elements in the cycle are removed). The given
1113         * <code>getSuccessors</code> function must establish an order on the elements
1114         * of the collection (more details below). The given
1115         * <code>getPredecessors</code> function must establish the reverse order of
1116         * <code>getSuccessors</code>.
1117         *
1118         *
1119         * The sorting is stable if the stream() iterator on the given collection is
1120         * stable.
1121         *
1122         * The result of this function is a <code>Pair</code>. The first item of the
1123         * pair contains the sorted collection as a list. The second item contains a
1124         * list of cycle elements that were removed to enable topological sorting.
1125         *
1126         * Direction of the sorting: if <code>getSuccessors(A).contains(B)</code>, then
1127         * <code>A</code> will be before <code>B</code> in the sorted list.
1128         *
1129         * For detail requirements on <code>getSuccessors</code> and
1130         * <code>getPredecessors</code>, see {@link #topSort(Collection, Function)}.
1131         *
1132         * @param collection
1133         *            the collection to be sorted
1134         * @param getSuccessors
1135         *            the order relation (described above)
1136         * @return a topologically sorted collection
1137         */
1138        public static <T> Pair<List<T>, Set<T>> topSortRemoveCycles(Collection<T> collection,
1139                        Function<T, Collection<T>> getSuccessors, Function<T, Collection<T>> getPredecessors) {
1140                // First remove all nodes that have trivial cycle references to themselves
1141                Set<T> removedCycleElements = collection.stream().filter(node -> {
1142                        Collection<T> successors = getSuccessors.apply(node);
1143                        return successors != null && successors.contains(node);
1144                }).collect(Collectors.toSet());
1145                List<T> reducedCollection = new ArrayList<>(collection);
1146                reducedCollection.removeIf(removedCycleElements::contains);
1147
1148                Pair<List<T>, List<T>> topSorted = topSort(reducedCollection, getSuccessors);
1149                if (topSorted.getSecond().isEmpty()) {
1150                        return new Pair<>(topSorted.getFirst(), removedCycleElements);
1151                }
1152
1153                /*
1154                 * Implementation idea: After remove non-cycle vertices alternatingly from "top"
1155                 * and "bottom" and store them for the result. From the resulting cycle, remove
1156                 * one vertex and repeat.
1157                 */
1158                List<T> tailElements = new ArrayList<>();
1159                List<T> headElements = topSorted.getFirst();
1160                List<T> cycle = topSorted.getSecond();
1161                while (!cycle.isEmpty()) {
1162                        Pair<List<T>, List<T>> inverseTopSortedCycle = topSort(cycle, getPredecessors);
1163                        tailElements.addAll(inverseTopSortedCycle.getFirst());
1164                        cycle = inverseTopSortedCycle.getSecond();
1165                        if (!cycle.isEmpty()) {
1166                                removedCycleElements.add(cycle.remove(cycle.size() - 1));
1167                        }
1168                        Pair<List<T>, List<T>> topSortedCycle = topSort(cycle, getSuccessors);
1169                        headElements.addAll(topSortedCycle.getFirst());
1170                        cycle = topSortedCycle.getSecond();
1171                }
1172                headElements.addAll(reverse(tailElements));
1173                return new Pair<>(headElements, removedCycleElements);
1174        }
1175
1176        /**
1177         * Maps all entries of the given Collection to their string representations.
1178         * This method always returns a list. The order of elements in the returned list
1179         * corresponds to the order of element returned by input.stream(), i.e., if
1180         * input is a List then the order is stable, if input is a set then the order is
1181         * random.
1182         */
1183        public static List<String> toStringSet(Collection<?> input) {
1184                return input.stream().map(Object::toString).collect(Collectors.toList());
1185        }
1186
1187        /**
1188         * Returns a {@link Comparator} that compares lists. Shorter lists are
1189         * considered "smaller" than longer lists. If lists have the same length,
1190         * elements are compared using their compareTo methods until one is found that
1191         * is does not return 0 when compared to its counterpart. If list lengths are
1192         * equal and all elements return 0 on comparison, the returned
1193         * {@link Comparator} returns 0.
1194         */
1195        public static <L extends List<T>, T extends Comparable<T>> Comparator<L> getListComparator() {
1196                return getListComparator(T::compareTo);
1197        }
1198
1199        /**
1200         * Returns a {@link Comparator} that compares lists. Shorter lists are
1201         * considered "smaller" than longer lists. If lists have the same length,
1202         * elements are compared using the given elementComparator until one is found
1203         * that is does not return 0 when compared to its counterpart. If list lengths
1204         * are equal and all elements return 0 on comparison, the returned
1205         * {@link Comparator} returns 0.
1206         */
1207        public static <L extends List<T>, T> Comparator<L> getListComparator(Comparator<T> elementComparator) {
1208                return (o1, o2) -> {
1209                        if (o1.size() != o2.size()) {
1210                                return o1.size() - o2.size();
1211                        }
1212                        for (int i = 0; i < o1.size(); i++) {
1213                                int currentComparison = elementComparator.compare(o1.get(i), o2.get(i));
1214                                if (currentComparison != 0) {
1215                                        return currentComparison;
1216                                }
1217                        }
1218                        return 0;
1219                };
1220        }
1221
1222        /**
1223         * Returns a {@link Comparator} that compares {@link Pair}s of
1224         * {@link Comparable}s. First compares the first elements and if their
1225         * comparison returns 0, compares the second elements. If their comparison also
1226         * return 0, this {@link Comparator} returns 0.
1227         */
1228        public static <P extends Pair<T, S>, T extends Comparable<T>, S extends Comparable<S>> Comparator<P> getPairComparator() {
1229                return (o1, o2) -> {
1230                        int firstComparison = o1.getFirst().compareTo(o2.getFirst());
1231                        if (firstComparison != 0) {
1232                                return firstComparison;
1233                        }
1234                        return o1.getSecond().compareTo(o2.getSecond());
1235                };
1236        }
1237
1238        /** Returns an empty {@link Consumer} that does nothing. */
1239        public static <T> Consumer<T> emptyConsumer() {
1240                return x -> {
1241                        // empty
1242                };
1243        }
1244
1245        /**
1246         * Splits a {@link String} representing a list of values to a list of lines and
1247         * forwards it to {@link CollectionUtils#parseMultiValueStringToList(List)}.
1248         */
1249        public static List<String> parseMultiValueStringToList(String valueList) {
1250                List<String> lines = StringUtils.splitWithEscapeCharacter(valueList, "\\n");
1251                return parseMultiValueStringToList(lines);
1252        }
1253
1254        /**
1255         * Parses a {@link List} of {@link String} representing lines of values to a
1256         * list of the single values. The value entries must be separated by
1257         * {@value #MULTI_VALUE_DELIMITER}.
1258         */
1259        public static List<String> parseMultiValueStringToList(List<String> valueListLines) {
1260                List<String> results = new ArrayList<>();
1261                for (String line : valueListLines) {
1262                        List<String> result = StringUtils.splitWithEscapeCharacter(line, MULTI_VALUE_DELIMITER);
1263                        for (String value : result) {
1264                                if (StringUtils.isEmpty(value)) {
1265                                        throw new IllegalArgumentException(
1266                                                        "Found duplicate comma (empty value) in list: " + valueListLines);
1267                                }
1268                        }
1269                        results.addAll(result);
1270                }
1271                return results;
1272        }
1273
1274        /**
1275         * Creates a {@link List} that holds the combination of the values of two
1276         * collections.
1277         *
1278         * @see #combine(Collection, Collection, Collection, BiFunction)
1279         */
1280        public static <T1, T2, RESULT> List<RESULT> combine(Collection<T1> firstValues, Collection<T2> secondValues,
1281                        BiFunction<T1, T2, RESULT> combineFunction) {
1282                List<RESULT> resultList = new ArrayList<>(firstValues.size());
1283                return combine(firstValues, secondValues, resultList, combineFunction);
1284        }
1285
1286        /**
1287         * Creates a {@link Collection} that holds the combination of the values of two
1288         * collections.
1289         *
1290         * Both collections must be of the same size. The order of insertion into the
1291         * new {@link Collection} is determined by the order imposed by the collections'
1292         * iterators.
1293         */
1294        public static <T1, T2, RESULT, COLLECTION extends Collection<RESULT>> COLLECTION combine(Collection<T1> firstValues,
1295                        Collection<T2> secondValues, COLLECTION resultCollection, BiFunction<T1, T2, RESULT> combineFunction) {
1296                CCSMAssert.isTrue(firstValues.size() == secondValues.size(), "Can only combine collections of the same size.");
1297                Iterator<T1> firstIterator = firstValues.iterator();
1298                Iterator<T2> secondIterator = secondValues.iterator();
1299                while (firstIterator.hasNext()) {
1300                        resultCollection.add(combineFunction.apply(firstIterator.next(), secondIterator.next()));
1301                }
1302                return resultCollection;
1303        }
1304
1305        /**
1306         * Applies the function to the values of both collections at the same index.
1307         *
1308         * Both collections must be of the same size.
1309         */
1310        public static <T1, T2> void forEach(Collection<T1> firstValues, Collection<T2> secondValues,
1311                        BiConsumer<T1, T2> combineFunction) {
1312                CCSMAssert.isTrue(firstValues.size() == secondValues.size(), "Can only combine collections of the same size.");
1313                Iterator<T1> firstIterator = firstValues.iterator();
1314                Iterator<T2> secondIterator = secondValues.iterator();
1315                while (firstIterator.hasNext()) {
1316                        combineFunction.accept(firstIterator.next(), secondIterator.next());
1317                }
1318        }
1319
1320        /**
1321         * Applies the function to the values of both collections at the same index.
1322         *
1323         * Both collections must be of the same size.
1324         */
1325        public static <T1, T2, E extends Exception> void forEachWithException(Collection<T1> firstValues,
1326                        Collection<T2> secondValues, BiConsumerWithException<? super T1, ? super T2, E> combineFunction) throws E {
1327                CCSMAssert.isTrue(firstValues.size() == secondValues.size(), "Can only combine collections of the same size.");
1328                Iterator<T1> firstIterator = firstValues.iterator();
1329                Iterator<T2> secondIterator = secondValues.iterator();
1330                while (firstIterator.hasNext()) {
1331                        combineFunction.accept(firstIterator.next(), secondIterator.next());
1332                }
1333        }
1334
1335        /**
1336         * Returns the element index of the first element in the list that matches the
1337         * given predicate. Returns -1 if no element matches the predicate.
1338         */
1339        public static <T> int indexOfFirstMatch(List<T> list, Predicate<T> predicate) {
1340                int listSize = list.size();
1341                for (int i = 0; i < listSize; i++) {
1342                        if (predicate.test(list.get(i))) {
1343                                return i;
1344                        }
1345                }
1346                return -1;
1347        }
1348
1349        /**
1350         * Returns a map that maps each element of the first list to the corresponding
1351         * (by index) element of the second list. The lists must have the same size.
1352         */
1353        public static <K, V> Map<K, V> zipAsMap(List<K> first, List<V> second) {
1354                CCSMAssert.isTrue(first.size() == second.size(),
1355                                "Need the same number of elements in the given lists. Found " + first.size() + " / " + second.size());
1356                Map<K, V> resultMap = new HashMap<>();
1357                for (int i = 0; i < first.size(); i++) {
1358                        resultMap.put(first.get(i), second.get(i));
1359                }
1360                return resultMap;
1361        }
1362
1363        /**
1364         * Wrapper for {@link List#subList(int, int)} with only a from parameter.
1365         *
1366         * Returns a view of the portion of this list between the specified
1367         * <tt>fromIndex</tt>, inclusive, and the end of the list. The returned list is
1368         * backed by this list, so non-structural changes in the returned list are
1369         * reflected in this list, and vice-versa.
1370         *
1371         * @param fromIndex
1372         *            low endpoint (inclusive) of the subList
1373         * @return a view of the specified range within this list
1374         * @throws IndexOutOfBoundsException
1375         *             for an illegal endpoint index value
1376         *             (<tt>fromIndex &lt; 0 || fromIndex &gt; size</tt>)
1377         */
1378        public static <T> List<T> subListFrom(List<T> list, int fromIndex) {
1379                return list.subList(fromIndex, list.size());
1380        }
1381
1382        /**
1383         * Returns an {@link ArrayList} filled with the given count of objects created
1384         * by the factory function. The current count is passed to the factory funciton.
1385         */
1386        public static <T> ArrayList<T> repeat(Function<Integer, T> factory, int count) {
1387                CCSMAssert.isFalse(count < 0,
1388                                () -> "Repeating objects for negative number " + count + " of objects is not possible.");
1389                ArrayList<T> result = new ArrayList<>(count);
1390
1391                for (int i = 0; i < count; i++) {
1392                        result.add(factory.apply(count));
1393                }
1394
1395                return result;
1396        }
1397}