Java tutorial
/***************************************************************************************** * *** BEGIN LICENSE BLOCK ***** * * Version: MPL 2.0 * * echocat Jomon, Copyright (c) 2012-2014 echocat * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * *** END LICENSE BLOCK ***** ****************************************************************************************/ package org.echocat.jomon.runtime; import com.google.common.base.Predicate; import org.apache.commons.collections15.MultiMap; import org.echocat.jomon.runtime.iterators.CloseableIterator; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.WillClose; import java.util.*; import static com.google.common.base.Predicates.equalTo; import static java.util.Collections.*; import static org.echocat.jomon.runtime.util.ResourceUtils.closeQuietlyIfAutoCloseable; public class CollectionUtils { /** * Returns a the given map enriched * with the mappings <code>a[0] => a[1], a[2] => a[3], ...</code>. * @param a the elements to construct a {@link Map} from. * @return a {@link Map} constructed of the specified elements. */ @Nonnull public static <K, V> Map<K, V> putAll(@Nonnull Map<K, V> original, @Nullable Object... a) { if (a != null) { final int length = a.length; if (length % 2 == 1) { throw new IllegalArgumentException("You must provide an even number of arguments."); } for (int i = 0; i < length; i += 2) { // noinspection unchecked original.put((K) a[i], (V) a[i + 1]); } } return original; } @Nonnull public static <K, V> Map<K, V> putAll(@Nonnull Map<K, V> original, @Nullable Map<K, V> other) { if (other != null) { original.putAll(other); } return original; } /** * Returns a {@link LinkedHashMap} * with the mappings <code>a[0] => a[1], a[2] => a[3], ...</code>. * @param a the elements to construct a {@link Map} from. * @return a {@link Map} constructed of the specified elements. */ @Nonnull public static <K, V> Map<K, V> asMap(@Nullable Object... a) { return putAll(new LinkedHashMap<K, V>(), a); } /** * Returns a the given map enriched * with the mappings <code>a[0] => a[1], a[2] => a[3], ...</code>. * @param a the elements to construct a {@link Map} from. * @return a immutable {@link Map} constructed of the specified elements. */ @Nonnull public static <K, V> Map<K, V> putAllAndMakeImmutable(@Nonnull Map<K, V> original, @Nullable Object... a) { return asImmutableMap(CollectionUtils.putAll(original, a)); } /** * Returns a {@link LinkedHashMap} * with the mappings <code>a[0] => a[1], a[2] => a[3], ...</code>. * @param a the elements to construct a {@link Map} from. * @return a immutable {@link Map} constructed of the specified elements. */ @Nonnull public static <K, V> Map<K, V> asImmutableMap(@Nullable Object... a) { return putAllAndMakeImmutable(new LinkedHashMap<K, V>(), a); } @Nonnull public static <K, V> Map<K, V> asImmutableMap(@Nullable Map<K, V> map) { return map != null ? unmodifiableMap(map) : Collections.<K, V>emptyMap(); } public static boolean isNotEmpty(@Nullable Collection<?> collection) { return collection != null && !collection.isEmpty(); } public static boolean isNotEmpty(@Nullable Iterable<?> iterable) { return iterable != null && isNotEmpty(iterable.iterator()); } public static boolean isNotEmpty(@Nullable Iterator<?> iterator) { return iterator != null && iterator.hasNext(); } public static boolean isNotEmpty(@Nullable Map<?, ?> map) { return map != null && !map.isEmpty(); } public static boolean isNotEmpty(@Nullable MultiMap<?, ?> map) { return map != null && !map.isEmpty(); } public static boolean isEmpty(@Nullable Collection<?> collection) { return collection == null || collection.isEmpty(); } public static boolean isEmpty(@Nullable Iterable<?> iterable) { return iterable == null || isEmpty(iterable.iterator()); } public static boolean isEmpty(@Nullable Iterator<?> iterator) { return iterator == null || !iterator.hasNext(); } public static boolean isEmpty(@Nullable Map<?, ?> map) { return map == null || map.isEmpty(); } public static boolean isEmpty(@Nullable MultiMap<?, ?> map) { return map == null || map.isEmpty(); } @Nonnull public static <T, C extends Collection<T>> C addAll(@Nonnull C to, @Nullable T... elements) { if (elements != null) { Collections.addAll(to, elements); } return to; } @Nonnull public static <T, C extends Collection<T>> C addAll(@Nonnull C to, @Nullable Iterable<T> elements) { if (elements != null) { try { addAll(to, elements.iterator()); } finally { closeQuietlyIfAutoCloseable(elements); } } return to; } @Nonnull public static <T, C extends Collection<T>> C addAll(@Nonnull C to, @Nullable Iterator<T> elements) { if (elements != null) { try { while (elements.hasNext()) { to.add(elements.next()); } } finally { closeQuietlyIfAutoCloseable(elements); } } return to; } /** * Returns a {@link Collection} containing the given <code>objects</code>, * returns an empty List, if <code>objects</code> is null. */ @Nonnull public static <T> Collection<T> asCollection(@Nullable T... objects) { return asList(objects); } /** * Returns an unmodifiable {@link Collection} containing the given <code>objects</code>, * returns an empty {@link Collection}, if <code>objects</code> is null. */ @Nonnull public static <T> Collection<T> asImmutableCollection(@Nullable T... objects) { return unmodifiableCollection(asCollection(objects)); } @Nonnull public static <T> Collection<T> addAllAndMakeImmutable(@Nonnull Collection<T> original, @Nullable T... objects) { return unmodifiableCollection(addAll(original, objects)); } @Nonnull public static <T> Collection<T> asCollection(@Nullable Iterator<T> iterator) { return asList(iterator); } @Nonnull public static <T> Collection<T> asImmutableCollection(@Nullable Iterator<T> iterator) { return unmodifiableCollection(asCollection(iterator)); } @Nonnull public static <T> Collection<T> addAllAndMakeImmutable(@Nonnull Collection<T> original, @Nullable Iterator<T> iterator) { return unmodifiableCollection(addAll(original, iterator)); } @Nonnull public static <T> Collection<T> asCollection(@Nullable Iterable<T> in) { final Collection<T> result; if (in instanceof Collection) { result = (Collection<T>) in; } else { result = asList(in); } return result; } @Nonnull public static <T> Collection<T> asImmutableCollection(@Nullable Iterable<T> in) { return unmodifiableCollection(asCollection(in)); } @Nonnull public static <T> Collection<T> addAllAndMakeImmutable(@Nonnull Collection<T> original, @Nullable Iterable<T> in) { return unmodifiableCollection(addAll(original, in)); } /** * Returns a {@link List} containing the given <code>objects</code>, * returns an empty List, if <code>objects</code> is null. */ @Nonnull public static <T> List<T> asList(@Nullable T... objects) { final List<T> result; if (objects == null) { result = new ArrayList<>(); } else { final int initialCapacity = Math.max(16, ((objects.length + 2) / 3) * 4); result = new ArrayList<>(initialCapacity); result.addAll(new ArrayWrapper<>(objects)); } return result; } /** * Returns an unmodifiable {@link List} containing the given <code>objects</code>, * returns an empty {@link List}, if <code>objects</code> is null. */ @Nonnull public static <T> List<T> asImmutableList(@Nullable T... objects) { return unmodifiableList(asList(objects)); } @Nonnull public static <T> List<T> addAllAndMakeImmutable(@Nonnull List<T> original, @Nullable T... objects) { return unmodifiableList(addAll(original, objects)); } @Nonnull public static <T> List<T> asList(@Nullable Iterator<T> iterator) { final List<T> result = new ArrayList<>(); try { if (iterator != null) { while (iterator.hasNext()) { result.add(iterator.next()); } } } finally { closeQuietlyIfAutoCloseable(iterator); } return result; } @Nonnull public static <T> List<T> asImmutableList(@Nullable Iterator<T> iterator) { return unmodifiableList(asList(iterator)); } @Nonnull public static <T> List<T> addAllAndMakeImmutable(@Nonnull List<T> original, @Nullable Iterator<T> iterator) { return unmodifiableList(addAll(original, iterator)); } @Nonnull public static <T> List<T> asList(@Nullable Iterable<T> in) { final List<T> result; if (in instanceof List) { result = (List<T>) in; } else if (in instanceof Collection) { result = new ArrayList<>((Collection<T>) in); } else { result = new ArrayList<>(); addAll(result, in); } return result; } @Nonnull public static <T> List<T> asImmutableList(@Nullable Iterable<T> in) { return unmodifiableList(asList(in)); } @Nonnull public static <T> List<T> addAllAndMakeImmutable(@Nonnull List<T> original, @Nullable Iterable<T> in) { return unmodifiableList(addAll(original, in)); } /** * Returns a {@link Set} containing the given <code>objects</code>, * returns an empty Set, if <code>objects</code> is null. */ @Nonnull public static <T> Set<T> asSet(@Nullable T... objects) { final Set<T> result; if (objects == null) { result = new LinkedHashSet<>(); } else { final int initialCapacity = Math.max(16, ((objects.length + 2) / 3) * 4); result = new LinkedHashSet<>(initialCapacity); result.addAll(new ArrayWrapper<>(objects)); } return result; } /** * Returns an unmodifiable {@link Set} containing the given <code>objects</code>, * returns an empty Set, if <code>objects</code> is null. */ @Nonnull public static <T> Set<T> asImmutableSet(@Nullable T... objects) { return addAllAndMakeImmutable(new HashSet<T>(), objects); } /** * Returns an unmodifiable {@link Set} containing the given <code>objects</code>. */ @Nonnull public static <T> Set<T> addAllAndMakeImmutable(@Nonnull Set<T> original, @Nullable T... objects) { return unmodifiableSet(addAll(original, objects)); } @Nonnull public static <T> Set<T> asSet(@Nullable Iterator<T> iterator) { return addAll(new LinkedHashSet<T>(), iterator); } @Nonnull public static <T> Set<T> asImmutableSet(@Nullable Iterator<T> iterator) { return unmodifiableSet(asSet(iterator)); } @Nonnull public static <T> Set<T> addAllAndMakeImmutable(@Nonnull Set<T> original, @Nullable Iterator<T> iterator) { return unmodifiableSet(addAll(original, iterator)); } @Nonnull public static <T> Set<T> asSet(@Nullable Iterable<T> in) { final Set<T> result; if (in instanceof Set) { result = (Set<T>) in; } else if (in instanceof Collection) { result = new LinkedHashSet<>((Collection<T>) in); } else { result = addAll(new LinkedHashSet<T>(), in); } return result; } @Nonnull public static <T> Set<T> asImmutableSet(@Nullable Iterable<T> in) { return unmodifiableSet(asSet(in)); } @Nonnull public static <T> Set<T> addAllAndMakeImmutable(@Nonnull Set<T> original, @Nullable Iterable<T> in) { return unmodifiableSet(addAll(original, in)); } @Nonnull public static <T> CloseableIterator<T> asSingletonIterator(@Nullable final T element) { return new CloseableIterator<T>() { private boolean _elementFetched; @Override public boolean hasNext() { return !_elementFetched; } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } _elementFetched = true; return element; } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public void close() { } }; } @Nonnull public static <T> CloseableIterator<T> asCloseableIterator(@Nullable final Iterator<T> iterator) { final CloseableIterator<T> result; if (iterator instanceof CloseableIterator) { result = (CloseableIterator<T>) iterator; } else if (iterator != null) { result = new CloseableIterator<T>() { @Override public void close() { } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public T next() { return iterator.next(); } @Override public void remove() { iterator.remove(); } }; } else { result = emptyIterator(); } return result; } @SafeVarargs @Nonnull public static <T> CloseableIterator<T> asIterator(@Nullable T... elements) { final CloseableIterator<T> result; if (elements != null) { final int length = elements.length; if (length == 0) { result = emptyIterator(); } else if (length == 1) { result = asSingletonIterator(elements[0]); } else { result = asIterator(Arrays.asList(elements)); } } else { result = emptyIterator(); } return result; } @Nonnull public static <T> CloseableIterator<T> asIterator(@Nullable Iterable<T> elements) { final CloseableIterator<T> result; if (elements != null) { final Iterator<T> iterator = elements.iterator(); if (iterator.hasNext()) { result = asCloseableIterator(iterator); } else { result = emptyIterator(); } } else { result = emptyIterator(); } return result; } @Nonnull public static <T> CloseableIterator<T> emptyIterator() { return new CloseableIterator<T>() { @Override public boolean hasNext() { return false; } @Override public T next() { throw new NoSuchElementException(); } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public void close() { } }; } public static <T> boolean oneApplies(@Nullable @WillClose Iterable<T> elements, @Nullable T predicate) { return elements != null && oneApplies(elements, equalTo(predicate)); } public static <T> boolean oneApplies(@Nullable @WillClose Iterable<T> elements, @Nonnull Predicate<T> predicate) { return elements != null && oneApplies(elements.iterator(), predicate); } public static <T> boolean oneApplies(@Nullable @WillClose Iterable<T> elements, @Nullable final Collection<T> predicate) { return oneApplies(elements, new Predicate<T>() { @Override public boolean apply(@Nullable T input) { return predicate == null || predicate.contains(input); } }); } public static <T> boolean oneApplies(@Nullable @WillClose Iterator<T> elements, @Nonnull T predicate) { return elements != null && oneApplies(elements, equalTo(predicate)); } public static <T> boolean oneApplies(@Nullable @WillClose Iterator<T> elements, @Nonnull Predicate<T> predicate) { boolean result = false; if (elements != null) { try { while (elements.hasNext() && !result) { result = predicate.apply(elements.next()); } } finally { closeQuietlyIfAutoCloseable(elements); } } return result; } @Nonnegative public static <T> long countElementsOf(@Nullable Iterable<T> elements) { return countElementsOf(elements, null); } @Nonnegative public static <T> long countElementsOf(@Nullable Iterable<T> elements, @Nullable Predicate<T> matches) { return elements instanceof Collection && matches == null ? ((Collection) elements).size() : countElementsOf(elements.iterator(), matches); } @Nonnegative public static <T> long countElementsOf(@Nullable Iterator<T> iterator) { return countElementsOf(iterator, null); } @Nonnegative public static <T> long countElementsOf(@Nullable Iterator<T> iterator, @Nullable Predicate<T> matches) { long count = 0; try { if (iterator != null) { while (iterator.hasNext()) { final T what = iterator.next(); if (matches == null || matches.apply(what)) { count++; } } } } finally { closeQuietlyIfAutoCloseable(iterator); } return count; } @Nullable public static <T> T findFirstOf(@Nullable Iterable<T> elements) { return elements != null ? findFirstOf(elements.iterator()) : null; } @Nullable public static <T> T findFirstOf(@Nullable Iterator<T> iterator) { T firstElement = null; try { if (iterator != null && iterator.hasNext()) { firstElement = iterator.next(); } } finally { closeQuietlyIfAutoCloseable(iterator); } return firstElement; } @Nonnegative public static <T> long removeAllOf(@Nullable Iterable<T> elements) { return removeAllOf(elements, null); } @Nonnegative public static <T> long removeAllOf(@Nullable Iterable<T> elements, @Nullable Predicate<T> matching) { return removeAllOf(elements.iterator(), matching); } @Nonnegative public static <T> long removeAllOf(@Nullable Iterator<T> iterator) { return removeAllOf(iterator, null); } @Nonnegative public static <T> long removeAllOf(@Nullable Iterator<T> iterator, @Nullable Predicate<T> matching) { long removed = 0; try { if (iterator != null) { while (iterator.hasNext()) { final T what = iterator.next(); if (matching == null || matching.apply(what)) { iterator.remove(); removed++; } } } } finally { closeQuietlyIfAutoCloseable(iterator); } return removed; } /** * This class is similar to the class which is returned by {@link Arrays#asList} * but does not clone the wrapped array if {@link #toArray} is called. */ private static class ArrayWrapper<E> extends AbstractList<E> { private final E[] _wrappedArray; private ArrayWrapper(E[] arrayToWrap) { _wrappedArray = arrayToWrap; } @Override public E get(int index) { return _wrappedArray[index]; } @Override public int size() { return _wrappedArray.length; } /** * Returns the wrapped array. */ @Override public Object[] toArray() { return _wrappedArray; } } private CollectionUtils() { } }