/* * Copyright (c) 2013, SRI International * All rights reserved. * Licensed under the The BSD 3-Clause 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/BSD-3-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the aic-util nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.sri.ai.util; import static com.sri.ai.util.base.PairOf.makePairOf; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.Reader; import java.io.StringWriter; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Optional; import java.util.Random; import java.util.Set; import java.util.Stack; import java.util.StringJoiner; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collector; import java.util.stream.Collectors; import com.google.common.annotations.Beta; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.sri.ai.util.base.BinaryFunction; import com.sri.ai.util.base.BinaryPredicate; import com.sri.ai.util.base.Equals; import com.sri.ai.util.base.NullaryFunction; import com.sri.ai.util.base.Pair; import com.sri.ai.util.base.PairOf; import com.sri.ai.util.base.TernaryFunction; import com.sri.ai.util.collect.EZIterator; import com.sri.ai.util.math.Rational; /** * A suite of general purpose utility routines related to handling errors, * string manipulation, I/O, collections, and math that have proven useful over * time. * * @author braz * */ @Beta public class Util { /** * Logs the error message and stack trace for the given exception, and exits * the program, returning code 1. * * @param e * the throwable causing the fatal error. */ public static void fatalError(Throwable e) { fatalError(e, true); } /** * Logs a top level message, the error message and stack trace for the given * exception, and exits the program, returning code 1. * * @param topLevelMessage * the top level message describing the fatal error. * @param e * the throwable causing the fatal error. */ public static void fatalError(String topLevelMessage, Throwable e) { fatalError(topLevelMessage, e, true); } /** * Logs the error message for the given exception, and optionally logs a * stack trace. Then exits the program with return code 1. * * @param e * the throwable causing the fatal error. * @param trace * indicates whether or not to log the stack trace. */ public static void fatalError(Throwable e, boolean trace) { fatalError("Fatal error: ", e, trace); } /** * Logs error message and exits. * * @param msg * the error message * */ public static void fatalError(String msg) { fatalError(msg, true); } /** * Logs error message without loging stack trace, and exits. * * @param msg * the error message */ public static void fatalErrorWithoutStack(String msg) { fatalError(msg, false); } /** * Logs a top level message, the error message for the given exception, and * optionally logs a stack trace. Then exits the program with return code 1. * * @param topLevelMessage * the top level message describing the fatal error. * @param e * the throwable causing the fatal error. * @param trace * indicates whether or not to log the stack trace. */ public static void fatalError(String topLevelMessage, Throwable e, boolean trace) { if (trace) { if (e.getCause() != null) { System.err.println(topLevelMessage + "\n" + e.getMessage() + "\n" + join("\n", e.getStackTrace()) + "\n" + e.getCause().getMessage() + "\n" + join("\n", e.getCause().getStackTrace())); } else { System.err.println(topLevelMessage + "\n" + e.getMessage()); } } else { System.err.println(topLevelMessage + "\n" + e.getMessage()); } if (e != null) { e.printStackTrace(); } System.exit(1); } /** * Logs error message, optionally logs stack trace, and exits. * * @param msg * the error message * * @param trace * if true, log a stack trace */ public static void fatalError(String msg, boolean trace) { if (trace) { System.err.println(msg + "\n" + join("\n", Thread.currentThread().getStackTrace())); } else { System.err.println(msg); } System.exit(1); } /** * Returns a string with the entire context of an input stream. * * @param inputStream * the input stream from which to read all from. * @return a String representation of the entire contents of the given input * stream. */ public static String readAll(InputStream inputStream) { StringBuilder result = new StringBuilder(); String line; boolean first = true; try { BufferedReader reader = new BufferedReader(new InputStreamReader( inputStream)); while ((line = reader.readLine()) != null) { if (!first) { result.append("\n"); } result.append(line); first = false; } return result.toString(); } catch (Exception e) { Util.fatalError("Could not read " + inputStream, e); } return null; } /** * Returns a string with the entire contents of an input reader. * * @param inputReader * the input reader to be read from. * @return all of the contents read from the input reader. * @throws IOException if an error occurs. */ public static String readAll(Reader inputReader) throws IOException { StringWriter result = new StringWriter(); char[] cbuf = new char[1024]; int read = 0; while ((read = inputReader.read(cbuf)) != -1) { result.write(cbuf, 0, read); } return result.toString(); } /** * Returns the string formed by concatenating the two given strings, with a * space in between if both strings are non-empty. * * @param str1 * the first string to join. * @param str2 * the second string to join. * @return a concatenated version of str1 and str2 with a space in between. */ public static String join(String str1, String str2) { if (str1.length() == 0) { return str2; } if (str2.length() == 0) { return str1; } StringJoiner sj = new StringJoiner(" "); sj.add(str1).add(str2); return sj.toString(); } /** * Returns a string formed by the concatenation of string versions of the * elements in a collection, separated by a given separator. * * @param separator * the separator to use between elements when creating the joined * string. * @param c * the collection whose elements toString() values are to be * joined together. * @return a String constructed from the toString of each element of the * given collection with the given separator between each argument. */ public static String join(String separator, Collection c) { Iterator it = c.iterator(); return join(separator, it); } /** * Returns a string formed by the concatenation of string versions of the * elements in an iterator's range, separated by a given separator. * * @param separator * the separator to use between elements when creating the joined * string. * @param it * the iterator whose elements toString() values are to be joined * together. * @return a String constructed from the toString of each element of the * given iterator with the given separator between each argument. */ @SuppressWarnings("unchecked") public static String join(String separator, Iterator it) { StringJoiner sj = new StringJoiner(separator); it.forEachRemaining(e -> sj.add(e == null? "null" : e.toString())); return sj.toString(); } /** * Same as {@link #join(String, Iterator)}, with <code>", "</code> for a * separator. * * @param it * the iterator whose elements toString() values are to be joined * together. * @return a String constructed from the toString of each element of the * given iterator with a comma (<code>", "</code>) separator between * each argument. */ public static String join(Iterator it) { return join(", ", it); } /** * Same as {@link #join(String, Collection)}. * * @param c * the collection whose elements toString() values are to be * joined together. * @param separator * the separator to use between elements when creating the joined * string. * @return a String constructed from the toString of each element of the * given collection with the given separator between each argument. */ public static String join(Collection c, String separator) { return join(separator, c); } /** * Calls {@link #join(String, Collection)} with ", " as separator. * * @param c * the collection whose elements toString() values are to be * joined together. * @return a String constructed from the toString of each element of the * given collection with a comma (<code>", "</code>) separator * between each argument. */ public static String join(Collection c) { return join(", ", c); } /** * Calls {@link #join(Collection)} on the given array as a collection. * * @param a * the array whose elements toString() values are to be joined * together. * @return a String constructed from the toString of each element of the * given array with a comma (<code>", "</code>) separator between * each argument. */ public static String join(Object[] a) { return join(Arrays.asList(a)); } /** * Calls {@link #join(String, Collection)} on the given array as a * collection. * * @param separator * the separator to use between elements when creating the joined * string. * @param a * the array whose elements toString() values are to be joined * together. * @return a String constructed from the toString of each element of the * given array with the given separator between each argument. */ public static String join(String separator, Object[] a) { return join(separator, Arrays.asList(a)); } /** * Produces a string with map entry representations separated by a given * entry separator, where entry representations are the key and value * representations separated by a key-value separator. * * @param entrySeparator * the separator to use between each map entry in the join * output. * @param keyValueSeparator * the separator to use between each entry's key value pair in * the join output. * @param map * the map whose key value pairs are to be joined into a String. * @return a joined string with an entrySeparator between each entry in the * given map, each of which has a keyValueSeparator between the * entry's key and value. */ public static String join(String entrySeparator, String keyValueSeparator, Map<? extends Object, ? extends Object> map) { List<Object> c = new LinkedList<Object>(); for (Map.Entry<? extends Object, ? extends Object> entry : map .entrySet()) { c.add(entry.getKey() + keyValueSeparator + entry.getValue()); } return join(entrySeparator, c); } /** * Same as {@link #join(String, String, Map)} with key-value separator equal * to -> . * * @param entrySeparator * the separator to use between each map entry in the join * output. * @param map * the map whose key value pairs are to be joined into a String. * @return a joined string with an entrySeparator between each entry in the * given map, each of which has an arrow -> separator between the * entry's key and value. */ public static String join(String entrySeparator, Map<? extends Object, ? extends Object> map) { return join(entrySeparator, " -> ", map); } /** * Same as {@link #join(String, String, Map)} with entry separator equal to * <code>", "</code> and key-value separator equal to ->. * * @param map * the map whose key value pairs are to be joined into a String. * @return a joined string with a <code>", "</code> comma separator between * each entry in the given map, each of which has an arrow -> * separator between the entry's key and value. */ public static String join(Map<? extends Object, ? extends Object> map) { return join(", ", " -> ", map); } public static List<String> split(String separator, String string) { if (separator.length() == 0) { throw new Error("Util.split cannot run on empty separator."); } List<String> result = new LinkedList<String>(); int begin = 0; int end; while (begin <= string.length()) { end = string.indexOf(separator, begin); if (end == -1) { end = string.length(); } result.add(string.substring(begin, end)); begin = end + separator.length(); } return result; } /** * Construct an Object array of the given elements. * * @param elements * the elements to construct an array from. * @return the received arguments in an array. * */ public static Object[] array(Object... elements) { return elements; } /** * Construct a list of the given type populated with the provided elements. * * @param elements * the elements to construct the List from. * @return the received arguments in a linked list. * @param <T> * the type of the elements in the list. */ @SafeVarargs public static <T> LinkedList<T> list(T... elements) { return new LinkedList<T>(Arrays.asList(elements)); } /** * Construct an iterator of the given type ranging over provided elements. * * @param elements * the elements to construct the List from. * @return an iterator over the received arguments. * @param <T> * the type of elements the iterator will range over. */ public static <T> Iterator<T> iterator(T... elements) { return Arrays.asList(elements).iterator(); } /** * Construct an {@link ArrayList} of the given type populated with the provided elements. * * @param elements * the elements to construct the List from. * @return the received arguments in an array list. * @param <T> * the type of the List to be constructed and the elements it is * to contain. */ @SafeVarargs public static <T> ArrayList<T> arrayList(T... elements) { return new ArrayList<T>(Arrays.asList(elements)); } /** * @return an empty stack of the given type. * @param <T> * the type of the Stack to instantiate. */ public static <T> Stack<T> stack() { Stack<T> result = new Stack<T>(); return result; } public static <T> LinkedHashSet<T> set(T... elements) { return new LinkedHashSet<T>(Arrays.asList(elements)); } @SuppressWarnings("unchecked") public static <T> List<T> singletonListIfNotNullOrEmptyListIfNull(T element) { if (element == null) { return new LinkedList<T>(); } else { return list(element); } } public static boolean isEven(int number) { return number % 2 == 0; } /** * * @param keysAndValues * a sequence of key and value pairs to be placed into a new Map. * * @return the received arguments (interpreted as a sequence of key and * value pairs) in a hash map. * @param <K> * the type of the Map's key. * @param <V> * the type of the Map's value. */ public static <K, V> LinkedHashMap<K, V> map(Object... keysAndValues) { if (!isEven(keysAndValues.length)) { fatalError("Util.map(Object ...) must receive an even number of arguments but received " + keysAndValues.length + ": " + join(";", keysAndValues) + "."); } LinkedHashMap<K, V> result = new LinkedHashMap<K, V>(); putAll(result, keysAndValues); return result; } /** * @param map * a map. * @param keysAndValues * a sequence of key and value pairs to be placed into a given Map. * * @return the received arguments (interpreted as a sequence of key and * value pairs) in a given map. * @param <K> * the type of the Map's key. * @param <V> * the type of the Map's value. */ @SuppressWarnings("unchecked") public static <K, V> Map<K, V> putAll(Map<K, V> map, Object... keysAndValues) { int i = 0; while (i != keysAndValues.length) { map.put((K) keysAndValues[i], (V) keysAndValues[i + 1]); i += 2; } return map; } /** * Add given element of a given collection to a collection value in a map, * creating it in advance (as an instance of given class) if needed. * * @param mapToCollections * the map containing the collections to be added to. * @param key * the key identifying the collection in the given map to be * added to. * @param element * the element to be added to the identified collection. * @param newCollectionClass * the class of the collection to create if it is not currently * mapped to in the given map. * @param <K> * the type of the Map's key. * @param <V> * the type of the Map's value. */ @SuppressWarnings("unchecked") public static <K, V, C extends Collection<V>> void addToCollectionValuePossiblyCreatingIt( Map<K, C> mapToCollections, K key, V element, Class newCollectionClass) { C c = mapToCollections.get(key); if (c == null) { try { c = (C) newCollectionClass.newInstance(); mapToCollections.put(key, c); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } c.add(element); } /** * Add all elements of a given collection to a collection value in a map, * creating it in advance (as an instance of given class) if needed. * * @param mapToCollections * the map containing the collections to be added to. * @param key * the key identifying the collection in the given map to be * added to. * @param elements * the elements to be added to the identified collection. * @param newCollectionClass * the class of the collection to create if it is not currently * mapped to in the given map. */ @SuppressWarnings("unchecked") public static void addAllToCollectionValuePossiblyCreatingIt( Map mapToCollections, Object key, Collection elements, Class newCollectionClass) { Collection c = (Collection) mapToCollections.get(key); if (c == null) { try { c = (Collection) newCollectionClass.newInstance(); mapToCollections.put(key, c); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } c.addAll(elements); } /** * Given two maps of collections, add all elements in each collection2 of second map * to the corresponding (that is, associated with the same key) collection1 in first map, * guaranteeing to keep collection2's instance if collection1 is absent or empty, * and returns the first map, unless it is null, in which case the second map is returned. * * @param map1 * map 1 * @param map2 * map 2 * @return the first map, unless it is null, in which case the second map is returned * @param <M> a map type * @param <V> a value type * @param <K> a key type */ public static <M extends Map<K, Collection<V>>, K, V> M addAllForEachEntry(M map1, M map2) { M result; if (map1 == null) { result = map2; } else { for (Map.Entry<K,Collection<V>> entry : map2.entrySet()) { Collection<V> collectionInMap1 = map1.get(entry.getKey()); Collection<V> collectionInMap2 = entry.getValue(); Collection<V> entryUnion = addAllOrSame(collectionInMap1, collectionInMap2); if (entryUnion != collectionInMap1) { map1.put(entry.getKey(), entryUnion); } } result = map1; } return result; } /** * Adds to a collection all given new elements in a second collection, returning the second collection * same instance if the first is null or empty. * @param collection * a collection * @param newElements * new elements * @return if collection null then newElements, else collection with newElements added to it. * @param <T> the type of the elements in the collection. */ public static <T> Collection<T> addAllOrSame(Collection<T> collection, Collection<T> newElements) { Collection<T> result; if (collection == null || collection.isEmpty()) { result = newElements; } else { collection.addAll(newElements); result = collection; } return result; } /** * Given a map, a function on its entries, and a value combination function, * returns a pair of: * <ul> * <li> a new map containing the transformed entries; * if multiple entries have their keys transformed to the same new key, * their values will be combined with the value combination function. * <li> a set of keys of the original entries that were transformed; * an entry is considered transformed if the returned pair is not null, * and if either its key or value identities (instances) have changed * </ul> * The function receives an entry from the original map as its input and returns * a {@link Pair} with new key and new value as output. * * @param map * a map * @param function * a function * @param valueCombination * a value combination * @return a pair with values as described in description. * @param <K1> type of key 1 * @param <V1> type of value 1 * @param <K2> type of key 2 * @param <V2> type of value 2 */ public static <K1, V1, K2, V2> Pair<Map<K2,V2>, Set<K1>> getTransformedSubMapAndOriginalKeysOfTransformedEntries( Map<K1, V1> map, Function<Map.Entry<K1, V1>, Pair<K2, V2>> function, BinaryFunction<V2, V2, V2> valueCombination) { Map<K2, V2> transformedSubMap = new LinkedHashMap<K2, V2>(); Set<K1> originalKeysOfTransformedEntries = new LinkedHashSet<K1>(); for (Map.Entry<K1, V1> entry : map.entrySet()) { Pair<K2, V2> transformedEntry = function.apply(entry); if (transformedEntry != null && (transformedEntry.first != entry.getKey() || transformedEntry.second != entry.getValue())) { V2 newValue = transformedEntry.second; V2 alreadyPresentValueForNewKey = transformedSubMap.get(transformedEntry.first); if (alreadyPresentValueForNewKey == null) { newValue = transformedEntry.second; } else { newValue = valueCombination.apply(alreadyPresentValueForNewKey, transformedEntry.second); } transformedSubMap.put(transformedEntry.first, newValue); originalKeysOfTransformedEntries.add(entry.getKey()); } } return Pair.make(transformedSubMap, originalKeysOfTransformedEntries); } /** * Adds all elements of iterator's range to collection. * * @param c * the collection to add the iterator's range to. * @param i * the iterator whose range is to be added to the given * collection. * @return the given collection. * @param <T> * the type of the elements given. * @param <C> the type of the collection */ public static <T, C extends Collection<T>> C addAll(C c, Iterator<T> i) { while (i.hasNext()) { c.add(i.next()); } return c; } /** * Adds all elements of iterator's range to a new linked list. * * @param i * the iterator whose range is to be added to the list. * @return the list. * @param <T> * the type of the elements given. */ public static <T> LinkedList<T> addAllToList(Iterator<T> i) { LinkedList<T> result = new LinkedList<T>(); while (i.hasNext()) { result.add(i.next()); } return result; } /** * Adds all elements of iterator's range to a new array list. * * @param i * the iterator whose range is to be added to the list. * @return the list. * @param <T> * the type of the elements given. */ public static <T> ArrayList<T> addAllToArrayList(Iterator<T> i) { ArrayList<T> result = new ArrayList<T>(); while (i.hasNext()) { result.add(i.next()); } return result; } /** * Adds all elements of iterator's range to a new linked hash set. * * @param i * the iterator whose range is to be added to the set. * @return the set. * @param <T> * the type of the elements given. */ public static <T> LinkedHashSet<T> addAllToSet(Iterator<T> i) { LinkedHashSet<T> result = new LinkedHashSet<T>(); while (i.hasNext()) { result.add(i.next()); } return result; } /** * @param map * the map to look up a value using the given key. * @param key * the key to look up the given map with. * @param defaultValue * the defaultValue to return if the given key is not in the map. * @return value indexed by given key in map, or a default value if that is * null. * @param <K> * the type of the Map's key. * @param <V> * the type of the Map's value. */ public static <K, V> V getOrUseDefault(Map<K, V> map, K key, V defaultValue) { V result = map.get(key); if (result == null) { result = defaultValue; } return result; } /** * @param map * the map to look up a value using the given key. * @param key * the key to look up the given map with. * @param defaultMaker * a function to make a default object from. * @return value indexed by given key in map, or a default value made by the default maker. * @param <K> * the type of the Map's key. * @param <V> * the type of the Map's value. */ public static <K, V> V getOrMakeAndPut(Map<K, V> map, K key, NullaryFunction<V> defaultMaker) { V result = map.get(key); if (result == null) { result = defaultMaker.apply(); map.put(key, result); } return result; } @SuppressWarnings("unchecked") public static <K, V> V getValuePossiblyCreatingIt(Map<K, V> map, K key, Class<?> newValueClass) { V value = map.get(key); if (value == null) { try { value = (V) newValueClass.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); System.exit(-1); } catch (IllegalAccessException e) { e.printStackTrace(); System.exit(-1); } map.put(key, value); } return value; } public static <K, V> V getValuePossiblyCreatingIt(Map<K, V> map, K key, Function<K, V> makerFromKey) { V value = map.get(key); if (value == null) { value = makerFromKey.apply(key); map.put(key, value); } return value; } public static File createTempFileWithContent(String content, String pattern, String suffix) { File temp = null; try { // Create temp file. temp = File.createTempFile(pattern, "." + suffix); // Delete temp file when program exits. temp.deleteOnExit(); // Write to temp file BufferedWriter out = new BufferedWriter(new FileWriter(temp)); out.write(content); out.close(); } catch (IOException e) { Util.fatalError("Could not create temporary file."); } return temp; } public static <T1> boolean isEmpty(Iterable<T1> i) { return !i.iterator().hasNext(); } /** * * @param element * the element to test. * @param iterable * An iterable object. * @param predicate * the predicate to test if the given element has found a match * in the iterable object. * @return an Iterator that has just iterated past an element <code>x</code> * of <code>iterable</code> such that * <code>predicate.evaluate(element, x)</code> is true, or * <code>null</code> if there is no such element. * @param <E> * the type of the element to find. */ public static <E> Iterator<E> find(E element, Iterable<E> iterable, BinaryPredicate<E, E> predicate) { Iterator<E> i = iterable.iterator(); boolean foundIt = false; while (i.hasNext() && !(foundIt = predicate.apply(element, i.next()))) { ; } if (foundIt) { return i; } return null; } public static <E> boolean removeAnyTwoMatchingElements(Iterable<E> a, Iterable<E> b, BinaryPredicate<E, E> predicate) { Iterator<E> aI = a.iterator(); Iterator<E> bI = null; while (aI.hasNext() && (bI = find(aI.next(), b, predicate)) != null) { ; } if (bI != null) { aI.remove(); bI.remove(); return true; } return false; } /** * If there is no element in collection satisfying given predicate, returns * null. Otherwise, returns list with elements in iteration order, excluding * the first satisfying element. * * @param c * the collection to copy elements from. * @param p * the predicate to test elements on the given collection for * whether or not they should be copied or not. * @return null if no element in given collection satisfying given * predicate, otherwise a list with elements in iteration order, * excluding the first element satisfying the predicate. * @param <T> * the type of the elements in the collection. */ public static <T> List<T> listCopyWithoutSatisfyingElementOrNull( Collection<T> c, Predicate<T> p) { Pair<T, List<T>> satisfyingElementAndListCopyWithoutIt = findSatisfyingElementAndListCopyWithoutItOrNull( c, p); return satisfyingElementAndListCopyWithoutIt.second; } /** * If there is no element in collection satisfying given predicate, returns * null. Otherwise, returns pair with found element and a list with elements * in iteration order, excluding the first satisfying element. * * @param c * the collection to copy elements from. * @param p * the predicate to test elements on the given collection for * whether or not they should be copied or not. * @return null if no element in given collection satisfying given * predicate, otherwise a pair with found element and a list with * elements in iteration order, excluding the first satisfying * element. * @param <T> * the type of the elements in the collection. */ public static <T> Pair<T, List<T>> findSatisfyingElementAndListCopyWithoutItOrNull( Collection<T> c, Predicate<T> p) { Pair<T, List<T>> result = null; final AtomicInteger elementIndex = new AtomicInteger(-1); Optional<T> first = c.stream().filter(e -> { elementIndex.incrementAndGet(); return p.apply(e); }).findFirst(); if (first.isPresent()) { // we create another list and add all elements, but found one, to // it. List<T> copy = makeCopyButForElementAtGivenIndex(c, elementIndex.intValue()); result = Pair.make(first.get(), copy); } return result; } /** * Given a collection and an index, returns a list with the collection's * elements in iteration order, excluding the elementIndex-th element. * * @param c * the collection whose elements are to be copied. * @param elementIndex * the index of the element to be excluded from the copied * collection. * @return a list wit the collection's elements in iteration order, * excluding the elementIndex-th element. * @param <T> * the type of the elements in the collection. */ public static <T> List<T> makeCopyButForElementAtGivenIndex( Collection<T> c, int elementIndex) { final AtomicInteger currentIndex = new AtomicInteger(-1); List<T> result = c.stream() .filter(e -> currentIndex.incrementAndGet() != elementIndex) .collect(toLinkedList()); return result; } /** * Stores iterator's range in a new, empty list and returns it. * * @param iterator * the iterator whose range is to be stored in a new List. * @return a new List populated with the elements from the given iterator's * range. * @param <T> * the type of the elements iterated over. */ public static <T> List<T> listFrom(Iterator<T> iterator) { LinkedList<T> result = new LinkedList<T>(); while (iterator.hasNext()) { result.add(iterator.next()); } return result; } /** * Stores iterator's range in a new, empty array list and returns it. * * @param iterator * the iterator whose range is to be stored in a new ArrayList. * @return a new ArrayList populated with the elements from the given iterator's * range. * @param <T> * the type of the elements iterated over. */ public static <T> ArrayList<T> arrayListFrom(Iterator<T> iterator) { ArrayList<T> result = new ArrayList<T>(); while (iterator.hasNext()) { result.add(iterator.next()); } return result; } /** * Makes a list out of an array. * * @param array * the array from which to construct a list. * @return a List containing the elements of the given array. * @param <T> * the type of the array's elements. */ public static <T> List<T> listFrom(T[] array) { LinkedList<T> result = new LinkedList<T>(); for (int i = 0; i != array.length; i++) { result.add(array[i]); } return result; } /** * Stores results of applying a function to an iterator's range in a given list. * * @param iterator * the iterator's whose range a function is to be applied to. * @param function * the function to be applied to the given iterator's range. * @param result a list to which we add the results from the function applications on the given * iterator's range. * @param <F> * the type of the iterators arguments. * @param <T> * the result type of the function applied to the iterator's * range. */ protected static <F, T> void mapIntoList(Iterator<? extends F> iterator, Function<F, T> function, List<T> result) { while (iterator.hasNext()) { F nextElement = iterator.next(); result.add(function.apply(nextElement)); } } /** * Stores results of applying a function to the elements of a collection in a given list. * * @param collection * the collection to whose elements a function is to be applied to. * @param function * the function to be applied to the given iterator's range. * @param result a list to which we add the results from the function applications on the given * collection elements. * @param <F> * the type of the collection elements. * @param <T> * the result type of the function applied to the collection elements. */ public static <F, T> void mapIntoList(Collection<? extends F> collection, Function<F, T> function, List<T> result) { mapIntoList(collection.iterator(), function, result); } /** * Stores results of applying a function to an iterator's range in a new, * empty list and returns it. * * @param iterator * the iterator's whose range a function is to be applied to. * @param function * the function to be applied to the given iterator's range. * @return a List of the results from the function applications on the given * iterator's range. * @param <F> * the type of the iterators arguments. * @param <T> * the result type of the function applied to the iterator's * range. */ public static <F, T> List<T> mapIntoList(Iterator<? extends F> iterator, Function<F, T> function) { List<T> result = new LinkedList<T>(); mapIntoList(iterator, function, result); return result; } /** * Stores results of applying a function to a collection's elements in a * new, empty list and returns it. * * @param collection * the collection whose elements a function is to be applied to. * @param function * the function to be applied to the given collection's elements. * @return a List of the results from the function applications on the given * collection's elements. * @param <F> * the type of the collection's elements. * @param <T> * the result type of the function applied to the collection's * elements. */ public static <F, T> List<T> mapIntoList( Collection<? extends F> collection, Function<F, T> function) { return mapIntoList(collection.iterator(), function); } /** * Stores results of applying a function to a collection's elements in a * new, empty array list and returns it. * * @param collection * the collection whose elements a function is to be applied to. * @param function * the function to be applied to the given collection's elements. * @return an ArrayList of the results from the function applications on the * given collection's elements. * @param <F> * the type of the collection's elements. * @param <T> * the result type of the function applied to the collection's * elements. */ public static <F, T> ArrayList<T> mapIntoArrayList( Collection<? extends F> collection, Function<F, T> function) { ArrayList<T> result = collection .stream() .map(function::apply) .collect(toArrayList(collection.size())); // ArrayList<T> result = new ArrayList<T>(collection.size()); // for (F element : collection) { // result.add(function.apply(element)); // } return result; } /** * Stores results of applying a function to iterator's range in a * new, empty array list and returns it. * * @param iterator * the iterator whose range's elements a function is to be applied to. * @param function * the function to be applied to the given iterator's range elements. * @return an ArrayList of the results from the function applications on the * given iterator's range elements. * @param <F> * the type of the iterator's range elements. * @param <T> * the result type of the function applied to the iterator's range elements. */ public static <F, T> ArrayList<T> mapIntoArrayList( Iterator<? extends F> iterator, Function<F, T> function) { ArrayList<T> result = new ArrayList<T>(); for (F element : in(iterator)) { result.add(function.apply(element)); } return result; } /** * Stores results of applying a function to an array's elements in a * new, empty array list and returns it. * * @param array * the array whose elements a function is to be applied to. * @param function * the function to be applied to the given collection's elements. * @return an ArrayList of the results from the function applications on the * given collection's elements. * @param <F> * the type of the collection's elements. * @param <T> * the result type of the function applied to the collection's * elements. */ public static <F, T> ArrayList<T> mapIntoArrayList(F[] array, Function<F, T> function) { ArrayList<T> result = Arrays .stream(array) .map(function::apply) .collect(toArrayList(array.length)); return result; } public static <F, T> List<T> mapIntoList(F[] array, Function<F, T> function) { return mapIntoList(Arrays.asList(array), function); } /** * Stores results of applying a function to a collection's elements in a * new array and returns it. * * @param clazz the type of the objects in the array * @param collection * the collection whose elements a function is to be applied to. * @param function * the function to be applied to the given collection's elements. * @return an array of the results from the function applications on the * given collection's elements. * @param <F> * the type of the collection's elements. * @param <T> * the result type of the function applied to the collection's * elements. */ public static <F, T> T[] mapIntoArray(Class<T> clazz, Collection<? extends F> collection, Function<F, T> function) { @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(clazz, collection.size()); int i = 0; for(F element : collection) { result[i++] = function.apply(element); } return result; } /** * Stores results of applying a function to a collection's elements in a * new array of Objects and returns it. * * @param collection * the collection whose elements a function is to be applied to. * @param function * the function to be applied to the given collection's elements. * @return an array of the results from the function applications on the * given collection's elements. * @param <F> * the type of the collection's elements. * @param <T> * the result type of the function applied to the collection's * elements. */ public static <F, T> T[] mapIntoObjectArray(Collection<? extends F> collection, Function<F, T> function) { @SuppressWarnings("unchecked") T[] result = (T[]) new Object[collection.size()]; int i = 0; for(F element : collection) { result[i++] = function.apply(element); } return result; } /** * Indicates whether two collections contain the exact same instances in the * same (iterable) order. * * @param c1 * the first collection to test. * @param c2 * the second collection to test. * @return true if the two collections contain the eact same instances in * the same (iterable) order, false otherwise. * @param <T> * the type of the elements in the given collections. */ public static <T> boolean sameInstancesInSameIterableOrder( Collection<T> c1, Collection<T> c2) { Iterator<T> i1 = c1.iterator(); Iterator<T> i2 = c2.iterator(); while (i1.hasNext() && i2.hasNext()) { if (i1.next() != i2.next()) { return false; } } boolean result = !i1.hasNext() && !i2.hasNext(); // only true if they // are both done at // the same time return result; } /** * Stores results of applying a function to an set's elements in a new, * empty hash set and returns it. * * @param set * the set to map from. * @param function * the function to apply to each element in the set. * @return the results of applying the given function to the elements of the * given set. * @param <F> * the type of the elements in the Set. * @param <T> * the type of the result from applying the given function. */ public static <F, T> Set<T> mapIntoSet(Collection<? extends F> set, Function<F, T> function) { Set<T> result = set .stream() .map(function::apply) .collect(toLinkedHashSet(set.size())); return result; } /** * Stores results of applying a function to an collection's elements in a new, * empty linked hash set and returns it if any elements are distinct instances from originals, * or original collection otherwise. * * @param set * the set to map from. * @param function * the function to apply to each element in the set. * @return the results of applying the given function to the elements of the * given set, or same set if there are no changes * @param <T> * the type of the result from applying the given function. */ public static <T> Collection<T> mapIntoSetOrSameIfNoDistinctElementInstances(Collection<T> set, Function<T, T> function) { Collection<T> possibleResult = new LinkedHashSet<T>(); boolean change = false; for (T element : set) { T elementResult = function.apply(element); possibleResult.add(elementResult); change = change || elementResult != element; } return change? possibleResult : set; } /** * Stores results of applying a function to the values of a map in a new, * empty linked hash map and returns it. * * @param map * the map whose values to apply to function on. * @param function * the function to apply to each element in the set. * @return the results of applying the given function to the elements of the * given set. * @param <K> * the type of the keys in the maps. * @param <V1> * the type of the values in the input map. * @param <V2> * the type of the values in the output map. */ public static <K, V1, V2> LinkedHashMap<K, V2> applyFunctionToValuesOf( Map<? extends K, ? extends V1> map, Function<V1, V2> function) { LinkedHashMap<K, V2> result = map(); for (Map.Entry<? extends K, ? extends V1> entry : map.entrySet()) { result.put(entry.getKey(), function.apply(entry.getValue())); } return result; } /** * Collects elements in an iterator's range satisfying two different * conditions, returning false if some element does not satisfy either. * * @param iterator * an iterator over a collection of elements to be tested. * @param satisfyingCondition1 * populated with elements that satisfy condition1. * @param condition1 * the test to be applied to the iterator's range to be passed in * order to add elements to the given satisfyingCondition1 * collection. * @param satisfyingCondition2 * populated with elements that satisfy condition2. * @param condition2 * the test to be applied to the iterator's range to be passed in * order to add elements to the given satisfyingCondition2 * collection. * @return false is some element in the given iterator's range does not * satisfy both given conditions, true otherwise. * @param <E> * the type of the elements in the given collections. */ public static <E> boolean collectOrReturnFalseIfElementDoesNotFitEither( Iterator<E> iterator, Collection<E> satisfyingCondition1, Predicate<E> condition1, Collection<E> satisfyingCondition2, Predicate<E> condition2) { while (iterator.hasNext()) { E object = iterator.next(); boolean result1; boolean result2; if (result1 = condition1.apply(object)) { satisfyingCondition1.add(object); } if (result2 = condition2.apply(object)) { satisfyingCondition2.add(object); } if (!result1 && !result2) { return false; } } return true; } /** * Collects elements in a collection satisfying two different conditions, * returning false if some element does not satisfy either. * * @param collection * a collection of elements to be tested. * @param satisfyingCondition1 * populated with elements that satisfy condition1. * @param condition1 * the test to be applied to the elements of the given collection * to be passed in order to add elements to the given * satisfyingCondition1 collection. * @param satisfyingCondition2 * populated with elements that satisfy condition2. * @param condition2 * the test to be applied to the elements of the given collection * to be passed in order to add elements to the given * satisfyingCondition2 collection. * @return false is some element in the given collection does not satisfy * both given conditions, true otherwise. * @param <E> * the type of the elements in the given collections. */ public static <E> boolean collectOrReturnFalseIfElementDoesNotFitEither( Collection<E> collection, Collection<E> satisfyingCondition1, Predicate<E> condition1, Collection<E> satisfyingCondition2, Predicate<E> condition2) { return collectOrReturnFalseIfElementDoesNotFitEither( collection.iterator(), satisfyingCondition1, condition1, satisfyingCondition2, condition2); } /** * Collects elements in an iterator's range into two different given * collections, one with the N first elements satisfying a condition and the * other with the elements not doing so. Returns the index of the first of * the n elements satisfying condition or -1 if there aren't n element * satisfying the predicate. * * @param iterator * the iterator over whose range the first n are to be collected * from * @param n * the maximum number to be collected. * @param condition * the satisfying condition predicate * @param satisfyingCondition * those elements from the iterator's range that satisfy the * condition. * @param remaining * those elements from the iterator's range that don't satisfy * the condition. * @return the index of the first of the n elements satisfying the * condition, -1 if there aren't n elements satisfying the * condition. * @param <E> * the type of the elements from the iterator's range. */ public static <E> int collectFirstN(Iterator<E> iterator, int n, Predicate<E> condition, Collection<E> satisfyingCondition, Collection<E> remaining) { int i = 0; int result = -1; while (iterator.hasNext()) { E object = iterator.next(); if (n > 0 && condition.apply(object)) { satisfyingCondition.add(object); n--; if (result == -1) { result = i; } } else { remaining.add(object); } i++; } if (n != 0) { return -1; } return result; } /** * Collects elements in a collection into two different given collections, * one with the N first elements satisfying a condition and the other with * the elements not doing so. Returns the index of the first of the n * elements satisfying condition or -1 if there aren't n element satisfying * the predicate. * * @param c * the collection the first n elements are to be collected from. * @param n * the maximum number to be collected. * @param condition * the satisfying condition predicate * @param satisfyingCondition * those elements from the collection that satisfy the condition. * @param remaining * those elements from the collection that don't satisfy the * condition. * @return the index of the first of the n elements satisfying the * condition, -1 if there aren't n elements satisfying the * condition. * @param <E> * the type of the elements from the input collection. */ public static <E> int collectFirstN(Collection<E> c, int n, Predicate<E> condition, Collection<E> satisfyingCondition, Collection<E> remaining) { int result = collectFirstN(c.iterator(), n, condition, satisfyingCondition, remaining); return result; } /** * Collects elements in a given iterable into two different given * collections, one with the elements satisfying a condition and the other * with the elements not doing so. Returns the index of the first element * satisfying condition. * * @param iterable * an iterable over the elements to be tested. * @param satisfyingCondition * elements from the iterable that satisfy the given condition * will be added to this collection. * @param condition * the predicate used to test the elements in the given iterable. * @param remaining * elements from the iterable that do not satisfy the given * condition will be added to this collection. * @return the index of the first element satisfying the condition, -1 if * none satisfy. * @param <E> * the type of the elements being collected. */ public static <E> int collect(Iterable<E> iterable, Collection<E> satisfyingCondition, Predicate<E> condition, Collection<E> remaining) { final AtomicInteger i = new AtomicInteger(0); final AtomicInteger result = new AtomicInteger(-1); iterable.forEach(e -> { if (condition.apply(e)) { satisfyingCondition.add(e); if (result.intValue() == -1) { result.set(i.intValue()); } } else { remaining.add(e); } i.incrementAndGet(); }); return result.intValue(); } /** * Collects elements in a collection satisfying a given predicate into a * given collection, returning the latter. * * @param collection * the collection from which elements are to be collected from. * @param collected * elements from the given collection that pass the given * predicate test will be added to this collection. * @param predicate * the test to be used to select collect elements from the given * collection. * @return collected. * @param <E> * the type of the elements being collected. */ public static <E> Collection<E> collect(Collection<E> collection, Collection<E> collected, Predicate<E> predicate) { collection.stream().filter(predicate::apply) .forEach(collected::add); return collected; } /** * Collects elements in an iterator's range satisfying a given predicate * into a given collection, returning the latter. * * @param iterator * an iterator over whose range elements are to be collected * from. * @param collected * elements from the given iterator's range that pass the given * predicate test will be added to this collection. * @param predicate * the test to be used to select iterated elements from the given * iterator. * @return collected. * @param <E> * the type of the elements being collected. */ public static <E> Collection<E> collect(Iterator<E> iterator, Collection<E> collected, Predicate<E> predicate) { iterator.forEachRemaining(e -> { if (predicate.apply(e)) { collected.add(e); } }); return collected; } /** * Collects elements in a collection satisfying a given predicate into a new * linked list and returns it. * * @param collection * the collection from which elements are to be copied. * @param predicate * the test to be applied to determine which elements should be * copied into the returned list. * @return a List of the elements in the collection that matched the given * predicate. * @param <T> * the type of the elements to collect. */ public static <T> List<T> collectToList(Collection<T> collection, Predicate<T> predicate) { return (List<T>) collect(collection, new LinkedList<T>(), predicate); } /** * Collects elements in an iterator's range satisfying a given predicate into a new * linked list and returns it. * * @param iterator * the iterator from which elements are to be copied. * @param predicate * the test to be applied to determine which elements should be * copied into the returned list. * @return a List of the elements in the collection that matched the given * predicate. * @param <T> * the type of the elements to collect. */ public static <T> List<T> collectToList(Iterator<T> iterator, Predicate<T> predicate) { return (List<T>) collect(iterator, new LinkedList<T>(), predicate); } /** * Collects elements in a collection satisfying a given predicate into a new * array list and returns it. * * @param collection * the collection from which elements are to be copied. * @param predicate * the test to be applied to determine which elements should be * copied into the returned list. * @return a List of the elements in the collection that matched the given * predicate. * @param <T> * the type of the elements to collect. */ public static <T> ArrayList<T> collectToArrayList(Collection<T> collection, Predicate<T> predicate) { return (ArrayList<T>) collect(collection, new ArrayList<T>(), predicate); } /** * Collects elements in an iterator's range satisfying a given predicate into a new * linked array list and returns it. * * @param iterator * the iterator from which elements are to be copied. * @param predicate * the test to be applied to determine which elements should be * copied into the returned list. * @return a List of the elements in the collection that matched the given * predicate. * @param <T> * the type of the elements to collect. */ public static <T> ArrayList<T> collectToArrayList(Iterator<T> iterator, Predicate<T> predicate) { return (ArrayList<T>) collect(iterator, new ArrayList<T>(), predicate); } /** * Returns a list containing the elements in collection that satisfy the predicate. * @param collection * a collection to filter * @param predicate * a predicate to filter the given collection with. * @return a new list containing the elements in the give collection that satisfy the given predicate. * @param <T> the type of elements in the list */ public static <T> List<T> filter(Collection<T> collection, Predicate<T> predicate) { List<T> result = new LinkedList<T>(); for (T element : collection) { if (predicate.apply(element)) { result.add(element); } } return result; } /** * Returns the number of elements in collection satisfying predicate. * @param collection * a collection to count * @param predicate * a predicate to indicate which elements should be counted. * @return the number of elements in the given collection satisfying the given predicate. * @param <T> * the type of the elements in the collection. */ public static <T> int count(Collection<T> collection, Predicate<T> predicate) { int result = 0; for (T element : collection) { if (predicate.apply(element)) { result++; } } return result; } /** * Returns the number of elements in an iterator's range satisfying predicate. * @param iterator * an iterator whose range to count the elements of * @return the number of elements in the given iterator's range. * @param <T> * the type of the elements in the iterator's range. */ public static <T> int count(Iterator<T> iterator) { int result = 0; while (iterator.hasNext()) { iterator.next(); result++; } return result; } public static Number numberInJustNeededType(double number) { if (Math.floor(number) == number) { return Integer.valueOf((int) number); } return new Double(number); } public static Number sum(Iterator<Number> numbersIt) { double sum = 0; while (numbersIt.hasNext()) { sum += numbersIt.next().doubleValue(); } return numberInJustNeededType(sum); } public static Number sum(Collection<Number> numbers) { return sum(numbers.iterator()); } /** * Returns the sum of the elements in an array of integers. * @param array an array of ints * @return the sum of the elements in an array of integers. */ public static int sum(int[] array) { int result = 0; for (int element : array) { result += element; } return result; } public static Rational sumArbitraryPrecision(Iterator<Number> numbersIt) { Rational sum = Rational.ZERO; while (numbersIt.hasNext()) { Rational number = (Rational) numbersIt.next(); sum = sum.add(number); } return sum; } public static Rational sumArbitraryPrecision(Collection<Number> numbers) { return sumArbitraryPrecision(numbers.iterator()); } /** * Computer the maximum in the range of a {@link Rational} iterator, * throwing an error if the range is empty. * @param numbersIt * @return */ public static Rational maxArbitraryPrecision(Iterator<Rational> numbersIt) { if (numbersIt.hasNext()) { Rational result = numbersIt.next(); while (numbersIt.hasNext()) { Rational number = (Rational) numbersIt.next(); if (number.compareTo(result) > 0) { result = number; } } return result; } else { throw new Error("Iterator may not have empty range for Util.maxArbitraryPrecision(Iteator<Rational>)"); } } public static Rational maxArbitraryPrecision(Collection<Rational> numbers) { return maxArbitraryPrecision(numbers.iterator()); } public static Number product(Iterator<Number> numbersIt) { double product = 1; while (numbersIt.hasNext()) { product *= numbersIt.next().doubleValue(); if (product == 0) { break; } } return numberInJustNeededType(product); } public static Number product(Collection<Number> numbers) { return product(numbers.iterator()); } public static Rational productArbitraryPrecision(Iterator<Number> numbersIt) { Rational product = Rational.ONE; while (numbersIt.hasNext()) { Rational number = (Rational) numbersIt.next(); product = product.multiply(number); if (product.equals(0)) { break; } } return product; } public static Rational productArbitraryPrecision(Collection<Number> numbers) { return productArbitraryPrecision(numbers.iterator()); } /** * Returns a Number representing the quotient of a division, or null if * denominator is zero. * * @param numerator * the numerator. * @param denominator * the denominator. * @return a Number representing the quotient of a division, or null if * denominator is zero. */ public static Number division(Number numerator, Number denominator) { double denominatorValue = denominator.doubleValue(); if (denominatorValue == 0) { return null; } double numeratorValue = numerator.doubleValue(); double quotientValue = numeratorValue / denominatorValue; return numberInJustNeededType(quotientValue); } /** * Returns a Number representing the quotient of a division, or null if * denominator is zero, with arbitrary precision when possible. * * @param numerator * the numerator. * @param denominator * the denominator. * @return a Number representing the quotient of a division, or null if * denominator is zero, with arbitrary precision when possible. */ public static Rational divisionWithArbitraryPrecisionIfPossible( Rational numerator, Rational denominator) { if (denominator.isZero()) { return null; } // Note: In the case of Rational as opposed to the previously used // BigDecimal, // this should always be possible. Rational quotient = numerator.divide(denominator); return quotient; } /** * Returns the maximum in collection of numbers, or null if collection is * empty. * * @param numbers * a collection of numbers a maximum is to be found for. * @return the maximum element in the given collection, or null if * collection is empty. */ public static Number max(Collection<? extends Number> numbers) { Number result = max( numbers, (Number n1, Number n2) -> Double.compare(n1.doubleValue(), n2.doubleValue())); if (result != null) { result = numberInJustNeededType(result.doubleValue()); } return result; } /** * Returns the minimum in collection of numbers, or null if collection is * empty. * * @param numbers * a collection of numbers a minimum is to be found for. * @return the minimum element in the given collection, or null if * collection is empty. */ public static Number min(Collection<? extends Number> numbers) { Number result = min( numbers, (Number n1, Number n2) -> Double.compare(n1.doubleValue(), n2.doubleValue())); if (result != null) { result = numberInJustNeededType(result.doubleValue()); } return result; } /** * Returns the maximum element in a collection according to a comparator. * * @param c * the collection to find a maximum from. * @param comparator * the comparator to use to determine the maximum between * elements. * @return the maximum of the given collection, or null if the collection is * empty. * @param <T> * the type of the elements in the collection. */ public static <T> T max(Collection<? extends T> c, Comparator<T> comparator) { T result = null; Optional<? extends T> max = c.stream().max(comparator); if (max.isPresent()) { result = max.get(); } return result; } /** * Returns the maximum value of given function to an element of collection, * or null if collection is empty. * * @param c * the collection to find a maximum from. * @param function * the function. * @return the maximum value of function on any element of the given collection, * or null if the collection is empty. * @param <T> * the type of the elements in the collection. */ public static <T> Integer max(Collection<? extends T> c, Function<T, Integer> function) { Integer result = null; for (T element : c) { Integer value = function.apply(element); if (result == null || value.compareTo(result) > 0) { result = value; } } return result; } /** * Returns the minimum element in a collection according to a comparator. * * @param c * the collection to find a minimum from. * @param comparator * the comparator to use to determine the minimum between * elements. * @return the minimum of the given collection, or null if the collection is * empty. * @param <T> * the type of the elements in the collection. */ public static <T> T min(Collection<? extends T> c, Comparator<T> comparator) { T result = null; Optional<? extends T> min = c.stream().min(comparator); if (min.isPresent()) { result = min.get(); } return result; } /** * Returns the minimum value of given function to an element of collection, * or null if collection is empty. * * @param c * the collection to find a minimum from. * @param function * the function. * @return the minimum value of function on any element of the given collection, * or null if the collection is empty. * @param <T> * the type of the elements in the collection. */ public static <T> Integer min(Collection<? extends T> c, Function<T, Integer> function) { Integer result = null; for (T element : c) { Integer value = function.apply(element); if (result == null || value.compareTo(result) < 0) { result = value; } } return result; } /** * Returns the element in a collection whose value for the given function is minimum, * or null if collection is empty. * * @param c * the collection to find an element with a minimum function value. * @param function * the function. * @return the element with a minimum function value, * or null if the collection is empty. * @param <T> * the type of the elements in the collection. */ public static <T> T argmin(Collection<? extends T> c, Function<T, Integer> function) { Integer minimum = null; T result = null; for (T element : c) { Integer value = function.apply(element); if (minimum == null || value.compareTo(minimum) < 0) { minimum = value; result = element; } } return result; } /** * Returns the element in a collection whose value for the given function is maximum, * or null if collection is empty. * * @param c * the collection to find an element with a maximum function value. * @param function * the function. * @return the element with a maximum function value, * or null if the collection is empty. * @param <T> * the type of the elements in the collection. */ public static <T> T argmax(Collection<? extends T> c, Function<T, Integer> function) { Integer maximum = null; T result = null; for (T element : c) { Integer value = function.apply(element); if (maximum == null || value.compareTo(maximum) < 0) { maximum = value; result = element; } } return result; } public static Boolean and(Iterator<Boolean> booleansIt) { while (booleansIt.hasNext()) { if (!booleansIt.next()) { return false; } } return true; } public static Boolean and(Collection<Boolean> booleans) { return !booleans.stream().filter(b -> !b).findFirst().isPresent(); } public static Boolean or(Collection<Boolean> booleans) { return booleans.stream().filter(b -> b).findFirst().isPresent(); } /** * Returns a list composed of all elements of given list but the first one. * Throws an exception if list is empty. * * @param list * the list all elements except the first are to be returned * from. * @return the input list excluding the first element. * @param <T> * the type of the elements in the list. */ public static <T> List<T> rest(List<T> list) { List<T> result = list.subList(1, list.size()); return result; } public static <T> T applyTillIdentityDoesNotChange(Function<T, T> function, T object) { T previousOne; do { previousOne = object; object = function.apply(previousOne); } while (object != previousOne); return object; } public static <T> T applyFunctionsFromIteratorUntilFindingDifferentIdentityResultThenReturnIt( Iterator<Function<T, T>> functionIterator, T originalArgument) { while (functionIterator.hasNext()) { Function<T, T> function = functionIterator.next(); T result = function.apply(originalArgument); if (result != originalArgument) { return result; } } return originalArgument; } public static String stringOf(int repetitions, String string) { StringBuilder buffer = new StringBuilder(); while (repetitions-- > 0) { buffer.append(string); } return buffer.toString(); } /** * Indicates whether the elements of two iterators's ranges are equal. * * @param it1 * the first iterator to test. * @param it2 * the second iterator to test. * @return true if the elements of the two iterator's ranges are equal. */ public static boolean equals(Iterator it1, Iterator it2) { while (it1.hasNext()) { if (!it2.hasNext()) { return false; } Object o1 = it1.next(); Object o2 = it2.next(); if (!o1.equals(o2)) { return false; } } if (it2.hasNext()) { return false; } return true; } /** * A replacement for {@link Object#equals(Object)} that can deal with * objects being <code>null</code>. * * @param o1 * the first object to test. * @param o2 * the second object to test. * * @return true if true if the two object are null or both equal each other, * false otherwise. */ public static boolean equals(Object o1, Object o2) { if (o1 == null) { return o2 == null; } else if (o2 == null) { return false; } return o1.equals(o2); } /** * Indicates that neither of two objects are null and the first equals the * second. * * @param o1 * the first object to test. * @param o2 * the second object to test. * @return true if both object are not null and are equal, false otherwise. */ public static boolean notNullAndEquals(Object o1, Object o2) { if (o1 == null || o2 == null) { return false; } return o1.equals(o2); } /** * Indicates that two objects are not null and not equal. * * @param o1 * the first object to test. * @param o2 * the second object to test. * @return true if both object are not null and not equal, false otherwise. */ public static boolean notNullAndDistinct(Object o1, Object o2) { if (o1 == null || o2 == null) { return false; } return !o1.equals(o2); } /** * Indicates whether all elements in collection satisfy the given predicate. * * @param collection * the collection of elements to test. * @param predicate * the predicate to test the elements within the collection. * @return true if all elements in the collection match the given predicate, * false otherwise. * @param <E> * the type of the collections elements. */ public static <E> boolean forAll(Collection<E> collection, Predicate<E> predicate) { boolean result = collection.stream().allMatch(predicate::apply); return result; } /** * Indicates whether all elements in iterator's range satisfy the given predicate. * * @param iterator * the iterator over elements to test. * @param predicate * the predicate to test the elements within the iterator's range. * @return true if all elements in the iterator's range match the given predicate, * false otherwise. * @param <E> * the type of the elements iterated over. */ public static <E> boolean forAll(Iterator<E> iterator, Predicate<E> predicate) { while (iterator.hasNext()) { E element = iterator.next(); boolean predicateResult = predicate.apply(element); if ( ! predicateResult) { return false; } } return true; } /** * Indicates whether there is an element in iterator's range that satisfies * the given predicate. * * @param iterator * the iterator whose range of elements are to be tested. * @param predicate * the predicate to test the elements within the iterator's * range. * @return true if any element in the iterator's range match the given * predicate, false otherwise. * @param <E> * the type of the iterators range elements. */ public static <E> boolean thereExists(Iterator<E> iterator, Predicate<E> predicate) { while (iterator.hasNext()) { if (predicate.apply(iterator.next())) { return true; } } return false; } /** * Indicates whether there is an element in collection that satisfies the * given predicate. * * @param collection * the collection of elements to test. * @param predicate * the predicate to test the elements within the collection. * @return true if any element in the collection match the given predicate, * false otherwise. * @param <E> * the type of the collections elements. */ public static <E> boolean thereExists(Collection<E> collection, Predicate<E> predicate) { boolean result = collection.stream().anyMatch(predicate::apply); return result; } /** * Indicates whether there is a true element in array. * * @param array the array of booleans. * @return true if any element in the collection is true, false otherwise. */ public static boolean thereExists(boolean[] array) { for (boolean element : array) { if (element) { return true; } } return false; } /** * Adds all elements of two collections to a new LinkedList. * * @param c1 * the first collection to add elements from. * @param c2 * the second collection to add elements from. * @return a LinkedList containing the elements from both input collections. * @param <E> * the type of the collections elements. */ public static <E> List<E> union(Collection<E> c1, Collection<E> c2) { List<E> result = new LinkedList<E>(); result.addAll(c1); result.addAll(c2); return result; } /** * Adds all elements of given collections to a new LinkedList. * * @param collections * the collections whose elements should be added to the returned * list. * @return a new Linked List containing all the elements from the given * collections. * @param <E> * the type of the collections elements. */ public static <E> List<E> addAllToANewList(Collection<E>... collections) { LinkedList<E> result = new LinkedList<E>(); for (Collection<E> c : collections) { result.addAll(c); } return result; } public static String times(int level, String string) { StringBuilder result = new StringBuilder(); while (level-- > 0) { result.append(string); } return result.toString(); } /** * Creates PrintStream from file name checking for errors and throwing * appropriate {@link Error}s. * * @param fileName * the name of the file a print stream is to be created for. * @return the PrintStream against the given file. */ public static PrintStream getPrintStream(String fileName) { // use buffering PrintStream output; try { output = new PrintStream(fileName); } catch (IOException e) { throw new Error(e.getMessage()); } return output; } public static <T> T getFirstOrNull(Iterator<T> i) { if (i.hasNext()) { return i.next(); } return null; } public static <T> T getFirstOrNull(Collection<T> c) { return getFirstOrNull(c.iterator()); } /** * Returns the last element of a list or null, if empty. * * @param list * the list whose last element is to be returned. * @return the last element in the list or null if the list is empty. * @param <E> * the type of the elements in the list. */ public static <E> E getLast(List<E> list) { if (list.isEmpty()) { return null; } return list.get(list.size() - 1); } public static <T> T getFirst(Iterator<T> i) { return i.next(); } public static <T> T getFirst(Collection<T> c) { return getFirst(c.iterator()); } /** * Return all but the first element in an iterator's range, in a newly made * list. * * @param i * the iterator to get rest from. * @return all but the first element in the iterator's range, in a newly * made list. * @param <E> * the type of the elements in the iterator's range. */ public static <E> List<E> getRest(Iterator<E> i) { if (!i.hasNext()) { throw new Error("Util.getRest called on empty iterator"); } i.next(); List<E> result = listFrom(i); return result; } /** * Return all but the first element in a collection, in iteration order, in * a newly made list. * * @param c * the collection to get rest from. * @return all but the first element in the collection, in a newly made * list. * @param <E> * the type of the collections elements. */ public static <E> List<E> getRest(Collection<E> c) { return getRest(c.iterator()); } public static <E> E getFirstSatisfyingPredicateOrNull( Iterator<? extends E> i, Predicate<E> p) { while (i.hasNext()) { E o = i.next(); if (p.apply(o)) { return o; } } return null; } public static <E> E getFirstSatisfyingPredicateOrNull( Collection<? extends E> c, Predicate<E> p) { return getFirstSatisfyingPredicateOrNull(c.iterator(), p); } /** * Returns the first result of applying a given function to the elements of * a collection, or <code>null</code> if all such results are * <code>null</code>. * * @param c * the collection whose elements are to be mapped by the given * function. * @param f * the function to map the given elements with. * @return the first result of applying the given function to the elements * that is not null, otherwise null. * @param <A> * the type of the give collections arguments and the type of the * argument to the given function. * @param <R> * the result type of applying the given function to an element * in the given collection. */ public static <A, R> R getFirstNonNullResultOrNull(Collection<A> c, Function<A, R> f) { R result = null; Optional<R> first = c.stream().map(a -> f.apply(a)) .filter(r -> r != null).findFirst(); if (first.isPresent()) { result = first.get(); } return result; } public static <E> E findFirst(Collection<? extends E> c, Predicate<E> p) { return getFirstSatisfyingPredicateOrNull(c.iterator(), p); } public static <E> E findFirst(Iterator<? extends E> i, Predicate<E> p) { return getFirstSatisfyingPredicateOrNull(i, p); } public static <E> int getIndexOfFirstSatisfyingPredicateOrMinusOne(Collection<? extends E> c, Predicate<E> p) { int i = 0; for (E e : c) { if (p.apply(e)) { return i; } i++; } return -1; } public static <T> Set<T> intersection(Collection<T> c1, Collection<T> c2) { LinkedHashSet<T> result = new LinkedHashSet<T>(); for (T element : c1) { if (c2.contains(element)) { result.add(element); } } return result; } /** * Indicates whether two collections intersect. * * @param c1 * the first collection to test. * @param c2 * the second collection to test. * @return true if the two collections intersect. * @param <E1> * the type of the elements in the first collection. * @param <E2> * the type of the elements in the second collection. */ public static <E1, E2> boolean intersect(Collection<E1> c1, Collection<E2> c2) { boolean result; // Optimization: Traverse the smaller list. if (c1.size() < c2.size()) { result = c1.stream().filter(e -> c2.contains(e)).findAny() .isPresent(); } else { result = c2.stream().filter(e -> c1.contains(e)).findAny() .isPresent(); } return result; } /** * A structure for * {@link Util#selectPair(List, Predicate, Predicate, BinaryPredicate)} and * {@link Util#selectPairInEitherOrder(List, Predicate, Predicate, BinaryPredicate)} results. * * @param <P> the type of the pairs. */ public static class SelectPairResult<P> { public SelectPairResult(P first, P second, int indexOfFirst, int indexOfSecond, P satisfiesFirstPredicate, P satisfiesSecondPredicate) { super(); this.first = first; this.second = second; this.indexOfFirst = indexOfFirst; this.indexOfSecond = indexOfSecond; this.satisfiesFirstPredicate = satisfiesFirstPredicate; this.satisfiesSecondPredicate = satisfiesSecondPredicate; } /** Element appearing first. */ public P first; /** Element appearing second. */ public P second; /** Index of element appearing first. */ public int indexOfFirst; /** Index of element appearing second. */ public int indexOfSecond; /** Element satisfying first predicate. */ public P satisfiesFirstPredicate; /** Element satisfying second predicate. */ public P satisfiesSecondPredicate; } /** * Returns the indices of first pair of elements of a list such that each of * them satisfies a respectively given unary predicate, and them both * satisfy a binary predicate, or null if there is no such pair. * * @param list * the elements to test. * @param unaryPredicate1 * the first predicate to test with. * @param unaryPredicate2 * the second predicate to test with. * @param binaryPredicate * the binary predicate to test with. * @return the indices of first pair of elements of a list such that each of * them satisfies a respectively given unary predicate, and them * both satisfy a binary predicate, or null if there is no such * pair. * @param <T> * the type of the elements in the list. */ public static <T> SelectPairResult<T> selectPair(List<? extends T> list, Predicate<T> unaryPredicate1, Predicate<T> unaryPredicate2, BinaryPredicate<T, T> binaryPredicate) { for (int i = 0; i != list.size(); i++) { final T o1 = list.get(i); if (unaryPredicate1.apply(o1)) { for (int j = i + 1; j != list.size(); j++) { final T o2 = list.get(j); if (unaryPredicate2.apply(o2) && binaryPredicate.apply(o1, o2)) { return new SelectPairResult<T>(o1, o2, i, j, o1, o2); } } } } return null; } /** * Like {@link #selectPair(List, Predicate, Predicate, BinaryPredicate)} , * but the pair may be present in either order. The binary predicate, for * consistency, is always applied to <code>(x1, x2)</code> where * <code>x1</code> is the element satisfying the first unary predicate (as * opposed to being the element that appears first), and where * <code>x2</code> is the element satisfying the second unary predicate (as * opposed to being the element that appears second). * * @param list * the elements to test. * @param unaryPredicate1 * the first predicate to test with. * @param unaryPredicate2 * the second predicate to test with. * @param binaryPredicate * the binary predicate to test with. * @return Like * {@link #selectPair(List, Predicate, Predicate, BinaryPredicate)} * , but the pair may be present in either order. The binary * predicate, for consistency, is always applied to * <code>(x1, x2)</code> where <code>x1</code> is the element * satisfying the first unary predicate (as opposed to being the * element that appears first), and where <code>x2</code> is the * element satisfying the second unary predicate (as opposed to * being the element that appears second). * @param <T> * the type of the elements in the list. */ public static <T> SelectPairResult<T> selectPairInEitherOrder( List<? extends T> list, Predicate<T> unaryPredicate1, Predicate<T> unaryPredicate2, BinaryPredicate<T, T> binaryPredicate) { // straight implementation // for (int i = 0; i != list.size(); i++) { // final T o1 = list.get(i); // boolean o1SatisfiesPredicate1 = unaryPredicate1.evaluate(o1); // boolean o1SatisfiesPredicate2 = unaryPredicate2.evaluate(o1); // // for (int j = i + 1; j != list.size(); j++) { // final T o2 = list.get(j); // boolean o2SatisfiesPredicate1 = unaryPredicate1.evaluate(o2); // boolean o2SatisfiesPredicate2 = unaryPredicate2.evaluate(o2); // // if (o1SatisfiesPredicate1 && o2SatisfiesPredicate2) { // boolean o1AndO2SatisfyBinaryPredicate = binaryPredicate.evaluate(o1, // o2); // if (o1AndO2SatisfyBinaryPredicate) { // return new SelectPairResult<T>(o1, o2, i, j, o1, o2); // } // } // // if (o2SatisfiesPredicate1 && o1SatisfiesPredicate2) { // boolean o2AndO1SatisfyBinaryPredicate = binaryPredicate.evaluate(o2, // o1); // if (o2AndO1SatisfyBinaryPredicate) { // return new SelectPairResult<T>(o1, o2, i, j, o2, o1); // } // } // } // } // return null; // implementation optimized for minimizing the calls to the predicates. for (int i = 0; i != list.size(); i++) { final T o1 = list.get(i); boolean o1SatisfiesPredicate1 = unaryPredicate1.apply(o1); if (o1SatisfiesPredicate1) { boolean o1SatisfyingOfPredicate2AlreadyComputed = false; boolean o1SatisfiesPredicate2 = false; // initial value is // irrelevant (never // used). Just making // compiler happy. int j; for (j = i + 1; j != list.size(); j++) { final T o2 = list.get(j); boolean o2SatisfiesPredicate2 = unaryPredicate2.apply(o2); if (o2SatisfiesPredicate2) { boolean o1AndO2SatisfyBinaryPredicate = binaryPredicate .apply(o1, o2); if (o1AndO2SatisfyBinaryPredicate) { return new SelectPairResult<T>(o1, o2, i, j, o1, o2); } } else { boolean o2SatisfiesPredicate1 = unaryPredicate1 .apply(o2); if (o2SatisfiesPredicate1) { if (!o1SatisfyingOfPredicate2AlreadyComputed) { o1SatisfiesPredicate2 = unaryPredicate2 .apply(o1); o1SatisfyingOfPredicate2AlreadyComputed = true; } if (o1SatisfiesPredicate2) { boolean o2AndO1SatisfyBinaryPredicate = binaryPredicate .apply(o2, o1); if (o2AndO1SatisfyBinaryPredicate) { return new SelectPairResult<T>(o1, o2, i, j, o2, o1); } } } } } } else { boolean o1SatisfiesPredicate2 = unaryPredicate2.apply(o1); if (o1SatisfiesPredicate2) { for (int j = i + 1; j != list.size(); j++) { final T o2 = list.get(j); boolean o2SatisfiesPredicate1 = unaryPredicate1 .apply(o2); if (o2SatisfiesPredicate1) { boolean o2AndO1SatisfyBinaryPredicate = binaryPredicate .apply(o2, o1); if (o2AndO1SatisfyBinaryPredicate) { return new SelectPairResult<T>(o1, o2, i, j, o2, o1); } } } } } } return null; } /** * Returns two lists: one containing the elements of a list with indices * from 0 to i - 1, and another containing elements of indices i + 1 to the * last, excluding j. * * @param list * the list whose elements are to be sliced into two lists. * @param i * the index of the element to slice the list into two. * @param j * the index of an element > i to be excluded from the second * slice. * @return two lists: one containing the elements of a list with indices * from 0 to i - 1, and another containing elements of indices i + 1 * to the last, excluding j. * @param <E> * the type of the elements in the list. */ public static <E> Pair<List<E>, List<E>> slicesBeforeIAndRestWithoutJ( List<E> list, int i, int j) { Pair<List<E>, List<E>> result = new Pair<>(new LinkedList<>(), new LinkedList<>()); for (int k = 0; k != i; k++) { result.first.add(list.get(k)); } for (int k = i + 1; k != list.size(); k++) { if (k != j) { result.second.add(list.get(k)); } } return result; } /** * Adds elements contained in c1 but not c2 to a given collection result. * * @param c1 * the elements to be placed in the result if they are not in the * second collection. * @param c2 * the elements not be added to the result. * @param result * the collection to be returned as the result. * @return result with elements contained in c1 that are not in c2 added to * it. * @param <E> * the type of the elements. */ public static <E> Collection<E> setDifference(Collection<E> c1, Collection<E> c2, Collection<E> result) { c1.stream().filter(e -> !c2.contains(e)).forEach(result::add); return result; } /** * Adds elements contained in c1 but not c2 to a new linked list and returns * it. * * @param c1 * the elements to be placed in the result if they are not in the * second collection. * @param c2 * the elements not be added to the result. * @return a new LinkedList with elements contained in c1 that are not in c2 * added to it. * @param <E> * the type of the elements. */ public static <E> List<E> setDifference(Collection<E> c1, Collection<E> c2) { return (List<E>) setDifference(c1, c2, new LinkedList<E>()); } /** * Adds elements contained in c1 but not c2 to a new linked list and returns * it. * * @param c1 * the elements to be placed in the result if they are not in the * second collection. * @param c2 * the elements not be added to the result. * @return a new LinkedList with elements contained in c1 that are not in c2 * added to it. * @param <E> * the type of the elements. */ public static <E> List<E> subtract(Collection<E> c1, Collection<E> c2) { return (List<E>) setDifference(c1, c2, new LinkedList<E>()); } public static String camelCaseToSpacedString(String camel) { StringBuilder result = new StringBuilder(); int i = 0; while (i < camel.length()) { char c = camel.charAt(i); if (Character.isUpperCase(c) && i != 0) { result.append(' '); int initialUpperCaseLetterIndex = i; while (i < camel.length() && Character.isUpperCase(camel.charAt(i))) { // if this is upper case but next one is lower case, then // this is the first letter of a word, // so append space first. if (i > initialUpperCaseLetterIndex && i + 1 < camel.length() && Character.isLowerCase(camel.charAt(i + 1))) { result.append(' '); } result.append(Character.toLowerCase(camel.charAt(i))); i++; } } else { result.append(c); i++; } } return result.toString(); } /** * Gets a collection and returns it back if there are no repeated elements, * or an ArrayList with unique elements. * * @param c * the collection to be tested. * @return the given collection if there are no repreated elements, or an * ArrayList with unique elements. * @param <E> * the type of the elements. */ public static <E> Collection<E> removeRepeatedNonDestructively(Collection<E> c) { LinkedHashSet<E> s = new LinkedHashSet<E>(c); if (s.size() == c.size()) { return c; } return new ArrayList<E>(s); } public static <T> List<T> removeNonDestructively(List<T> list, int excludedIndex) { if (excludedIndex >= list.size()) { return list; } ArrayList<T> newList = new ArrayList<T>(); int i = 0; for (T element : list) { if (i != excludedIndex) { newList.add(element); } i++; } return newList; } /** * Returns a new linked list containing the elements of collection that do not * satisfy a predicate. * * @param collection * the collection of elements to be tested. * @param predicate * the predicate to be used to test the elements. * @return a new linked list containing the elements of list that do not * satisfy a predicate. * @param <E> * the type of the elements. */ public static <E> LinkedList<E> removeNonDestructively(Collection<E> collection, Predicate<E> predicate) { LinkedList<E> result = collection.stream() .filter(e -> !predicate.apply(e)) .collect(toLinkedList()); return result; } /** * Returns a new linked hash set containing the elements of set that do not * satisfy a predicate. * * @param set * the set of elements to be tested. * @param predicate * the predicate to be used to test the elements. * @return a new linked hash set containing the elements of set that do not * satisfy a predicate. * @param <E> * the type of the elements. */ public static <E> LinkedHashSet<E> removeFromSetNonDestructively(Set<E> set, Predicate<E> predicate) { LinkedHashSet<E> result = set.stream() .filter(e -> !predicate.apply(e)) .collect(toLinkedHashSet(set.size())); return result; } /** * Returns a new linked hash set containing the elements of array list that do not * satisfy a predicate. * * @param arrayList * the array list of elements to be tested. * @param predicate * the predicate to be used to test the elements. * @return a new array list containing the elements of set that do not * satisfy a predicate. * @param <E> * the type of the elements. */ public static <E> ArrayList<E> removeFromArrayListNonDestructively(ArrayList<E> arrayList, Predicate<E> predicate) { ArrayList<E> result = new ArrayList<E>(arrayList.size()); for (E element : arrayList) { if (!predicate.apply(element)) { result.add(element); } } return result; } /** * Returns a new linked list containing the elements of collection that are not equal to * a given one. * * @param collection * the collection of elements to be tested. * @param element * the element to be removed * @return a new linked list containing the elements of list that are not equal to the * given element. * @param <T> * the type of the elements. */ public static <T> List<T> removeNonDestructively(Collection<T> collection, T element) { List<T> result = removeNonDestructively(collection, Equals.make(element)); return result; } public static <T> List<T> makeAListByReplacingFirstOccurrenceOfElementInAListWithAnotherList( List<T> list, T element, List<T> anotherList) { ArrayList<T> result = new ArrayList<T>(); boolean replacementAlreadyHappened = false; for (T someElement : list) { if (!replacementAlreadyHappened && someElement.equals(element)) { result.addAll(anotherList); replacementAlreadyHappened = true; } else { result.add(someElement); } } return result; } /** * Returns list of results of application of a function to pairs of elements * with same indices on two given lists. This is based on a Haskell function * of same name. * * @param function * the function to be applied to the paired elements from each * list. * @param list1 * a list of the first arguments to be zipped. * @param list2 * a list of the second arguments to be zipped. * @return a list of results of application of given function to pairs of * elements with same indices in two given lists. * @param <A1> * the type of the elements of list 1. * @param <A2> * the type of the elements of list 2. * @param <R> * the type of the result of applying the given function to the * given pair of arguments. */ public static <A1, A2, R> List<R> zipWith( BinaryFunction<A1, A2, R> function, List<A1> list1, List<A2> list2) { List<R> result = new LinkedList<R>(); Iterator<A1> i1 = list1.iterator(); Iterator<A2> i2 = list2.iterator(); while (i1.hasNext()) { A1 t1 = i1.next(); A2 t2 = i2.next(); R application = function.apply(t1, t2); result.add(application); } return result; } /** * Returns list of results of application of a function to triples of * elements with same indices on three given lists. This is based on a * Haskell function of same name. * * @param function * the function to be applied to the paired elements from each * list. * @param list1 * a list of the first arguments to be zipped. * @param list2 * a list of the second arguments to be zipped. * @param list3 * a list of the third arguments to be zipped. * @return a list of results of application of given function to triples of * elements with same indices in three given lists. * @param <A1> * the type of the elements of list 1. * @param <A2> * the type of the elements of list 2. * @param <A3> * the type of the elements of list 3. * @param <R> * the type of the result of applying the given function to the * given triple of arguments. */ public static <A1, A2, A3, R> List<R> zip3With( TernaryFunction<A1, A2, A3, R> function, List<A1> list1, List<A2> list2, List<A3> list3) { List<R> result = new LinkedList<R>(); Iterator<A1> i1 = list1.iterator(); Iterator<A2> i2 = list2.iterator(); Iterator<A3> i3 = list3.iterator(); while (i1.hasNext() && i2.hasNext() && i3.hasNext()) { A1 f1 = i1.next(); A2 f2 = i2.next(); A3 f3 = i3.next(); R application = function.apply(f1, f2, f3); result.add(application); } return result; } /** * Returns same list if none of its elements gets evaluated to a distinct * object by a replacement function, or a new list equal to the original one * but for having elements replaced by their replacements as provided by * same replacement function. * * @param list * the elements to be mapped. * @param replacementFunction * the element replacement function. * @return the same list if none of its elements gets evaluated to a * distinct object by a replacement function, or a new list equal to * the original one but for having elements replaced by their * replacements as provided by same replacement function. * @param <E> * the type of the elements in the list. */ public static <E> List<E> replaceElementsNonDestructively(List<E> list, Function<E, E> replacementFunction) { List<E> replacementList = null; ListIterator<E> it = list.listIterator(); while (it.hasNext()) { E element = it.next(); E replacement = replacementFunction.apply(element); if (replacement != element) { replacementList = new ArrayList<E>(list); replacementList.set(it.previousIndex(), replacement); break; } } if (replacementList == null) { return list; } it = replacementList.listIterator(it.nextIndex()); while (it.hasNext()) { E element = it.next(); E replacement = replacementFunction.apply(element); if (replacement != element) { it.set(replacement); } } return replacementList; } /** * Evaluates replacement function on i-th element of given list * and returns a new list with -ith element replaced by the result, * if the result is different from the original element, * or the same list if the result is equal to the original element. * * @param list * the list. * @param i the index of the element to be possibly replaced * @param replacementFunction * the element replacement function. * @return the same list if the i-th element gets evaluated to itself, * or a new (array) list with copied elements but for the i-th, * which gets replaced by the evaluation result. * @param <E> * the type of the elements in the list. */ public static <E> List<E> replaceElementNonDestructively( List<E> list, int i, Function<E, E> replacementFunction) { E element = list.get(i); E evaluationResult = replacementFunction.apply(element); List<E> result; if (evaluationResult.equals(element)) { result = list; } else { result = new ArrayList<E>(list); result.set(i, evaluationResult); } return result; } public static <T1, T2> boolean isPairWiseTrue(BinaryPredicate<T1, T2> p, Collection<T1> c1, Iterator<T2> it2) { return isPairWiseTrue(p, c1.iterator(), it2); } public static <T1, T2> boolean isPairWiseTrue(BinaryPredicate<T1, T2> p, Iterator<T1> it1, Collection<T2> c2) { return isPairWiseTrue(p, it1, c2.iterator()); } public static <T1, T2> boolean isPairWiseTrue(BinaryPredicate<T1, T2> p, Iterator<T1> it1, Iterator<T2> it2) { while (it1.hasNext() && it2.hasNext()) { T1 t1 = it1.next(); T2 t2 = it2.next(); if (!p.apply(t1, t2)) { return false; } } if (it1.hasNext() != it2.hasNext()) { return false; } return true; } public static <T1, T2> boolean isPairWiseTrue(BinaryPredicate<T1, T2> p, Collection<T1> c1, Collection<T2> c2) { if (c1.size() != c2.size()) { return false; } Iterator<T1> it1 = c1.iterator(); Iterator<T2> it2 = c2.iterator(); while (it1.hasNext()) { T1 t1 = it1.next(); T2 t2 = it2.next(); if (!p.apply(t1, t2)) { return false; } } return true; } public static <T> List<T> setNonDestructively(List<T> list, int index, T newElement) { List<T> result = new LinkedList<T>(list); result.set(index, newElement); return result; } /** * Returns a given iterator after iterating over its first element. * * @param iterator * the iterator to iterate over its first element. * @return the iterator after it has been moved past its first element. * Throws error if the iterator's range is empty. * @param <E> * the type of the elements in the iterators range. */ public static <E> Iterator<E> removeFirst(Iterator<E> iterator) { if (iterator.hasNext()) { iterator.next(); return iterator; } Util.fatalError("Iterator without elements received by Util.removeFirst(Iterator)"); return null; } public static <T> List<T> getAllButFirst(List<T> list) { Iterator<T> iterator = list.iterator(); iterator.next(); LinkedList<T> result = new LinkedList<T>(); addAll(result, iterator); return result; } /** * Compares two integers, taking into account that -1 means "infinite", * using the same return value convention as {@link Comparator}. * * @param limit1 * the first integer to compare. * @param limit2 * the second integer to compare. * @return the comparison between the two given integers, taking into * account that -1 means "infinite", using the same return value * convention as {@link Comparator}. * */ public static int compareIntegersWithMinusOneMeaningInfinite(int limit1, int limit2) { if (limit1 == -1) { if (limit2 == -1) { return 0; } else { return +1; } } else { if (limit2 == -1) { return -1; } else { return limit1 - limit2; } } } /** * Indicates whether an iterator's range contains a given element. * * @param iterator * the iterator whose range is to be tested. * @param element * the element to test if it is in the given iterators range. * @return true if the given element is in the given iterators range. * @param <E> * the type of the elements. */ public static <E> boolean contains(Iterator<E> iterator, E element) { while (iterator.hasNext()) { if (iterator.next().equals(element)) { return true; } } return false; } /** * Indicates whether an element appears in a list from a given position. * * @param list * the list whose elements are to be tested. * @param i * the starting position in the list to start testing from. * @param element * the element to test if it is in the given sublist. * @return true if the element appears in the list from a given position, * false otherwise. * @param <E> * the type of the elements. */ public static <E> boolean listFromIContains(ArrayList<E> list, int i, E element) { ListIterator<E> iterator = list.listIterator(i); boolean result = contains(iterator, element); return result; } /** * Indicates whether an element appears in a list in a position up to, but * different from, i. * * @param list * the list whose elements are to be tested. * @param i * the index in the list that are to be tested to. * @param element * the element to test if its is in the given sublist. * @return true if the element appears in the list is a position up to, but * different from, i. * @param <E> * the type of the elements. */ public static <E> boolean listUpToIExclusiveContains(ArrayList<E> list, int i, E element) { Iterator<E> iterator = list.iterator(); for (int j = 0; iterator.hasNext() && j != i; j++) { E element2 = iterator.next(); if (element2.equals(element)) { return true; } } return false; } public static <T> void removeAll(Set<T> c, Predicate<T> p) { List<T> toBeRemoved = collectToList(c, p); c.removeAll(toBeRemoved); } public static <K, V> void removeAll(Map<K, V> map, Collection<K> keysToRemove) { for (K key : keysToRemove) { map.remove(key); } } public static boolean lessThan(Rational r1, Rational r2) { int comparison = r1.compareTo(r2); return comparison == -1; } public static boolean lessThanOrEqualTo(Rational r1, Rational r2) { int comparison = r1.compareTo(r2); return comparison == -1 || comparison == 0; } public static boolean greaterThan(Rational r1, Rational r2) { int comparison = r1.compareTo(r2); return comparison == 1; } public static boolean equalValues(Rational r1, Rational r2) { int comparison = r1.compareTo(r2); return comparison == 0; } public static boolean greaterThanOrEqualTo(Rational r1, Rational r2) { int comparison = r1.compareTo(r2); return comparison == 0 || comparison == 1; } public static boolean equals(Rational rational, int integer) { return rational.compareTo(integer) == 0; } /** * Removes the elements that satisfy a predicate from a list. * * @param list * the list of elements to be tested. * @param predicate * the predicate to test the elements on the list with. * @param <E> * the type of the elements. */ public static <E> void removeElementsSatisfying(List<? extends E> list, Predicate<E> predicate) { ListIterator<? extends E> iterator = list.listIterator(); while (iterator.hasNext()) { E element = iterator.next(); if (predicate.apply(element)) { iterator.remove(); } } } /** * Removes the elements that satisfy a predicate from a set -- works for * sets not containing null elements only. * * @param set * the set of elements to be tested. * @param predicate * the predicate to test the elements on the set with. * @param <E> * the type of the elements. */ public static <E> void removeElementsSatisfying(Set<? extends E> set, Predicate<E> predicate) { boolean removed; do { removed = false; E element = getFirstSatisfyingPredicateOrNull(set, predicate); if (element != null) { set.remove(element); removed = true; } } while (removed); } public static <T> Pair<T, T> pair(T first, T second) { return new Pair<T, T>(first, second); } /** * Returns an object's toString() result, or string "null" if object is * null. * * @param object * the object to be toString'd. * @return the object's toString() result, or string "null" if the object is * null. */ public static String toStringOrNull(Object object) { if (object == null) { return "null"; } return object.toString(); } /** * Returns +1 if given int is greater than 0, 0 if it is 0, and -1 if it is * less than 0. * * @param integer * the integer to be tested. * @return +1 if given int is greater than 0, 0 if it is 0, and -1 if it is * less than 0. */ public static int signal(int integer) { if (integer == 0) { return 0; } else if (integer > 0) { return +1; } return -1; } /** * Creates a map from a list of keys and a list of values. * * @param keys * a list of keys to be contained in the returned map. * @param values * a list of values to be contained in the returned map. * @return a map from the given lists of keys and values. * @param <K> * the type of the keys. * @param <V> * the type of the values. */ public static <K, V> Map<K, V> mapFromListOfKeysAndListOfValues( List<K> keys, List<V> values) { if (keys.size() != values.size()) { throw new Error( "mapFromListOfKeysAndListOfValues requires two lists of same size but got " + keys + " with " + keys.size() + " elements and " + values + " with " + values.size() + " elements."); } LinkedHashMap<K, V> result = new LinkedHashMap<K, V>(); Iterator<K> keysIterator = keys.iterator(); Iterator<V> valuesIterator = values.iterator(); while (keysIterator.hasNext()) { K key = keysIterator.next(); V value = valuesIterator.next(); result.put(key, value); } return result; } /** * Given map1 and map2, returns a new map such that map(K) = map2(map1(K)) * * @param map1 * the first map to compose. * @param map2 * the second map to compose. * @return a new map such that map(K) = map2(map1(K)) * @param <K> * the type of map1's keys. * @param <V1> * the type of map1's values and map2's keys. * * @param <V2> * the type of map2's values. */ public static <K, V1, V2> Map<K, V2> composeMaps(Map<K, V1> map1, Map<V1, V2> map2) { Map<K, V2> result = new LinkedHashMap<K, V2>(); for (Map.Entry<K, V1> entry : map1.entrySet()) { K key = entry.getKey(); V1 value1 = entry.getValue(); V2 value2 = map2.get(value1); result.put(key, value2); } return result; } /** * Wait for some time, throwing an error in case of an exception. * * @param time * the time in milliseconds to wait. */ public static void waitOrThrowError(long time) { try { Thread.sleep(time); } catch (Exception e) { throw new Error("Unexpected exception:", e); } } /** * Returns the first object in an array that is an instance of a given * class. * * @param clazz * the class of the object to be found. * @param args * the elements to be tested if they are of the given class. * @return the first object in the given args array that is an instance of * the given class. */ public static Object getObjectOfClass(Class clazz, Object[] args) { for (Object object : args) { if (clazz.isInstance(object)) { return object; } } return null; } /** * Incrementally calculates component-wise averages, given previously * calculated averages (out of n numbers) and a list of new numbers. The * average list is filled with the appropriate number of zeros if it is * empty. The result is stored in-place, destroying the previous average * list. * * @param average * previously calculated averages. * @param n * averages out of 'n' numbers. * @param newItems * new numbers. * @return an incrementally calculated component-wise average. */ static public List incrementalComputationOfComponentWiseAverage( List<Number> average, int n, List newItems) { if (average == null) { fatalError("Util.incrementalComputationOfComponentWiseAverage must receive a non-null List"); } if (average.size() == 0) { for (int i = 0; i != newItems.size(); i++) { average.add(new Double(0)); } } for (int i = 0; i != newItems.size(); i++) { double currentAverage = ((Double) average.get(i)).doubleValue(); double newItem = ((Double) newItems.get(i)).doubleValue(); double newAverage = (currentAverage * n + newItem) / (n + 1); average.set(i, new Double(newAverage)); } return average; } /** * A more general version of incrementalComputationOfComponentWiseAverage(List, int, * List) that operates on lists of lists of arbitrary depth, * including depth 0, that is, on {@link Number}s. It is in-place and * returns <code>average</code> if given objects are lists, or returns a new * Number otherwise. * * @param average * previously calculated averages. * @param n * averages out of 'n' numbers. * @param newItems * new numbers. * @return an incrementally calculated component-wise average. */ @SuppressWarnings("unchecked") public static Object incrementalComponentWiseAverageArbitraryDepth( Object average, int n, Object newItems) { if (average instanceof Number) { return (((Number) average).doubleValue() * n + ((Number) newItems) .doubleValue()) / (n + 1); } ListIterator averageIterator = ((List<Number>) average).listIterator(); ListIterator newItemsIt = ((List) newItems).listIterator(); while (averageIterator.hasNext()) { Object averageElement = averageIterator.next(); Object newItemsElement = newItemsIt.next(); Object newAverageElement = incrementalComponentWiseAverageArbitraryDepth( averageElement, n, newItemsElement); if (newAverageElement != averageElement) { averageIterator.set(newAverageElement); } } return average; } /** * Given an array <code>a</code>, returns a map from each string in it to * the immediately following object. More precisely, returns a map mapping * each String <code>s</code> in position <code>i</code> of <code>a</code> * to the object in position <code>i+1</code> of <code>a</code>, ignoring * the remaining elements. * * @param arguments * the arguments to be processed. * @return a map from each string in the given arguments array to the * immediately following object. */ public static Map<String, Object> getMapWithStringKeys(Object[] arguments) { Map<String, Object> map = new HashMap<String, Object>(); for (int i = 0; i < arguments.length; i++) { Object argument = arguments[i]; if (argument instanceof String) { String variable = (String) argument; Object value = arguments[++i]; map.put(variable, value); } } return map; } /** * Returns a function that returns a new iterator to the given collection * each time is it invoked. * * @param c * the collection the returned function is to create an iterator * over whenever it is applied. * @return a function that returns a new iterator to the given collection * each time it is invoked. * @param <E> the type of the elements. */ static public <E> NullaryFunction<Iterator<E>> getIteratorNullaryFunction( final Collection<E> c) { return new NullaryFunction<Iterator<E>>() { @Override public Iterator<E> apply() { return c.iterator(); } }; } /** * Takes a list of lists, a dimension index (0 for rows, 1 for columns) and * an index (either row or column index), and returns the corresponding * slice (data[index,*] if dimension is 0, or data[*,index] if dimension is * 1). * * @param data * a list of lists * @param dimension * a dimension index (0 for rows, 1 for columns) * @param index * an row or column index. * @return the corresponding slice * @param <E> * the type of the elements. */ public static <E> List<E> matrixSlice(List<List<E>> data, int dimension, int index) { if (dimension == 0) { return data.get(index); } List<E> result = new LinkedList<E>(); for (Iterator<List<E>> rowIt = data.iterator(); rowIt.hasNext();) { List<E> row = rowIt.next(); result.add(row.get(index)); } return result; } public static String[] makeArrayFilledOutWith(String element, int length) { String[] result = new String[length]; for (int i = 0; i < result.length; i++) { result[i] = element; } return result; } public static List<String> getFirstColumnAsList(String[][] stringMatrix) { List<String> list = new LinkedList<String>(); for (int i = 0; i < stringMatrix.length; i++) { list.add(stringMatrix[i][0]); } return list; } public static String[] getSecondColumnAsArray(String[][] stringMatrix) { String[] array = new String[stringMatrix.length]; for (int i = 0; i < stringMatrix.length; i++) { array[i] = stringMatrix[i][1]; } return array; } /** * Randomly picks an element of given array using a given {@link Random} * number generator. * * @param random * the random number generator to use. * @param items * the items from which an element is to be randomly picked from. * @return the randomly picked element from the given array of items. */ public static Object randomPick(Random random, Object[] items) { int index = random.nextInt(items.length); Object result = items[index]; return result; } /** * Randomly picks <code>n</code> elements (possibly repeated) of given array * using a given {@link Random} number generator. * * @param n * the number of items to randomly pick. * @param random * the random number generator to use. * @param items * the items from which an element is to be randomly picked from. * @return a list of elements (possibly repeated) randomly selected from the * given array of items. */ public static ArrayList<Object> randomPick(int n, Random random, Object[] items) { ArrayList<Object> result = new ArrayList<Object>(n); for (int i = 0; i != n; i++) { result.add(randomPick(random, items)); } return result; } /** * Randomly picks an element of given list ({@link ArrayList}s will be most * efficient) using a given {@link Random} number generator. * * @param random * the random number generator to use. * @param items * the items from which an element is to be randomly picked from. * @return the randomly picked element from the given list of items. * @param <E> * the type of the elements. */ public static <E> E randomPick(Random random, List<E> items) { int index = random.nextInt(items.size()); E result = items.get(index); return result; } /** * Randomly picks <code>n</code> elements (possibly repeated) of given list * ({@link ArrayList}s will be most efficient) using a given {@link Random} * number generator. * * @param n * the number of items to randomly pick. * @param random * the random number generator to use. * @param items * the items from which an element is to be randomly picked from. * @return a list of elements (possibly repeated) randomly selected from the * given list of items. * @param <E> * the type of the elements. */ public static <E> List<E> randomPick(int n, Random random, List<E> items) { List<E> result = new ArrayList<E>(n); for (int i = 0; i != n; i++) { result.add(randomPick(random, items)); } return result; } /** * Determines whether all elements in collection are * {@link Object#equals(Object)}, including <code>null</code>. * * @param collection * the collection of elements to be tested. * @return true of all elements in the given collection are equal, including * null. * @param <E> * the type of the elements. */ public static <E> boolean allEqual(Collection<E> collection) { boolean result = true; Iterator<E> iterator = collection.iterator(); if (iterator.hasNext()) { E previous = iterator.next(); while (result && iterator.hasNext()) { E nextOne = iterator.next(); if (!equals(nextOne, previous)) { result = false; } } } return result; } public static <T> T pickElementInFirstCollectionButNotSecondAndNotEqualTo( Collection<T> collection1, Collection<T> collection2, T valueItMustBeDifferentFrom) { for (T value1 : collection1) { if (!value1.equals(valueItMustBeDifferentFrom) && !collection2.contains(value1)) { return value1; } } return null; } public static <T> Set<T> copySetWithoutThisElement( Collection<T> collection, T excludedElement) { Set<T> result; result = new LinkedHashSet<T>(collection); result.remove(excludedElement); return result; } /** * Pushes all elements of a collection into a stack and returns the size of * this collection. * * @param stack * the stack to have elements pushed onto. * @param toBePushed * the elements to be pushed onto the given stack. * @return the number of elements pushed onto the stack. * @param <E> * the type of the elements. */ public static <E> int pushAll(Stack<E> stack, Collection<E> toBePushed) { for (E element : toBePushed) { stack.push(element); } return toBePushed.size(); } /** * Pops n elements from stack. * * @param stack * the stack to be popped. * @param n * the number of elements to be popped from the stack. * @param <E> * the type of the elements. */ public static <E> void popAll(Stack<E> stack, int n) { for (int i = 0; i != n; i++) { stack.pop(); } } /** * Receives a collection of keys and returns a map from them to their * respective results from a given function. * * @param keys * the keys to be used as arguments to given function. * @param function * the function to apply to the given keys to generate * corresponding values. * @return a Map of the given keys with values generated from applying the * given function to the keys. * @param <K> * the type of the keys. * @param <V> * the type of the values. */ public static <K, V> Map<K, V> getFunctionMapForGivenKeys( Collection<K> keys, Function<K, V> function) { Map<K, V> result = new LinkedHashMap<K, V>(); for (K key : keys) { result.put(key, function.apply(key)); } return result; } /** * @return a {@link Collector} to a {@link LinkedList}. * @param <E> * the type of the elements the constructed linked list should * contain. */ public static <E> Collector<E, ?, LinkedList<E>> toLinkedList() { return Collectors.toCollection(() -> new LinkedList<E>()); } /** * @return a {@link Collector} to a {@link LinkedHashSet}. * @param <E> * the type of the elements the constructed linked hash set * should contain. */ public static <E> Collector<E, ?, LinkedHashSet<E>> toLinkedHashSet() { return Collectors.toCollection(() -> new LinkedHashSet<E>()); } /** * @return a {@link Collector} to a {@link LinkedHashSet} with given initial * capacity. * @param initialCapacity * the initial capacity of the instantiated {@link LinkedHashSet} * @param <E> * the type of the elements the constructed linked hash set * should contain. */ public static <E> Collector<E, ?, LinkedHashSet<E>> toLinkedHashSet(int initialCapacity) { return Collectors.toCollection(() -> new LinkedHashSet<E>(initialCapacity)); } /** * @return a {@link Collector} to an array list with given initial capacity. * @param initialCapacity * the initial capacity of the instantiated {@link ArrayList}. * @param <E> * the type of the elements the constructed array list should * contain. */ public static <E> Collector<E, ?, ArrayList<E>> toArrayList(int initialCapacity) { return Collectors.toCollection(() -> new ArrayList<E>(initialCapacity)); } /** * Attempts to cast an object to a given class, * and if that does not succeed, throws an error with a message generated from a template * following the format conventions of {@link String#format(String, Object...)}, * with formatting arguments being the object being cast, and the expected and actual received classes' simple names, * in this order. * @param clazz the class to be cast to * @param object the object to be cast * @param messageTemplate the message template from which an error message is generated * @return the cast object * @param <T1> object type * @param <T2> class type */ public static <T1, T2> T2 castOrThrowError(Class<T2> clazz, T1 object, String messageTemplate) { T2 result; try { result = clazz.cast(object); } catch (ClassCastException e) { String message = String.format(messageTemplate, object, clazz.getSimpleName(), object.getClass().getSimpleName()); throw new Error(message); } return result; } /** * Given two objects, returns a pair in which either the first element satisfies given predicate, or neither object does. * @param t1 * type 1 * @param t2 * type 2 * @param predicate * a predicate * @return a pair in which either the first element satisfies given predicate, or neither object does. * @param <T> the type of the pair's elements. */ public static <T> Pair<T, T> sortPairMakingFirstOneSatisfyPredicateIfPossible(T t1, T t2, Predicate<T> predicate) { if (predicate.apply(t1)) { return Pair.make(t1, t2); } else { return Pair.make(t2, t1); } } /** * A utility method throwing an error to indicate that a method used by a default implementation of another method * has not been overridden. * <p> * This is useful in the following situation. * Suppose a class Vehicle (superClassName) provides a default implementation for checkUp() (nameOfMethodWhoseDefaultImplementationUsesThisMethod) * that assumes the Vehicle has tires in the first place, * and uses an abstract method tiresType() (thisMethodsName). Since a lot of vehicles do use tires, such default implementation is very convenient. * However, we do not want to make life harder for people extending Vehicle to represent vehicles without tires (such as a class Boat (thisClassName)), * and forcing them to implement tiresType() with some dummy code would be ugly and distracting. * Besides, the developer may not notice that checkUp() assumes tires, and as a result may not override it (as they should since Boat violates that assumption). * In that case, the dummy code in tiresType() code will be invoked even though it should not. * <p> * The solution is to change tiresType() from abstract to an implemented method simply invoking this Error-throwing safeguard utility. * If the developer overrides checkUp(), as they should in the case of Boat, the fact that tiresType() is no longer an abstract method * will prevent the compiler from insisting on its unnecessary implementation. * If the developer does not override checkUp() (for example, while extending Vehicle to a class Car), * but forgets to override tiresType() (since it is not abstract anymore, the compiler will not complain), * then there will be an Error thrown at run-time by this utility safeguard method. * <p> * In other words, because tiresType() is "abstract" only as a result of using a default, optional implementation, * we make it not technically abstract and required in compile-time, but still "abstract" in a run-time sense of * an implementation being demanded in case it is actually needed. * * @param thisClassName * the name of the class * @param thisMethodsName * the method name * @param superClassName * the super class name * @param namesOfMethodsWhoseDefaultImplementationUsesThisMethod * names of methods whose default implementation uses this method * @throws Error if one occurs */ public static void throwSafeguardError( String thisClassName, String thisMethodsName, String superClassName, String... namesOfMethodsWhoseDefaultImplementationUsesThisMethod) throws Error { String oneOf = namesOfMethodsWhoseDefaultImplementationUsesThisMethod.length > 1? "one of " : ""; throw new Error( thisMethodsName + " is being invoked but has not been overridden by " + thisClassName + ". " + "It is probably being invoked by the default implementation of " + oneOf + join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " in " + superClassName + ", unless some other overriding method invokes it. " + "If the default implementation of " + join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " in " + superClassName + " is being used, " + thisMethodsName + " should be overridden," + " or if " + thisMethodsName + " does not make sense for " + thisClassName + " (because of some assumption made by the default implementation of " + join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " that does not hold in " + thisClassName + "), then a new implementation of " + join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " should override the default one;" + " if on the other hand the default implementation of " + join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " has been overridden, then its new version, or some other overriding method, is invoking " + thisMethodsName + ", which (typically) should not happen (because " + thisMethodsName + " conforms to the assumptions made by the default" + " implementation of " + join(namesOfMethodsWhoseDefaultImplementationUsesThisMethod) + " and the overriding of the latter indicates that those assumptions probably do not hold anymore."); } public static <T> PairOf<List<T>> collectToLists(List<T> collection, Predicate<T> predicate) { List<T> positive = new LinkedList<T>(); List<T> negative = new LinkedList<T>(); collect(collection, positive, predicate, negative); PairOf<List<T>> result = makePairOf(positive, negative); return result; } /** * Non-destructively replaces each element in collection by the elements of a list, if expander produces a non-null one when given the element, * returning the same List instance if no expansion is done. * @param list * a list * @param expander * an expander * @return if expansion occurred a new list with all the old elements plus the expansions, otherwise the input list. * @param <T> the type of the list's elements. */ public static <T> List<T> nonDestructivelyExpandElementsIfFunctionReturnsNonNullCollection(List<T> list, Function<T, Collection<T>> expander) { List<T> result = new LinkedList<T>(); boolean expansionOccurred = false; for (T element : list) { Collection<T> expansion = expander.apply(element); if (expansion == null) { result.add(element); } else { result.addAll(expansion); expansionOccurred = true; } } if ( ! expansionOccurred) { result = list; } return result; } public static final String MY_ASSERT_OFF = "com.sri.ai.util.myAssertOff"; // /** // * A java <code>assert</code> substitute that, unlike the standard one, is on by default and // * can be turned off by setting any value to property {@link #MY_ASSERT_OFF}. // * It throws an {@link AssertionError} with the given message. // * @param test // * result of the test // * @param message // * message to display if test failed. // */ // public static void myAssert(boolean test, String message) { // if ( ! test && System.getProperty(MY_ASSERT_OFF) == null) { // throw new AssertionError(message); // } // } // Commented out because it can have unsuspected performance impact even when testing is turned off. /** * Checks for a condition that needs to be true, or * throws an error with a given message. * This is similar to {@link #myAssert(boolean, NullaryFunction)}, * but is performed even if property {@link #MY_ASSERT_OFF} is not null, * since it is meant for errors that may occur due to * incorrect input by a user. * It throws an {@link Error} with the given message. * @param test * result of the test * @param message * message in thrown {@link Error}. */ public static void check(boolean test, NullaryFunction<String> message) { if ( ! test) { throw new Error(message.apply()); } } /** * Checks for a condition that needs to be true, or * throws an error with a given message. * This is similar to {@link #myAssert(NullaryFunction, NullaryFunction)}, * but is performed even if property {@link #MY_ASSERT_OFF} is not null, * since it is meant for errors that may occur due to * incorrect input by a user. * It throws an {@link Error} with the given message. * @param test * result of the test * @param message * message in thrown {@link Error}. */ public static void check(NullaryFunction<Boolean> test, NullaryFunction<String> message) { if (! test.apply()) { throw new Error(message.apply()); } } /** * A java <code>assert</code> substitute that, unlike the standard one, is on by default and * can be turned off by setting any value to property {@link #MY_ASSERT_OFF}. * It throws an {@link AssertionError} with the given message. * @param test * result of the test * @param message * message to display if test failed. */ public static void myAssert(boolean test, NullaryFunction<String> message) { if ( ! test && System.getProperty(MY_ASSERT_OFF) == null) { throw new AssertionError(message.apply()); } } /** * Similar to {@link #myAssert(boolean, NullaryFunction)}, but takes nullary functions * for the test and the error message, and only executes them if property {@link #MY_ASSERT_OFF} is null, * thus maximizing performance when it <i>isn't</i> null. * * @param test * result of the test * @param message * message to display if test failed. */ public static void myAssert(NullaryFunction<Boolean> test, NullaryFunction<String> message) { if (System.getProperty(MY_ASSERT_OFF) == null && ! test.apply()) { throw new AssertionError(message.apply()); } } // /** // * Similar to {@link #myAssert(boolean, String)}, but takes a nullary function // * for the test, and only executes it if property {@link #MY_ASSERT_OFF} is null, // * thus maximizing performance when it <code>isn't</code> null. // * // * @param test // * result of the test // * @param message // * message to display if test failed. // */ // public static void myAssert(NullaryFunction<Boolean> test, String message) { // if (System.getProperty(MY_ASSERT_OFF) == null && ! test.apply()) { // throw new AssertionError(message); // } // } // Commented out because it can have unsuspected performance impact even when testing is turned off. /** * Returns the entryIndex-th entry in a {@link LinkedHashMap}, * assuming there is such entry (throws an exception otherwise). * @param map * a map * @param entryIndex * an entry index * @return the entry at the given index * @param <K> the map's key type * @param <V> the map's value type */ public static <K, V> Map.Entry<K, V> getIthEntry(LinkedHashMap<K, V> map, int entryIndex) { Map.Entry<K, V> result; Iterator<Map.Entry<K, V>> iterator = map.entrySet().iterator(); for (int i = 0; i != entryIndex; i++) { iterator.next(); } result = iterator.next(); return result; } /** * Iterates given iterator till it has no more elements or it is past a given element (ignored if null), * detecting the passage through them with the identity comparison (==). * @param iterator * an iterator * @param element * an element * @param <T> the type of the elements. */ public static <T> void iterateTillPastElementByIdentity(Iterator<T> iterator, T element) { boolean elementRequirementSatisfied = element == null; while (iterator.hasNext() && (!elementRequirementSatisfied)) { T current = iterator.next(); elementRequirementSatisfied = elementRequirementSatisfied || current == element; } } /** * Iterates given iterator till it has no more elements or it is past both given elements (ignored if null), * detecting the passage through them with the identity comparison (==). * @param iterator * an iterator * @param element1 * an element * @param element2 * an element * @param <T> the type of the elements. */ public static <T> void iterateTillPastBothElementsByIdentity(Iterator<T> iterator, T element1, T element2) { boolean element1RequirementSatisfied = element1 == null; boolean element2RequirementSatisfied = element2 == null; while (iterator.hasNext() && (!element1RequirementSatisfied || !element2RequirementSatisfied)) { T current = iterator.next(); element1RequirementSatisfied = element1RequirementSatisfied || current == element1; element2RequirementSatisfied = element2RequirementSatisfied || current == element2; } } /** * Computes the rising factorial <code>start^(n)</code> defined as <code>start(start + 1)...(start + n - 1)</code>. * @param start the first number to be multiplied * @param n the number of numbers to multiply, starting and rising from <code>start</code> * @return the rising factorial <code>start^(n)</code> */ public static Rational risingFactorial(long start, long n) { // more efficient implementation that works with smaller numbers than just multiplying numbers in sequence. // there are more efficient ways of doing this, though. long i; if (n == 0) { return Rational.ONE; } else if (n <= 16) { Rational r = new Rational(start); for (i = start + 1; i < start + n; i++) { r = r.multiply(i); } return r; } i = n / 2; Rational result = risingFactorial(start, i).multiply(risingFactorial(start + i, n - i)); return result; } /** * Computes the falling factorial <code>(start)_n</code> defined as <code>start(start - 1)...(start - n + 1)</code>. * It does that by reducing the problem to a rising factorial ({@link #risingFactorial(long, long)}) * due to the equality <code>(start)_n = (start - n + 1)^(n)</code>. * @param start the first number to be multiplied * @param n the number of numbers to multiply, starting and decreasing from start * @return the falling factorial <code>(start)_n</code> */ public static Rational fallingFactorial(long start, long n) { Rational result = risingFactorial(start - n + 1, n); return result; } /** * Computes the factorial of <code>n</code>. * It does that by reducing the problem to a rising factorial ({@link #risingFactorial(long, long)}) * due to the equality <code>n! = 1^(n)</code>. * @param n the number whose factorial is returned * @return the factorial of n */ public static Rational factorial(long n) { Rational result = risingFactorial(1, n); return result; } /** * Computes the binomial coefficient <code>choose(n, k) = n! / ((n - k)! k!)</code>. * It does that by reducing the problem to a falling factorial ({@link #fallingFactorial(long, long)}) * and a factorial ({@link #factorial(long)}) * due to the equality <code>n! / ((n - k)! k!) = (n)_k / k!</code>. * @param n the number of elements * @param k the number of elements selected for the set * @return the binomial coefficient */ public static Rational binomialCoefficient(long n, long k) { Rational result = fallingFactorial(n, k).divide(factorial(k)); return result; } /** * Applies a function to the values of a map, returning a new map, * or the same map instance if the function has always returned the same value object instances. * @param map the map * @param function the function * @param <K> the type of keys * @param <V> the type of values * @return a new map with each value v replaced by function(v), or the same map if f(v) == v for all v. */ public static <K,V> Map<K,V> mapValuesNonDestructively(Map<K,V> map, Function<V,V> function) { Map<K,V> result = new LinkedHashMap<K,V>(); boolean instanceChange = false; for (Map.Entry<K,V> entry : map.entrySet()) { V value = entry.getValue(); V newValue = function.apply(value); if (newValue != value) { instanceChange = true; } result.put(entry.getKey(), newValue); } if (instanceChange) { return result; } else { return map; } } /** * Iterates over all elements in iterator's range and picks one with uniform probability. * * @param iterator the iterator * @param random a random number generator * @param <T> the type of elements * @return a uniformly sampled element from the iterator's range using the random number generator. */ public static <T> T pickUniformly(Iterator<T> iterator, Random random) { List<T> list = listFrom(iterator); T result = list.get(random.nextInt(list.size())); return result; } /** * Iterates over all elements in collection and picks one with uniform probability. * * @param collection the collection * @param random a random number generator * @param <T> the type of elements * @return a uniformly sampled element from the iterator's range using the random number generator. */ public static <T> T pickUniformly(Collection<T> collection, Random random) { return pickUniformly(collection.iterator(), random); } /** * Iterates over a random subset of another iterator's range, * by selecting whether each element in it belong to the subset or not * with 0.5 probability. * @param iterator iterator * @param random random generator * @param <T> the type * @return a random sub-set */ public static <T> Iterator<T> pickSubSet(Iterator<T> iterator, Random random) { return new EZIterator<T>() { @Override protected T calculateNext() { if (iterator.hasNext()) { T next = iterator.next(); return random.nextBoolean()? next : null; } return null; } }; } /** * Returns an array list with <code>k</code> elements out of the given list, without replacement. * This means that the returned list contains the elements of <code>k</code> unique positions * in the original list. * If the list contains unique elements, then so will the returned list, * but elements may be repeated if they appear more than once in the original list. * Naturally, <code>k</code> needs to be no greater than the list's size, or an assertion error will be thrown. * @param list list * @param k number of elements to pick * @param random random generator * @param <T> type of elements * @return a list of elements at <code>k</code> unique positions in the given list */ public static <T> ArrayList<T> pickKElementsWithoutReplacement(ArrayList<T> list, int k, Random random) { ArrayList<T> result; if (k == list.size()) { // unnecessary, but faster result = list; } else { myAssert(() -> k < list.size(), () -> "pickKElementsWithoutReplacement received k = " + k + " greater than list size " + list.size() + ". List is " + list); Set<Integer> alreadyPicked = set(); result = new ArrayList<T>(k); for (int i = 0; i != k; i++) { int j; do { j = random.nextInt(list.size()); } while (alreadyPicked.contains(j)); result.add(list.get(j)); alreadyPicked.add(j); } } return result; } /** * Returns an array list with up to <code>k</code> elements out of the given list * satisfying a given predicate, without replacement. * This means that the returned list contains the elements of <code>k</code> unique positions * in the original list. * If the list contains unique elements, then so will the returned list, * but elements may be repeated if they appear more than once in the original list. * The number of picked elements is the maximum of <code>k</code> * and the number of positions in the input list whose elements satisfy the predicate. * @param list the list of elements * @param k number of elements to pick * @param requirement requirement * @param random random generator * @param <T> type of elements * @return a list of up to <code>k</code> elements at unique positions in the given list (picked without replacement). */ public static <T> ArrayList<T> pickUpToKElementsWithoutReplacement(ArrayList<T> list, int k, Predicate<T> requirement, Random random) { ArrayList<T> result; Set<Integer> alreadyPicked = set(); result = new ArrayList<T>(k); for (int i = 0; i != k; i++) { int j; do { if (alreadyPicked.size() == list.size()) { return result; } do { j = random.nextInt(list.size()); } while (alreadyPicked.contains(j)); alreadyPicked.add(j); } while (!requirement.apply(list.get(j))); result.add(list.get(j)); } return result; } /** * Stores, in a given array list, up to <code>k</code> elements out of the input list * satisfying a given predicate, without replacement. * The number of elements collected is the maximum of <code>k</code> * and the number of positions in the input list whose elements satisfy the predicate. * @param list the list of elements * @param k number of elements to pick * @param requirement requirement * @param random random generator * @param destination the array list to store the results * @param <T> type of elements */ public static <T> void pickUpToKElementsWithoutReplacement(ArrayList<T> list, int k, Predicate<T> requirement, Random random, ArrayList<T> destination) { Set<Integer> alreadyPicked = set(); for (int i = 0; i != k; i++) { int j; do { if (alreadyPicked.size() == list.size()) { return; } do { j = random.nextInt(list.size()); } while (alreadyPicked.contains(j)); alreadyPicked.add(j); } while (!requirement.apply(list.get(j))); destination.add(list.get(j)); } } /** * Adapts an {@link Iterator} to an {@link Iterable} for use in enhanced for * loops. If {@link Iterable#iterator()} is invoked more than once, an * {@link IllegalStateException} is thrown. * @param iterator the iterator * @param <T> the type of elements * @return the iterable for iterator */ public static <T> Iterable<T> in(final Iterator<T> iterator) { assert iterator != null; class SingleUseIterable implements Iterable<T> { private boolean used = false; @Override public Iterator<T> iterator() { if (used) { throw new IllegalStateException("SingleUseIterable already invoked"); } used = true; return iterator; } } return new SingleUseIterable(); } /** * Same as {@link #union(Iterator)} applied to given collection's iterator. * @param maps the collection of maps * @param <K> the type of keys * @param <V> the type of values * @return a new map with all entries from all maps in a collection */ public static <K,V> Map<K,V> union(Collection<Map<K,V>> maps) { return union(maps.iterator()); } /** * Returns a new map with all entries from all maps in an iterator's range. * @param mapsIterator the maps iterator * @param <K> the type of keys * @param <V> the type of values * @return a new map with all entries from all maps in an iterator's range */ public static <K,V> Map<K,V> union(Iterator<Map<K,V>> mapsIterator) { return putAllFromAll(new LinkedHashMap<K,V>(), mapsIterator); } /** * Puts all entries from all maps in the range of an iterator to a given map. * @param map the map * @param mapsIterator the maps iterator * @param <K> the type of keys * @param <V> the type of values * @return the given map with all entries from all maps in interator's range */ public static <K,V> Map<K,V> putAllFromAll(Map<K,V> map, Iterator<Map<K,V>> mapsIterator) { for (Map<K,V> eachMap : in(mapsIterator)) { map.putAll(eachMap); } return map; } /** * Returns a map mapping keys to lists containing all the values to which those * keys map in all maps given as arguments. * @param maps the maps whose values we want to union * @param <K> the key type * @param <V> the value type * @return a a map mapping keys to lists containing all the values to which those * keys map in all maps given as arguments. */ public static <K,V> Map<K, LinkedList<V>> unionOfValues(Collection<Map<? extends K, ? extends V>> maps) { Map<K, LinkedList<V>> result = map(); for (Map<? extends K, ? extends V> map : maps) { for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) { LinkedList<V> listOfValues = Util.getOrMakeAndPut(result, entry.getKey(), () -> new LinkedList<V>()); listOfValues.add(entry.getValue()); } } return result; } /** * Returns a map mapping keys to lists containing all the values to which those * keys map in all maps given as arguments. * @param maps the iterator over maps whose values we want to union * @param <K> the key type * @param <V> the value type * @return a a map mapping keys to lists containing all the values to which those * keys map in all maps given as arguments. */ public static <K,V> Map<K, LinkedList<V>> mapWithValuesEqualToListOfValuesOfTheseMapsUnderSameKey(Iterator<Map<? extends K, ? extends V>> maps) { Map<K, LinkedList<V>> result = map(); for (Map<? extends K, ? extends V> map : in(maps)) { for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) { LinkedList<V> listOfValues = Util.getOrMakeAndPut(result, entry.getKey(), () -> new LinkedList<V>()); listOfValues.add(entry.getValue()); } } return result; } /** * Creates an array list of size n, filled with a given value. * @param n the size of the array * @param value the value to fill the array with * @param <T> the type of value * @return an array list of size n, filled with a given value. */ public static <T> ArrayList<T> fill(int n, T value) { ArrayList<T> result = new ArrayList<T>(n); for (int i = 0; i != n; i++) { result.add(value); } return result; } /** * Given an array list and a list of integers, returns an array list with the indexed elements in the indices order. * @param array the array from which to extract sub array. * @param indices the array of indices * @param <E> the type of values * @return array list with the indexed elements in the indices order. */ public static <E> ArrayList<E> makeCopyWithGivenIndices(ArrayList<E> array, List<Integer> indices) { ArrayList<E> result = new ArrayList<E>(indices.size()); for (int i = 0; i != indices.size(); i++) { Integer ithIndex = indices.get(i); E elementAtIthIndex = array.get(ithIndex); result.add(elementAtIthIndex); } return result; } /** * Stores the elements from an iterable of iterables in an array list of array lists. * @param iterableOfIterables iterable of iterables * @return array of arrays * @param <T> type */ public static <T> ArrayList<ArrayList<T>> storeIterableOfIterablesInArrayListOfArrayLists(Iterable<Iterable<T>> iterableOfIterables) { ArrayList<ArrayList<T>> result; result = arrayList(); for (Iterable<T> iterable : iterableOfIterables) { ArrayList<T> innerArrayList = arrayList(); for (T element : iterable) { innerArrayList.add(element); } result.add(innerArrayList); } return result; } /** * Put given value in a list indexed by key, creating a new linked list if the map still does not contain the key. * @param mapToLists map to lists * @param key a key * @param value a value * @param <K> key type * @param <V> value type */ public static <K,V> void putInListValue(Map<K, List<V>> mapToLists, K key, V value) { List<V> list; if (mapToLists.containsKey(key)) { list = mapToLists.get(key); } else { list = new LinkedList<V>(); mapToLists.put(key, list); } list.add(value); } /** * Allocates an array list of given size filled with given value. * @param value a value * @param size size of list * @param <T> type of elements * @return an array list of given size with all elements equal to given value */ public static <T> ArrayList<T> arrayListFilledWith(T value, int size) { ArrayList<T> result = new ArrayList<>(size); for (int i = 0; i != size; i++) { result.add(value); } return result; } /** * If there is more than one element in iterator's range and they are all equal to the first one, * returns the first one; * otherwise, returns null. * @param elements * @return */ public static <T> T ifAllTheSameOrNull(Iterator<T> elements) { if (elements.hasNext()) { T candidate = elements.next(); while (elements.hasNext()) { T next = elements.next(); if (! next.equals(candidate)) { return null; } } return candidate; } else { return null; } } }