org.opencastproject.util.data.Collections Maven / Gradle / Ivy
/*
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License
* at:
*
* http://opensource.org/licenses/ecl2.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package org.opencastproject.util.data;
import static org.opencastproject.util.data.Option.some;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* This class provides functions to ease and secure the handling of collections by supporting a type safe -- at least to
* the extent Java's type system allows -- immutable and more functional style.
*
* Note that all functions do not mutate input collections unless otherwise stated.
*
* @deprecated By now, all of this is natively available in Java.
*/
@Deprecated
public final class Collections {
private Collections() {
}
// TODO check all clients of this method since it potentially breaks!
@SuppressWarnings("unchecked")
private static Collection buildFrom(Collection as) {
try {
return as.getClass().newInstance();
} catch (Exception e) {
throw new IllegalArgumentException("Type " + as.getClass() + " needs a parameterless constructor");
}
}
/**
* Apply a function f
to all elements of collection as
to produce a new collection
* bs
.
*
* An (empty) instance of the target collection has to be provided explicitly.
*
* @param as
* the source collection
* @param bs
* the (empty) target collection
* @param f
* the function to apply to each element of as
* @deprecated use {@link Monadics}
*/
@Deprecated
public static > M map(Collection as, M bs, Function f) {
for (A x : as) {
bs.add(f.apply(x));
}
return bs;
}
/**
* Apply a function f
to all elements of collection as
to produce a new collection
* bs
.
*
* The type of collection as
needs a parameterless constructor.
*
* Please note that since java does not support higher-order polymorphism -- which is needed to capture the type of
* the collection -- some casting on the client side may still be necessary.
*
* @throws RuntimeException
* if the target collection cannot be created
* @deprecated use {@link Monadics}
*/
@Deprecated
public static Collection map(Collection as, Function f) {
Collection b = buildFrom(as);
for (A x : as) {
b.add(f.apply(x));
}
return b;
}
/**
* Return a new collection containing only the elements that satisfy predicate p
.
*
* The type of collection as
needs a parameterless constructor.
*
* @deprecated use {@link Monadics}
*/
@Deprecated
public static > M filter(M as, Predicate p) {
@SuppressWarnings("unchecked")
final M filtered = (M) buildFrom(as);
for (A a : as) {
if (p.apply(a))
filtered.add(a);
}
return filtered;
}
/** Return the head of list as
or none
. */
public static Option head(List as) {
if (!as.isEmpty()) {
return some(as.get(0));
} else {
return Option.none();
}
}
/** Make a string from a collection separating each element by sep
. */
public static String mkString(Collection> as, String sep) {
final StringBuilder b = new StringBuilder();
for (Object a : as)
b.append(a).append(sep);
return b.substring(0, Math.max(b.length() - sep.length(), 0));
}
/** Append source collection as
to target
. */
public static , S extends Iterable extends A>> T appendTo(T target, S as) {
for (A a : as)
target.add(a);
return target;
}
/** Append source collections as
to target
. */
@SafeVarargs
public static , S extends Iterable extends A>> T appendToM(T target, S... as) {
for (S s : as) {
for (A a : s)
target.add(a);
}
return target;
}
/** Append source collections as
to target
. */
@SafeVarargs
public static , X extends A> T appendToA(T target, X... as) {
java.util.Collections.addAll(target, as);
return target;
}
/** Concatenates two iterables into a new list. */
public static > List concat(M as, M bs) {
List x = new ArrayList<>();
for (A a : as)
x.add(a);
for (A b : bs)
x.add(b);
return x;
}
/**
* Merge two maps where b
takes precedence.
*
* @return a new immutable map
*/
public static Map merge(Map extends A, ? extends B> a, Map extends A, ? extends B> b) {
final Map x = new HashMap<>();
x.putAll(a);
x.putAll(b);
return java.util.Collections.unmodifiableMap(x);
}
/** Drain all elements of as
into a list. */
public static List toList(Iterator extends A> as) {
final List t = new ArrayList<>();
while (as.hasNext()) {
t.add(as.next());
}
return t;
}
/** Drain all elements of as
into a list. */
public static List toList(Collection as) {
return new ArrayList<>(as);
}
/**
* Return the list as is or nil, if as
is null.
*
* @deprecated use {@link #nullToNil(java.util.List)}
*/
@Deprecated
public static List mkList(List as) {
return as != null ? as : Collections. nil();
}
/** Return the list as is or nil, if as
is null. */
public static List nullToNil(List as) {
return as != null ? as : Collections. nil();
}
/** Create a list from an array. */
@SafeVarargs
public static List list(A... as) {
final List t = new ArrayList<>();
java.util.Collections.addAll(t, as);
return t;
}
/** Create a list from an array. */
@SafeVarargs
public static List nonNullList(A... as) {
final List t = new ArrayList<>();
for (A a : as) {
if (null != a) {
t.add(a);
}
}
return t;
}
/** The empty list. */
@SuppressWarnings("unchecked")
public static List nil() {
return java.util.Collections.EMPTY_LIST;
}
/** The empty list. */
@SuppressWarnings("unchecked")
public static List nil(Class type) {
return java.util.Collections.EMPTY_LIST;
}
/** Construct a new list by prepending an element to a given list. */
public static List cons(A a, List extends A> as) {
final List target = new ArrayList<>(as.size() + 1);
target.add(a);
target.addAll(as);
return target;
}
/** Create a set from an array. */
@SafeVarargs
public static Set set(A... as) {
final Set t = new HashSet<>(as.length);
java.util.Collections.addAll(t, as);
return t;
}
/** Create a set from a list. */
public static Set toSet(List as) {
Set r = new HashSet<>(as.size());
for (A a : as)
r.add(a);
return r;
}
/** Create a map from a list of tuples (K, V). */
@SafeVarargs
public static Map map(Tuple extends K, ? extends V>... ts) {
final Map map = new HashMap<>(ts.length);
for (Tuple extends K, ? extends V> t : ts) {
map.put(t.getA(), t.getB());
}
return map;
}
/** Create a dictionary from a list of tuples (K, V). */
@SafeVarargs
public static Dictionary dict(Tuple extends K, ? extends V>... ts) {
final Dictionary dict = new Hashtable<>(ts.length);
for (Tuple extends K, ? extends V> t : ts) {
dict.put(t.getA(), t.getB());
}
return dict;
}
/** Create an array from a collection. */
@SuppressWarnings("unchecked")
public static A[] toArray(Class elemType, Collection a) {
return a.toArray((A[]) Array.newInstance(elemType, a.size()));
}
/** Convert a collection of {@link Double}s into an array of primitive type. */
public static double[] toDoubleArray(Collection as) {
final double[] target = new double[as.size()];
int i = 0;
for (Double a : as) {
target[i] = a;
i++;
}
return target;
}
/** Create an iterator form an array. */
@SafeVarargs
public static Iterator iterator(final A... as) {
return new Iterator() {
private int i = 0;
@Override
public boolean hasNext() {
return as.length > i;
}
@Override
public A next() {
if (i < as.length) {
return as[i++];
} else {
throw new NoSuchElementException();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/** Create an iterator that repeats a
for the said times. */
public static Iterator repeat(final X a, final int times) {
return new Iterator() {
private int count = times;
@Override
public boolean hasNext() {
return count > 0;
}
@Override
public A next() {
count--;
return a;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/** Join two iterators. */
public static Iterator join(final Iterator a, final Iterator b) {
return new Iterator() {
@Override
public boolean hasNext() {
return a.hasNext() || b.hasNext();
}
@Override
public A next() {
return a.hasNext() ? a.next() : b.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* Make an Iterator usable in a for comprehension like this:
*
*
* Iterator<A> as = ...
* for (A a : forc(as)) {
* ...
* }
*
*/
public static Iterable forc(final Iterator as) {
return new Iterable() {
@Override
public Iterator iterator() {
return as;
}
};
}
/** Concat (aka flatten) a collection of collections by concatenating them all. [[a]] -> [a] */
public static >> List concat(M as) {
final List target = new ArrayList<>(as.size());
for (Collection a : as) {
target.addAll(a);
}
return target;
}
}