temper.core.Core Maven / Gradle / Ivy
Show all versions of temper-core Show documentation
package temper.core;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.PrimitiveIterator;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleFunction;
import java.util.function.DoublePredicate;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleUnaryOperator;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntBiFunction;
import java.util.function.ToIntFunction;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.Math.copySign;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
import static java.util.Objects.requireNonNull;
/**
* A support class for the temper core libraries.
*/
public final class Core {
private Core() {
}
/** Do nothing with a value. */
public static void doNothing(Object val) {}
/**
* @param klass the class literal to cast to
* @param value the value to cast
* @return the value cast to the new type
* @param the governing type
*/
public static T cast(Class extends T> klass, Object value) {
// TODO Inline?
return klass.cast(value);
}
/**
* Casts but throws [{@link NullPointerException}] if value is null.
* @param klass the class literal to cast to
* @param value the value to cast
* @return the value cast to the new type
* @param the governing type
*/
public static T castToNonNull(Class extends T> klass, Object value) {
if (value == null) {
throw new NullPointerException();
}
return klass.cast(value);
}
/**
* Checked cast from Temper *StringIndexOption* to Temper *NoStringIndex*
* @return -1, the representation of Temper *StringIndex.none*.
*/
public static int requireNoStringIndex(int i) {
if (i < 0) { return -1; }
throw new IllegalArgumentException("Required NoStringIndex but got " + i);
}
/**
* Checked cast from Temper *StringIndexOption* to Temper *StringIndex*
* @return A valid string index, >= 0
*/
public static int requireStringIndex(int i) {
if (i >= 0) { return i; }
throw new IllegalArgumentException("Required StringIndex but got " + i);
}
/**
* A simple print command.
* @param text the text to print.
*/
public static void print(String text) {
System.out.println(text);
}
/** A visible interface for the console. */
public interface Console {
/**
* Log a message to the console.
* @param message Has to be a String for now, but typing info sometimes requires Object, but we likely want to
* support general Object values in the future at some point, anyway, so eh?
*/
void log(String message);
}
/** A pseudo-global console associated with a logger. */
public static final class GlobalConsole implements Console {
private final Logger logger;
public GlobalConsole(Logger logger) {
this.logger = logger;
}
/** 0 is getStackTrace, 1 is this log helper, and 2 is our caller, which we want. */
private static final int CALLER_FRAME_INDEX = 2;
@Override
public void log(String message) {
if (logger.isLoggable(Level.INFO)) {
// If left null, these aren't included by Java-builtin formatters.
String sourceClass = null;
String sourceMethod = null;
try {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
if (trace.length > CALLER_FRAME_INDEX) {
// Alternatively, pre-configure property jdk.logger.packages,
// but that's officially nonstandard and subject to change.
StackTraceElement frame = trace[CALLER_FRAME_INDEX];
sourceClass = frame.getClassName();
sourceMethod = frame.getMethodName();
}
} catch (SecurityException ignore) {
// Ignore.
}
logger.logp(Level.INFO, sourceClass, sourceMethod, message);
}
}
}
/**
* Configure java.util.logging to log simple messages directly to System.out.
* Designed for simple test situations, not robust usage.
*/
public static void initSimpleLogging() {
Logger root = Logger.getLogger("");
// We get an array from getHandlers, so the loop should be fine.
for (Handler handler : root.getHandlers()) {
root.removeHandler(handler);
}
Formatter formatter = new Formatter() {
@Override
public String format(LogRecord record) {
return record.getMessage() + "\n";
}
};
root.addHandler(new StreamHandler(System.out, formatter));
}
/**
* Create a pseudo-global console for a given logger.
* @param logger the Logger instance to use
*/
public static GlobalConsole getConsole(Logger logger) {
return new GlobalConsole(logger);
}
/**
* Integer division, rethrowing.
* @param left the numerator
* @param right the denominator
* @return the quotient
*/
public static int divIntInt(int left, int right) {
if (right == 0) {
throw bubble();
}
return left / right;
}
/**
* Integer modulo, rethrowing.
* @param left the numerator
* @param right the denominator
* @return the quotient
*/
public static int modIntInt(int left, int right) {
if (right == 0) {
throw bubble();
}
return left % right;
}
/**
* Generic comparison; assumes elements implements Comparable.
*
* @param left an instance of Comparable
* @param right an instance of Comparable
* @return the result of comparing per the standard Comparator contract.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static int genericCmp(Object left, Object right) {
if (left == null) {
return -1;
} else if (right == null) {
return 1;
} else {
return ((Comparable) left).compareTo(right);
}
}
/**
* Obtain or create an exception that can be thrown for Temper bubbling.
*
* This must be `throw`n by the caller, to help the compiler with flow analysis.
*
*/
public static RuntimeException bubble() {
return new RuntimeException();
}
/**
* Throws an exception for Temper bubbling.
*
* @param an arbitrary type; allows this expression to effectively return bottom
*/
public static T throwBubble() {
throw bubble();
}
/** Convenience for throwing assertion errors as an expression. */
public static T throwAssertionError(String message) { throw new AssertionError(message); }
private static final Pattern floatExponent = Pattern.compile("E([+-]?)");
/**
* @param x the value to compare
* @param y the value to compare with
* @return whether the values are within tolerances
*/
public static boolean float64Near(double x, double y) {
return float64Near(x, y, null, null);
}
/**
* @param x the value to compare
* @param y the value to compare with
* @param relTol the tolerance relative to the max of x and y
* @return whether the values are within tolerances
*/
public static boolean float64Near(double x, double y, Double relTol) {
return float64Near(x, y, relTol, null);
}
/**
* @param x the value to compare
* @param y the value to compare with
* @param relTol the tolerance relative to the max of x and y
* @param absTol the absolute tolerance allowed if outside relTol
* @return whether the values are within tolerances
*/
public static boolean float64Near(double x, double y, Double relTol, Double absTol) {
double rel = relTol == null ? 1e-9 : relTol;
double abs = absTol == null ? 0.0 : absTol;
double margin = Math.max(Math.max(Math.abs(x), Math.abs(y)) * rel, abs);
return Math.abs(x - y) < margin;
}
/**
* @param n the value to convert to an int
* @throws RuntimeException if the result can't be expressed with less than an error of 1
* @return the value as an int
*/
public static int float64ToInt(double n) {
// Use double 1.0 here for immediate promotion.
if (n > Integer.MIN_VALUE - 1.0 && n < Integer.MAX_VALUE + 1.0) {
return (int) n;
} else {
// NaN should also end up here due to false comparison above.
throw bubble();
}
}
/**
* Implements connected method {@code Float64::toString}.
* TODO It might be possible to do this more succinctly with DecimalFormat.
*/
public static String float64ToString(double n) {
if (n == 0.0) {
if (copySign(1.0d, n) > 0.0) {
return "0.0";
} else {
return "-0.0";
}
} else {
String d = Double.toString(n);
Matcher m = floatExponent.matcher(d);
// Matcher.replaceFirst is 9+
if (m.find()) {
String sign = m.group(1);
if (sign.isEmpty()) {
sign = "+";
}
return d.substring(0, m.start()) + "e" + sign + d.substring(m.end());
} else {
return d;
}
}
}
public static String stringFromCodePoint(int codePoint) {
return new String(Character.toChars(codePoint));
}
public static String stringFromCodePoints(List codePoints) {
StringBuilder builder = new StringBuilder();
for (int codePoint : codePoints) {
builder.appendCodePoint(codePoint);
}
return builder.toString();
}
public static int stringCountBetween(String s, int begin, int end) {
int length = s.length();
begin = Math.min(begin, length);
end = Math.max(begin, Math.min(end, length));
int count = 0;
for (int i = begin; i < end;) {
int cp = s.codePointAt(i);
count += 1;
i += Character.charCount(cp);
}
return count;
}
public static boolean stringHasAtLeast(String s, int begin, int end, int minCount) {
int length = s.length();
begin = Math.min(begin, length);
end = Math.max(begin, Math.min(end, length));
int nUtf16 = end - begin;
if (nUtf16 < minCount) { return false; }
if (nUtf16 >= minCount * 2) { return true; }
// Fall back to an early-outing version of countBetween.
int count = 0;
for (int i = begin; i < end;) {
int cp = s.codePointAt(i);
count += 1;
if (count >= minCount) { return true; }
i += Character.charCount(cp);
}
return count >= minCount;
}
public static boolean stringHasIndex(String s, int i) {
return i < s.length();
}
public static int stringNext(String s, int i) {
int length = s.length();
if (i >= length) { return length; }
return i + Character.charCount(s.codePointAt(i));
}
public static int stringPrev(String s, int i) {
int length = s.length();
if (i <= 1) { return 0; } // Can't be a surrogate pair before.
if (i > length) { return length; }
int cp = s.codePointAt(i - 2);
return (cp >= 0x1_0000) ? i - 2 : i - 1;
}
public static void stringForEach(String s, IntConsumer f) {
for (int i = 0, length = s.length(); i < length;) {
int cp = s.codePointAt(i);
f.accept(cp);
i += Character.charCount(cp);
}
}
public static void stringBuilderAppendBetween(StringBuilder sb, String s, int begin, int end) {
int length = s.length();
begin = Math.min(begin, length);
end = Math.max(begin, Math.min(end, length));
sb.append(s, begin, end);
}
public static String stringSlice(String s, int begin, int end) {
int length = s.length();
begin = Math.min(begin, length);
end = Math.max(begin, Math.min(end, length));
return s.substring(begin, end);
}
/**
* Split a string over a delimiter.
* @param source a well-formed string
* @param delimiter a well-formed delimiter
* @return an immutable list of strings
*/
public static List stringSplit(String source, String delimiter) {
int sourceLen = source.length();
int delimLen = delimiter.length();
if (delimLen == 0) {
ArrayList result = new ArrayList<>(source.length());
int i = 0;
while (i < sourceLen) {
int j = i + Character.charCount(source.codePointAt(i));
result.add(source.substring(i, j));
i = j;
}
result.trimToSize();
return listCopyOfTrusted(result);
}
int count = 1; // Include the substring trailing the last delimiter.
int index = 0;
int nextDelim;
while((nextDelim = source.indexOf(delimiter, index)) >= 0) {
count ++;
index = nextDelim + delimLen;
}
ArrayList result = new ArrayList<>(count);
index = 0;
while((nextDelim = source.indexOf(delimiter, index)) >= 0) {
result.add(source.substring(index, nextDelim));
index = nextDelim + delimLen;
}
result.add(source.substring(index));
result.trimToSize();
return listCopyOfTrusted(result);
}
public static double stringToFloat64(String s) {
String trimmed = s.trim();
if (trimmed.startsWith(".") || trimmed.endsWith(".")) {
throw bubble();
}
return Double.parseDouble(s);
}
public static int stringToInt(String s) {
return stringToInt(s, 10);
}
public static int stringToInt(String s, int radix) {
return Integer.parseInt(s.trim(), radix);
}
/**
* Emulates List.of() in Java 9+.
* @return an empty immutable list.
* @param the element type
*/
public static List listOf() {
return emptyList();
}
/**
* Emulates List.of() in Java 9+.
* @return a singleton immutable list
* @param the element type
*/
public static List listOf(E elem) {
return singletonList(elem);
}
/**
* Emulates List.of() in Java 9+.
* @return an immutable list
* @param the element type
*/
@SafeVarargs
public static List listOf(E ... elem) {
return listCopyOfTrusted(Arrays.asList(elem));
}
/**
* Emulates List.copyOf() in Java 9+.
* @return an immutable list
* @param the element type
*/
public static List listCopyOf(Collection elems) {
return listCopyOfTrusted(new ArrayList<>(elems));
}
/**
* @param elems a trusted list that won't be modified
* @return an immutable list
* @param the element type
*/
private static List listCopyOfTrusted(List elems) {
switch(elems.size()) {
case 0:
return emptyList();
case 1:
return singletonList(elems.iterator().next());
default:
return unmodifiableList(elems);
}
}
/**
* @param target a ListBuilder instance
* @param elem the element to add
* @param the element type
*/
public static void listAdd(List target, E elem) {
target.add(elem);
}
/**
* @param target a ListBuilder instance
* @param elem the element to add
* @param at where to insert the element
* @param the element type
*/
public static void listAdd(List target, E elem, int at) {
// TODO Inline?
target.add(at, elem);
}
/**
* @param target a ListBuilder instance
* @param source the source of the elements to add
* @param the element type
*/
public static void listAddAll(List target, Collection extends E> source) {
target.addAll(source);
}
/**
* @param target a ListBuilder instance
* @param source the source of the elements to add
* @param at where to insert the elements
* @param the element type
*/
public static void listAddAll(List target, Collection extends E> source, int at) {
// TODO Inline?
target.addAll(at, source);
}
/**
* @param target a ListBuilder instance
* @return the removed element
* @param the element type
*/
public static E listRemoveLast(List target) {
// TODO Inline?
return target.remove(target.size() - 1);
}
/**
* @param target a ListBuilder instance
* @param the element type
*/
public static void listSort(List target, ToIntBiFunction compare) {
target.sort((a, b) -> compare.applyAsInt(a, b));
}
/**
* @param target a Listed instance
* @return the sorted list
* @param the element type
*/
public static List listSorted(List target, ToIntBiFunction compare) {
List result = new ArrayList<>(target);
listSort(result, compare);
return listCopyOfTrusted(result);
}
/**
* @param target a ListBuilder instance
* @return the removed list
* @param the element type
*/
public static List listSplice(List target) {
return listSplice(target, null, null, null);
}
/**
* @param target a ListBuilder instance
* @param index where to start removing from, defaulting to 0
* @return the removed list
* @param the element type
*/
public static List listSplice(List target, Integer index) {
return listSplice(target, index, null, null);
}
/**
* @param target a ListBuilder instance
* @param index where to start removing from, defaulting to 0
* @param removeCount how many to remove from, defaulting to all after index
* @return the removed list
* @param the element type
*/
public static List listSplice(List target, Integer index, Integer removeCount) {
return listSplice(target, index, removeCount, null);
}
/**
* @param target a ListBuilder instance
* @param index where to start removing from, defaulting to 0
* @param removeCount how many to remove from, defaulting to all after index
* @param newElems the elements to put in place of removed elements, defaulting to none
* @return the removed elements as an immutable list
* @param the element type
*/
public static List listSplice(List target, Integer index, Integer removeCount, List newElems) {
int size = target.size();
int sliceStart = index != null ? clamp(index, 0, size) : 0;
int removeClamped = removeCount != null ? clamp(removeCount, 0, size) : size;
int sliceEnd = Math.min(sliceStart + removeClamped, size);
List slice = target.subList(sliceStart, sliceEnd);
List result = listCopyOf(slice);
slice.clear();
if (newElems != null) {
slice.addAll(newElems);
}
return result;
}
/**
* Implements {@code List::filter}.
*
* @param source read once for its contents
* @param predicate result has values for which this returns true
* @return the filtered list
* @param the element type
*/
public static List listFilterObj(List source, Predicate predicate) {
ArrayList result = new ArrayList<>(source.size());
for (E elem : source) {
if (predicate.test(elem)) {
result.add(elem);
}
}
result.trimToSize();
return listCopyOfTrusted(result);
}
/**
* Implements {@code List::filter}.
*
* @param source read once for its contents
* @param predicate result has values for which this returns true
* @return the filtered list
*/
public static List listFilterBool(List source, Predicate predicate) {
ArrayList result = new ArrayList<>(source.size());
for (Boolean elem : source) {
if (predicate.test(elem)) {
result.add(elem);
}
}
result.trimToSize();
return listCopyOfTrusted(result);
}
/**
* Implements {@code List::filter}.
*
* @param source read once for its contents
* @param predicate result has values for which this returns true
* @return the filtered list
*/
public static List listFilterInt(List source, IntPredicate predicate) {
ArrayList result = new ArrayList<>(source.size());
for (int elem : source) {
if (predicate.test(elem)) {
result.add(elem);
}
}
result.trimToSize();
return listCopyOfTrusted(result);
}
/**
* Implements {@code List::filter}.
*
* @param source read once for its contents
* @param predicate result has values for which this returns true
* @return the filtered list
*/
public static List listFilterDouble(List source, DoublePredicate predicate) {
ArrayList result = new ArrayList<>(source.size());
for (double elem : source) {
if (predicate.test(elem)) {
result.add(elem);
}
}
result.trimToSize();
return listCopyOfTrusted(result);
}
/**
* @param source accessed randomly for the element
* @param index the index to the element
* @return the element, possibly throwing a RuntimeException if OOB
* @param the element type
*/
public static E listGet(List source, int index) {
// TODO Inline?
return source.get(index);
}
/**
* @param source accessed randomly for the element
* @param index the index to the element
* @param defaultValue a fallback value if the index is out of bounds
* @return the element or defaultValue
* @param the element type
*/
public static E listGetOr(List source, int index, E defaultValue) {
if (index < 0 || index >= source.size()) {
return defaultValue;
}
return source.get(index);
}
/**
* Implements {@code List::join}.
*
* @param source read once for its contents
* @param delimiter the delimiter inserted between values
* @param function a function to convert source values to strings
* @return the combined string
* @param the source element type
*/
public static String listJoinObj(List source, String delimiter, Function function) {
StringBuilder sb = new StringBuilder();
String before = "";
for (E elem : source) {
sb.append(before);
sb.append(function.apply(elem));
before = delimiter;
}
return sb.toString();
}
/**
* Implements {@code List::join}.
*
* @param source read once for its contents
* @param delimiter the delimiter inserted between values
* @param function a function to convert source values to strings
* @return the combined string
*/
public static String listJoinBool(List source, String delimiter, Function function) {
StringBuilder sb = new StringBuilder();
String before = "";
for (Boolean elem : source) {
sb.append(before);
sb.append(function.apply(elem));
before = delimiter;
}
return sb.toString();
}
/**
* Implements {@code List::join}.
*
* @param source read once for its contents
* @param delimiter the delimiter inserted between values
* @param function a function to convert source values to strings
* @return the combined string
*/
public static String listJoinInt(List source, String delimiter, IntFunction function) {
StringBuilder sb = new StringBuilder();
String before = "";
for (int elem : source) {
sb.append(before);
sb.append(function.apply(elem));
before = delimiter;
}
return sb.toString();
}
/**
* Implements {@code List::join}.
*
* @param source read once for its contents
* @param delimiter the delimiter inserted between values
* @param function a function to convert source values to strings
* @return the combined string
*/
public static String listJoinDouble(List source, String delimiter, DoubleFunction function) {
StringBuilder sb = new StringBuilder();
String before = "";
for (double elem : source) {
sb.append(before);
sb.append(function.apply(elem));
before = delimiter;
}
return sb.toString();
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the source element type
* @param the result element type
*/
public static List listMapObjToObj(List source, Function function) {
List result = new ArrayList<>(source.size());
for (E elem : source) {
result.add(function.apply(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the result element type
*/
public static List listMapIntToObj(List source, IntFunction function) {
List result = new ArrayList<>(source.size());
for (int elem : source) {
result.add(function.apply(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDoubleToObj(List source, DoubleFunction function) {
List result = new ArrayList<>(source.size());
for (double elem : source) {
result.add(function.apply(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the source element type
*/
public static List listMapObjToBool(List source, Predicate function) {
List result = new ArrayList<>(source.size());
for (E elem : source) {
result.add(function.test(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapIntToBool(List source, IntPredicate function) {
List result = new ArrayList<>(source.size());
for (int elem : source) {
result.add(function.test(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDoubleToBool(List source, DoublePredicate function) {
List result = new ArrayList<>(source.size());
for (double elem : source) {
result.add(function.test(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the source element type
*/
public static List listMapObjToInt(List source, ToIntFunction function) {
List result = new ArrayList<>(source.size());
for (E elem : source) {
result.add(function.applyAsInt(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapIntToInt(List source, IntUnaryOperator function) {
List result = new ArrayList<>(source.size());
for (int elem : source) {
result.add(function.applyAsInt(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDoubleToInt(List source, DoubleToIntFunction function) {
List result = new ArrayList<>(source.size());
for (double elem : source) {
result.add(function.applyAsInt(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the source element type
*/
public static List listMapObjToDouble(List source, ToDoubleFunction function) {
List result = new ArrayList<>(source.size());
for (E elem : source) {
result.add(function.applyAsDouble(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapIntToDouble(List source, IntToDoubleFunction function) {
List result = new ArrayList<>(source.size());
for (int elem : source) {
result.add(function.applyAsDouble(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::map}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDoubleToDouble(List source, DoubleUnaryOperator function) {
List result = new ArrayList<>(source.size());
for (double elem : source) {
result.add(function.applyAsDouble(elem));
}
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the source element type
* @param the result element type
*/
public static List listMapDroppingObjToObj(List source, Function function) {
ArrayList result = new ArrayList<>(source.size());
for (E elem : source) {
F mapped;
try {
mapped = function.apply(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the result element type
*/
public static List listMapDroppingIntToObj(List source, IntFunction function) {
ArrayList result = new ArrayList<>(source.size());
for (int elem : source) {
F mapped;
try {
mapped = function.apply(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the result element type
*/
public static List listMapDroppingDoubleToObj(List source, DoubleFunction function) {
ArrayList result = new ArrayList<>(source.size());
for (double elem : source) {
F mapped;
try {
mapped = function.apply(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the source element type
*/
public static List listMapDroppingObjToBool(List source, Predicate function) {
ArrayList result = new ArrayList<>(source.size());
for (E elem : source) {
Boolean mapped;
try {
mapped = function.test(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDroppingIntToBool(List source, IntPredicate function) {
ArrayList result = new ArrayList<>(source.size());
for (int elem : source) {
Boolean mapped;
try {
mapped = function.test(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDroppingDoubleToBool(List source, DoublePredicate function) {
ArrayList result = new ArrayList<>(source.size());
for (double elem : source) {
Boolean mapped;
try {
mapped = function.test(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the source element type
*/
public static List listMapDroppingObjToInt(List source, ToIntFunction function) {
ArrayList result = new ArrayList<>(source.size());
for (E elem : source) {
int mapped;
try {
mapped = function.applyAsInt(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDroppingIntToInt(List source, IntUnaryOperator function) {
ArrayList result = new ArrayList<>(source.size());
for (int elem : source) {
int mapped;
try {
mapped = function.applyAsInt(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDroppingDoubleToInt(List source, DoubleToIntFunction function) {
ArrayList result = new ArrayList<>(source.size());
for (double elem : source) {
int mapped;
try {
mapped = function.applyAsInt(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
* @param the source element type
*/
public static List listMapDroppingObjToDouble(List source, ToDoubleFunction function) {
ArrayList result = new ArrayList<>(source.size());
for (E elem : source) {
double mapped;
try {
mapped = function.applyAsDouble(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDroppingIntToDouble(List source, IntToDoubleFunction function) {
ArrayList result = new ArrayList<>(source.size());
for (int elem : source) {
double mapped;
try {
mapped = function.applyAsDouble(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
/**
* Implements {@code Listed::mapDropping}.
*
* @param source read once for its contents
* @param function converts source values to result values
* @return the remapped list, with the same length
*/
public static List listMapDroppingDoubleToDouble(List source, DoubleUnaryOperator function) {
ArrayList result = new ArrayList<>(source.size());
for (double elem : source) {
double mapped;
try {
mapped = function.applyAsDouble(elem);
} catch(RuntimeException ignored) {
continue;
}
result.add(mapped);
}
result.trimToSize();
return unmodifiableList(result);
}
public interface BooleanBiPredicate {
boolean test(boolean left, boolean right);
}
/** Implements {@code Listed::reduce}.
*/
public static boolean listedReduceBool(List source, BooleanBiPredicate reducer) {
return listedReduceBoolToBool(source, source.get(0), 1, (reduction, item) -> reducer.test(reduction, item));
}
/** Implements {@code Listed::reduceFrom}.
*/
public static boolean listedReduceBoolToBool(List source, boolean initial, BooleanBiPredicate reducer) {
return listedReduceBoolToBool(source, initial, 0, reducer);
}
static boolean listedReduceBoolToBool(List source, boolean initial, int index, BooleanBiPredicate reducer) {
boolean result = initial;
for (int i = index; i < source.size(); i += 1) {
result = reducer.test(result, source.get(i));
}
return result;
}
/** Implements {@code Listed::reduce}.
*/
public static double listedReduceDouble(List source, DoubleBinaryOperator reducer) {
return listedReduceDoubleToDouble(source, source.get(0), 1, (reduction, item) -> reducer.applyAsDouble(reduction, item));
}
/** Implements {@code Listed::reduceFrom}.
*/
public static double listedReduceDoubleToDouble(List source, double initial, DoubleBinaryOperator reducer) {
return listedReduceDoubleToDouble(source, initial, 0, reducer);
}
static double listedReduceDoubleToDouble(List source, double initial, int index, DoubleBinaryOperator reducer) {
double result = initial;
for (int i = index; i < source.size(); i += 1) {
result = reducer.applyAsDouble(result, source.get(i));
}
return result;
}
/** Implements {@code Listed::reduce}.
*/
public static int listedReduceInt(List source, IntBinaryOperator reducer) {
return listedReduceIntToInt(source, source.get(0), 1, (reduction, item) -> reducer.applyAsInt(reduction, item));
}
/** Implements {@code Listed::reduceFrom}.
*/
public static int listedReduceIntToInt(List source, int initial, IntBinaryOperator reducer) {
return listedReduceIntToInt(source, initial, 0, reducer);
}
static int listedReduceIntToInt(List source, int initial, int index, IntBinaryOperator reducer) {
int result = initial;
for (int i = index; i < source.size(); i += 1) {
result = reducer.applyAsInt(result, source.get(i));
}
return result;
}
/** Implements {@code Listed::reduce}.
*/
public static R listedReduceObj(List source, BinaryOperator reducer) {
return listedReduceObjToObj(source, source.get(0), 1, (reduction, item) -> reducer.apply(reduction, item));
}
/** Implements {@code Listed::reduceFrom}.
*/
public static R listedReduceObjToObj(List source, R initial, BinaryOperator reducer) {
return listedReduceObjToObj(source, initial, 0, reducer);
}
static R listedReduceObjToObj(List source, R initial, int index, BinaryOperator reducer) {
R result = initial;
for (int i = index; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface BoolToDoubleReducer {
double apply(double reduction, boolean element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static double listedReduceBoolToDouble(List source, double initial, BoolToDoubleReducer reducer) {
double result = initial;
for (int i = 0; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface BoolToIntReducer {
int apply(int reduction, boolean element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static int listedReduceBoolToInt(List source, int initial, BoolToIntReducer reducer) {
int result = initial;
for (int i = 0; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface BoolToObjReducer {
R apply(R reduction, boolean element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static R listedReduceBoolToObj(List source, R initial, BoolToObjReducer reducer) {
R result = initial;
for (int i = 0; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface DoubleToBoolReducer {
boolean apply(boolean reduction, double element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static boolean listedReduceDoubleToBool(List source, boolean initial, DoubleToBoolReducer reducer) {
boolean result = initial;
for (int i = 0; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface DoubleToIntReducer {
int apply(int reduction, double element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static int listedReduceDoubleToInt(List source, int initial, DoubleToIntReducer reducer) {
int result = initial;
for (int i = 0; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface DoubleToObjReducer {
R apply(R reduction, double element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static R listedReduceDoubleToObj(List source, R initial, DoubleToObjReducer reducer) {
R result = initial;
for (int i = 0; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface IntToBoolReducer {
boolean apply(boolean reduction, int element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static boolean listedReduceIntToBool(List source, boolean initial, IntToBoolReducer reducer) {
boolean result = initial;
for (int i = 0; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface IntToDoubleReducer {
double apply(double reduction, int element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static double listedReduceIntToDouble(List source, double initial, IntToDoubleReducer reducer) {
double result = initial;
for (int i = 0; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface IntToObjReducer {
R apply(R reduction, int element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static R listedReduceIntToObj(List source, R initial, IntToObjReducer reducer) {
R result = initial;
for (int i = 0; i < source.size(); i += 1) {
result = reducer.apply(result, source.get(i));
}
return result;
}
public interface ObjToBoolReducer {
boolean apply(boolean reduction, R element);
}
/** Implements {@code Listed::reduceFrom}.
*/
public static boolean listedReduceObjToBool(List