All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.landawn.abacus.util.Fn Maven / Gradle / Ivy

/*
 * Copyright (c) 2017, Haiyang Li.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.landawn.abacus.util;

import java.util.AbstractMap;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;

import com.landawn.abacus.util.Tuple.Tuple2;
import com.landawn.abacus.util.Tuple.Tuple3;
import com.landawn.abacus.util.function.BiConsumer;
import com.landawn.abacus.util.function.BiFunction;
import com.landawn.abacus.util.function.BiPredicate;
import com.landawn.abacus.util.function.BinaryOperator;
import com.landawn.abacus.util.function.Consumer;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.IndexedBiConsumer;
import com.landawn.abacus.util.function.IndexedBiFunction;
import com.landawn.abacus.util.function.IndexedBiPredicate;
import com.landawn.abacus.util.function.IndexedConsumer;
import com.landawn.abacus.util.function.IndexedFunction;
import com.landawn.abacus.util.function.IndexedPredicate;
import com.landawn.abacus.util.function.IntFunction;
import com.landawn.abacus.util.function.Predicate;
import com.landawn.abacus.util.function.Supplier;
import com.landawn.abacus.util.function.ToByteFunction;
import com.landawn.abacus.util.function.ToCharFunction;
import com.landawn.abacus.util.function.ToDoubleFunction;
import com.landawn.abacus.util.function.ToFloatFunction;
import com.landawn.abacus.util.function.ToIntFunction;
import com.landawn.abacus.util.function.ToLongFunction;
import com.landawn.abacus.util.function.ToShortFunction;
import com.landawn.abacus.util.function.TriConsumer;
import com.landawn.abacus.util.function.TriFunction;
import com.landawn.abacus.util.function.TriPredicate;
import com.landawn.abacus.util.function.UnaryOperator;
import com.landawn.abacus.util.stream.Collector;
import com.landawn.abacus.util.stream.Collectors;

/**
 * Factory utility class for functional interfaces.
 * 
 * 
 * 
 * 
 * Map map = N.asMap("a", 1, "b", 2, "c", 3);
 * // Instead of
 * Stream.of(map).filter(e -> e.getKey().equals("a") || e.getKey().equals("b")).toMap(e -> e.getKey(), e -> e.getValue());
 * // Using Fn
 * Stream.of(map).filter(Fn.testByKey(k -> k.equals("a") || k.equals("b"))).collect(Collectors.toMap());
 * 
 * 
 * 
* * * @author haiyang li * */ public final class Fn { @SuppressWarnings("rawtypes") public static final IntFunction> FACTORY_OF_MAP = (IntFunction) Factory.MAP_FACTORY; @SuppressWarnings("rawtypes") public static final IntFunction> FACTORY_OF_LINKED_HASH_MAP = (IntFunction) Factory.LINKED_HASH_MAP_FACTORY; @SuppressWarnings("rawtypes") public static final Supplier> SUPPLIER_OF_MAP = (Supplier) Suppliers.MAP; @SuppressWarnings("rawtypes") public static final Supplier> SUPPLIER_OF_LINKED_HASH_MAP = (Supplier) Suppliers.LINKED_HASH_MAP; private static final Runnable EMPTY_ACTION = new Runnable() { @Override public void run() { } }; @SuppressWarnings("rawtypes") private static final Consumer DO_NOTHING = new Consumer() { @Override public void accept(Object value) { // do nothing. } }; @SuppressWarnings("rawtypes") private static final Consumer PRINTLN = new Consumer() { @Override public void accept(Object value) { N.println(value); } }; @SuppressWarnings("rawtypes") private static final Function IDENTITY = new Function() { @Override public Object apply(Object t) { return t; } }; private static final Function, Object> KEY = new Function, Object>() { @Override public Object apply(Map.Entry t) { return t.getKey(); } }; private static final Function, Object> VALUE = new Function, Object>() { @Override public Object apply(Map.Entry t) { return t.getValue(); } }; private static final BiFunction> ENTRY = new BiFunction>() { @Override public Map.Entry apply(Object key, Object value) { return new AbstractMap.SimpleImmutableEntry<>(key, value); } }; private static final Function TRIM = new Function() { @Override public String apply(String t) { return t == null ? null : t.trim(); } }; private static final Function TRIM_TO_EMPTY = new Function() { @Override public String apply(String t) { return t == null ? "" : t.trim(); } }; private static final Function TRIM_TO_NULL = new Function() { @Override public String apply(String t) { if (t == null || (t = t.trim()).length() == 0) { return null; } return t; } }; private static final BiFunction> PAIR = new BiFunction>() { @Override public Pair apply(Object key, Object value) { return Pair.of(key, value); } }; private static final TriFunction> TRIPLE = new TriFunction>() { @Override public Triple apply(Object a, Object b, Object c) { return Triple.of(a, b, c); } }; @SuppressWarnings("rawtypes") private static final Predicate ALWAYS_TRUE = new Predicate() { @Override public boolean test(Object value) { return true; } }; @SuppressWarnings("rawtypes") private static final Predicate ALWAYS_FALSE = new Predicate() { @Override public boolean test(Object value) { return false; } }; @SuppressWarnings("rawtypes") private static final Predicate IS_NULL = new Predicate() { @Override public boolean test(Object value) { return value == null; } }; @SuppressWarnings("rawtypes") private static final Predicate NOT_NULL = new Predicate() { @Override public boolean test(Object value) { return value != null; } }; private static final Object NULL = new Object(); private Fn() { // Singleton. } public static T get(final Supplier supplier) { return supplier.get(); } public static Comparator naturalOrder() { return Comparators.naturalOrder(); } public static Comparator reversedOrder() { return Comparators.reversedOrder(); } public static Comparator reversedOrder(final Comparator cmp) { return Comparators.reversedOrder(cmp); } @SuppressWarnings("rawtypes") public static Comparator comparingBy(final Function keyExtractor) { return Comparators.comparingBy(keyExtractor); } @SuppressWarnings("rawtypes") public static Comparator reversedComparingBy(final Function keyExtractor) { return Comparators.reversedComparingBy(keyExtractor); } public static Runnable emptyAction() { return EMPTY_ACTION; } public static Consumer doNothing() { return DO_NOTHING; } public static Consumer println() { return PRINTLN; } public static BiConsumer println(final String separator) { return new BiConsumer() { @Override public void accept(T t, U u) { N.println(t + separator + u); } }; } public static Function identity() { return IDENTITY; } @SuppressWarnings("rawtypes") public static Function, K> key() { return (Function) KEY; } @SuppressWarnings("rawtypes") public static Function, V> value() { return (Function) VALUE; } @SuppressWarnings("rawtypes") public static BiFunction> entry() { return (BiFunction) ENTRY; } @SuppressWarnings("rawtypes") public static BiFunction> pair() { return (BiFunction) PAIR; } @SuppressWarnings("rawtypes") public static TriFunction> triple() { return (TriFunction) TRIPLE; } public static Function trim() { return TRIM; } public static Function trimToEmpty() { return TRIM_TO_EMPTY; } public static Function trimToNull() { return TRIM_TO_NULL; } public static Function cast(final Class clazz) { return new Function() { @Override public U apply(T t) { return (U) t; } }; } public static Predicate alwaysTrue() { return ALWAYS_TRUE; } public static Predicate alwaysFalse() { return ALWAYS_FALSE; } public static Predicate isNull() { return IS_NULL; } public static Predicate notNull() { return NOT_NULL; } public static Predicate equal(final Object target) { return new Predicate() { @Override public boolean test(T value) { return N.equals(value, target); } }; } public static Predicate notEqual(final Object target) { return new Predicate() { @Override public boolean test(T value) { return !N.equals(value, target); } }; } @SuppressWarnings("rawtypes") public static Predicate greaterThan(final T target) { return new Predicate() { @Override public boolean test(T value) { return N.compare(value, target) > 0; } }; } @SuppressWarnings("rawtypes") public static Predicate greaterEqual(final T target) { return new Predicate() { @Override public boolean test(T value) { return N.compare(value, target) >= 0; } }; } @SuppressWarnings("rawtypes") public static Predicate lessThan(final T target) { return new Predicate() { @Override public boolean test(T value) { return N.compare(value, target) < 0; } }; } @SuppressWarnings("rawtypes") public static Predicate lessEqual(final T target) { return new Predicate() { @Override public boolean test(T value) { return N.compare(value, target) <= 0; } }; } public static Predicate in(final Collection c) { return new Predicate() { @Override public boolean test(T value) { return c.contains(value); } }; } public static Predicate notIn(final Collection c) { return new Predicate() { @Override public boolean test(T value) { return !c.contains(value); } }; } public static Predicate instanceOf(final Class clazz) { return new Predicate() { @Override public boolean test(T value) { return clazz.isInstance(value); } }; } @SuppressWarnings("rawtypes") public static Predicate subtypeOf(final Class clazz) { return new Predicate() { @Override public boolean test(Class value) { return clazz.isAssignableFrom(value); } }; } public static Predicate startsWith(final String prefix) { return new Predicate() { @Override public boolean test(String value) { return value.startsWith(prefix); } }; } public static Predicate endsWith(final String suffix) { return new Predicate() { @Override public boolean test(String value) { return value.endsWith(suffix); } }; } public static Predicate matches(final Pattern pattern) { return new Predicate() { @Override public boolean test(CharSequence value) { return pattern.matcher(value).find(); } }; } public static BiPredicate equal() { return BiPredicates.EQUAL; } public static BiPredicate notEqual() { return BiPredicates.NOT_EQUAL; } @SuppressWarnings("rawtypes") public static BiPredicate greaterThan() { return (BiPredicate) BiPredicates.GREATER_THAN; } @SuppressWarnings("rawtypes") public static BiPredicate greaterEqual() { return (BiPredicate) BiPredicates.GREATER_EQUAL; } @SuppressWarnings("rawtypes") public static BiPredicate lessThan() { return (BiPredicate) BiPredicates.LESS_THAN; } @SuppressWarnings("rawtypes") public static BiPredicate lessEqual() { return (BiPredicate) BiPredicates.LESS_EQUAL; } public static Predicate> testByKey(final Predicate predicate) { return new Predicate>() { @Override public boolean test(Entry entry) { return predicate.test(entry.getKey()); } }; } public static Predicate> testByValue(final Predicate predicate) { return new Predicate>() { @Override public boolean test(Entry entry) { return predicate.test(entry.getValue()); } }; } public static Consumer> acceptByKey(final Consumer consumer) { return new Consumer>() { @Override public void accept(Entry entry) { consumer.accept(entry.getKey()); } }; } public static Consumer> acceptByValue(final Consumer consumer) { return new Consumer>() { @Override public void accept(Entry entry) { consumer.accept(entry.getValue()); } }; } public static Function, R> applyByKey(final Function func) { return new Function, R>() { @Override public R apply(Entry entry) { return func.apply(entry.getKey()); } }; } public static Function, R> applyByValue(final Function func) { return new Function, R>() { @Override public R apply(Entry entry) { return func.apply(entry.getValue()); } }; } public static Function, Map.Entry> mapKey(final Function func) { return new Function, Map.Entry>() { @Override public Map.Entry apply(Entry entry) { return Pair.of(func.apply(entry.getKey()), entry.getValue()); } }; } public static Function, Map.Entry> mapValue(final Function func) { return new Function, Map.Entry>() { @Override public Map.Entry apply(Entry entry) { return Pair.of(entry.getKey(), func.apply(entry.getValue())); } }; } public static Predicate> testKeyVal(final BiPredicate predicate) { return new Predicate>() { @Override public boolean test(Entry entry) { return predicate.test(entry.getKey(), entry.getValue()); } }; } public static Consumer> acceptKeyVal(final BiConsumer consumer) { return new Consumer>() { @Override public void accept(Entry entry) { consumer.accept(entry.getKey(), entry.getValue()); } }; } public static Function, R> applyKeyVal(final BiFunction func) { return new Function, R>() { @Override public R apply(Entry entry) { return func.apply(entry.getKey(), entry.getValue()); } }; } public static BinaryOperator throwingMerger() { return BinaryOperators.THROWING_MERGER; } public static BinaryOperator ignoringMerger() { return BinaryOperators.IGNORING_MERGER; } public static BinaryOperator replacingMerger() { return BinaryOperators.REPLACING_MERGER; } public static ToByteFunction unboxB() { return ToByteFunction.UNBOX; } public static ToCharFunction unboxC() { return ToCharFunction.UNBOX; } public static ToShortFunction unboxS() { return ToShortFunction.UNBOX; } public static ToIntFunction unboxI() { return ToIntFunction.UNBOX; } public static ToLongFunction unboxL() { return ToLongFunction.UNBOX; } public static ToFloatFunction unboxF() { return ToFloatFunction.UNBOX; } public static ToDoubleFunction unboxD() { return ToDoubleFunction.UNBOX; } /** * * @param predicate * @param limit * @return */ public static Predicate limited(final Predicate predicate, final int limit) { N.requireNonNull(predicate); return new Predicate() { private final AtomicInteger counter = new AtomicInteger(limit); @Override public boolean test(T t) { return predicate.test(t) && counter.decrementAndGet() >= 0; } }; } /** * * @param predicate * @param limit * @return */ public static Predicate limited(final Predicate predicate, final long limit) { N.requireNonNull(predicate); return new Predicate() { private final AtomicLong counter = new AtomicLong(limit); @Override public boolean test(T t) { return predicate.test(t) && counter.decrementAndGet() >= 0; } }; } /** * * @param predicate * @param limit * @return */ public static BiPredicate limited(final BiPredicate predicate, final int limit) { N.requireNonNull(predicate); return new BiPredicate() { private final AtomicInteger counter = new AtomicInteger(limit); @Override public boolean test(T t, U u) { return predicate.test(t, u) && counter.decrementAndGet() >= 0; } }; } /** * * @param predicate * @param limit * @return */ public static BiPredicate limited(final BiPredicate predicate, final long limit) { N.requireNonNull(predicate); return new BiPredicate() { private final AtomicLong counter = new AtomicLong(limit); @Override public boolean test(T t, U u) { return predicate.test(t, u) && counter.decrementAndGet() >= 0; } }; } /** * * @param predicate * @param limit * @return */ public static TriPredicate limited(final TriPredicate predicate, final int limit) { N.requireNonNull(predicate); return new TriPredicate() { private final AtomicInteger counter = new AtomicInteger(limit); @Override public boolean test(A a, B b, C c) { return predicate.test(a, b, c) && counter.decrementAndGet() >= 0; } }; } /** * * @param predicate * @param limit * @return */ public static TriPredicate limited(final TriPredicate predicate, final long limit) { N.requireNonNull(predicate); return new TriPredicate() { private final AtomicLong counter = new AtomicLong(limit); @Override public boolean test(A a, B b, C c) { return predicate.test(a, b, c) && counter.decrementAndGet() >= 0; } }; } /** * Returns a stateful Predicate which should not be used in parallel stream. * * @param predicate * @return */ public static Predicate indexed(final IndexedPredicate predicate) { N.requireNonNull(predicate); return new Predicate() { private final AtomicInteger idx = new AtomicInteger(0); @Override public boolean test(T t) { return predicate.test(idx.getAndIncrement(), t); } }; } /** * Returns a stateful BiPredicate which should not be used in parallel stream. * * @param predicate * @return */ public static BiPredicate indexed(final IndexedBiPredicate predicate) { N.requireNonNull(predicate); return new BiPredicate() { private final AtomicInteger idx = new AtomicInteger(0); @Override public boolean test(U u, T t) { return predicate.test(u, idx.getAndIncrement(), t); } }; } /** * Returns a stateful Function which should not be used in parallel stream. * * @param func * @return */ public static Function indexeD(final IndexedFunction func) { N.requireNonNull(func); return new Function() { private final AtomicInteger idx = new AtomicInteger(0); @Override public R apply(T t) { return func.apply(idx.getAndIncrement(), t); } }; } /** * Returns a stateful BiFunction which should not be used in parallel stream. * * @param func * @return */ public static BiFunction indexeD(final IndexedBiFunction func) { N.requireNonNull(func); return new BiFunction() { private final AtomicInteger idx = new AtomicInteger(0); @Override public R apply(U u, T t) { return func.apply(u, idx.getAndIncrement(), t); } }; } /** * Returns a stateful Consumer which should not be used in parallel stream. * * @param action * @return */ public static Consumer indexeed(final IndexedConsumer action) { N.requireNonNull(action); return new Consumer() { private final AtomicInteger idx = new AtomicInteger(0); @Override public void accept(T t) { action.accept(idx.getAndIncrement(), t); } }; } /** * Returns a stateful BiConsumer which should not be used in parallel stream. * * @param action * @return */ public static BiConsumer indexeed(final IndexedBiConsumer action) { N.requireNonNull(action); return new BiConsumer() { private final AtomicInteger idx = new AtomicInteger(0); @Override public void accept(U u, T t) { action.accept(u, idx.getAndIncrement(), t); } }; } public static Collector> toList() { return Collectors.toList(); } public static Collector> toSet() { return Collectors.toSet(); } public static Collector counting() { return Collectors.counting(); } public static Collector countingInt() { return Collectors.countingInt(); } public static Collector summingInt(final ToIntFunction mapper) { return Collectors.summingInt(mapper); } public static Collector summingLong(final ToLongFunction mapper) { return Collectors.summingLong(mapper); } public static Collector summingDouble(final ToDoubleFunction mapper) { return Collectors.summingDouble(mapper); } public static Collector averagingInt(final ToIntFunction mapper) { return Collectors.averagingInt(mapper); } public static Collector averagingLong(final ToLongFunction mapper) { return Collectors.averagingLong(mapper); } public static Collector averagingDouble(final ToDoubleFunction mapper) { return Collectors.averagingDouble(mapper); } public static final class Factory { private static final IntFunction BOOLEAN_ARRAY = new IntFunction() { @Override public boolean[] apply(int len) { return new boolean[len]; } }; private static final IntFunction CHAR_ARRAY = new IntFunction() { @Override public char[] apply(int len) { return new char[len]; } }; private static final IntFunction BYTE_ARRAY = new IntFunction() { @Override public byte[] apply(int len) { return new byte[len]; } }; private static final IntFunction SHORT_ARRAY = new IntFunction() { @Override public short[] apply(int len) { return new short[len]; } }; private static final IntFunction INT_ARRAY = new IntFunction() { @Override public int[] apply(int len) { return new int[len]; } }; private static final IntFunction LONG_ARRAY = new IntFunction() { @Override public long[] apply(int len) { return new long[len]; } }; private static final IntFunction FLOAT_ARRAY = new IntFunction() { @Override public float[] apply(int len) { return new float[len]; } }; private static final IntFunction DOUBLE_ARRAY = new IntFunction() { @Override public double[] apply(int len) { return new double[len]; } }; private static final IntFunction STRING_ARRAY = new IntFunction() { @Override public String[] apply(int len) { return new String[len]; } }; private static final IntFunction OBJECT_ARRAY = new IntFunction() { @Override public Object[] apply(int len) { return new Object[len]; } }; private static final IntFunction BOOLEAN_LIST = new IntFunction() { @Override public BooleanList apply(int len) { return new BooleanList(len); } }; private static final IntFunction CHAR_LIST = new IntFunction() { @Override public CharList apply(int len) { return new CharList(len); } }; private static final IntFunction BYTE_LIST = new IntFunction() { @Override public ByteList apply(int len) { return new ByteList(len); } }; private static final IntFunction SHORT_LIST = new IntFunction() { @Override public ShortList apply(int len) { return new ShortList(len); } }; private static final IntFunction INT_LIST = new IntFunction() { @Override public IntList apply(int len) { return new IntList(len); } }; private static final IntFunction LONG_LIST = new IntFunction() { @Override public LongList apply(int len) { return new LongList(len); } }; private static final IntFunction FLOAT_LIST = new IntFunction() { @Override public FloatList apply(int len) { return new FloatList(len); } }; private static final IntFunction DOUBLE_LIST = new IntFunction() { @Override public DoubleList apply(int len) { return new DoubleList(len); } }; @SuppressWarnings("rawtypes") private static final IntFunction LIST_FACTORY = new IntFunction() { @Override public List apply(int len) { return new ArrayList<>(len); } }; @SuppressWarnings("rawtypes") private static final IntFunction LINKED_LIST_FACTORY = new IntFunction() { @Override public LinkedList apply(int len) { return new LinkedList<>(); } }; @SuppressWarnings("rawtypes") private static final IntFunction SET_FACTORY = new IntFunction() { @Override public Set apply(int len) { return new HashSet<>(N.initHashCapacity(len)); } }; @SuppressWarnings("rawtypes") private static final IntFunction LINKED_HASH_SET_FACTORY = new IntFunction() { @Override public LinkedHashSet apply(int len) { return new LinkedHashSet<>(N.initHashCapacity(len)); } }; @SuppressWarnings("rawtypes") private static final IntFunction TREE_SET_FACTORY = new IntFunction() { @Override public TreeSet apply(int len) { return new TreeSet<>(); } }; @SuppressWarnings("rawtypes") private static final IntFunction MAP_FACTORY = new IntFunction() { @Override public Map apply(int len) { return new HashMap<>(N.initHashCapacity(len)); } }; @SuppressWarnings("rawtypes") private static final IntFunction LINKED_HASH_MAP_FACTORY = new IntFunction() { @Override public LinkedHashMap apply(int len) { return new LinkedHashMap<>(N.initHashCapacity(len)); } }; @SuppressWarnings("rawtypes") private static final IntFunction TREE_MAP_FACTORY = new IntFunction() { @Override public TreeMap apply(int len) { return new TreeMap<>(); } }; @SuppressWarnings("rawtypes") private static final IntFunction CONCURRENT_HASH_MAP_FACTORY = new IntFunction() { @Override public ConcurrentHashMap apply(int len) { return new ConcurrentHashMap(N.initHashCapacity(len)); } }; @SuppressWarnings("rawtypes") private static final IntFunction QUEUE_FACTORY = new IntFunction() { @Override public Queue apply(int len) { return new LinkedList(); } }; @SuppressWarnings("rawtypes") private static final IntFunction ARRAY_DEQUE_FACTORY = new IntFunction() { @Override public ArrayDeque apply(int len) { return new ArrayDeque(len); } }; @SuppressWarnings("rawtypes") private static final IntFunction LINKED_BLOCKING_QUEUE_FACTORY = new IntFunction() { @Override public LinkedBlockingQueue apply(int len) { return new LinkedBlockingQueue(len); } }; @SuppressWarnings("rawtypes") private static final IntFunction CONCURRENT_LINKED_QUEUE_FACTORY = new IntFunction() { @Override public ConcurrentLinkedQueue apply(int len) { return new ConcurrentLinkedQueue(); } }; @SuppressWarnings("rawtypes") private static final IntFunction PRIORITY_QUEUE_FACTORY = new IntFunction() { @Override public PriorityQueue apply(int len) { return new PriorityQueue(len); } }; private Factory() { // singleton. } public static IntFunction ofBooleanArray() { return BOOLEAN_ARRAY; } public static IntFunction ofCharArray() { return CHAR_ARRAY; } public static IntFunction ofByteArray() { return BYTE_ARRAY; } public static IntFunction ofShortArray() { return SHORT_ARRAY; } public static IntFunction ofIntArray() { return INT_ARRAY; } public static IntFunction ofLongArray() { return LONG_ARRAY; } public static IntFunction ofFloatArray() { return FLOAT_ARRAY; } public static IntFunction ofDoubleArray() { return DOUBLE_ARRAY; } public static IntFunction ofStringArray() { return STRING_ARRAY; } public static IntFunction ofObjectArray() { return OBJECT_ARRAY; } public static IntFunction ofBooleanList() { return BOOLEAN_LIST; } public static IntFunction ofCharList() { return CHAR_LIST; } public static IntFunction ofByteList() { return BYTE_LIST; } public static IntFunction ofShortList() { return SHORT_LIST; } public static IntFunction ofIntList() { return INT_LIST; } public static IntFunction ofLongList() { return LONG_LIST; } public static IntFunction ofFloatList() { return FLOAT_LIST; } public static IntFunction ofDoubleList() { return DOUBLE_LIST; } @SuppressWarnings("rawtypes") public static IntFunction> ofList() { return (IntFunction) LIST_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofLinkedList() { return (IntFunction) LINKED_LIST_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofSet() { return (IntFunction) SET_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofLinkedHashSet() { return (IntFunction) LINKED_HASH_SET_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofTreeSet() { return (IntFunction) TREE_SET_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofMap() { return (IntFunction) MAP_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofLinkedHashMap() { return (IntFunction) LINKED_HASH_MAP_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofTreeMap() { return (IntFunction) TREE_MAP_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofConcurrentHashMap() { return (IntFunction) CONCURRENT_HASH_MAP_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofQueue() { return (IntFunction) QUEUE_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofArrayDeque() { return (IntFunction) ARRAY_DEQUE_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofLinkedBlockingQueue() { return (IntFunction) LINKED_BLOCKING_QUEUE_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofConcurrentLinkedQueue() { return (IntFunction) CONCURRENT_LINKED_QUEUE_FACTORY; } @SuppressWarnings("rawtypes") public static IntFunction> ofPriorityQueue() { return (IntFunction) PRIORITY_QUEUE_FACTORY; } } public static final class Suppliers { private static final Supplier UUID = new Supplier() { @Override public String get() { return N.uuid(); } }; private static final Supplier GUID = new Supplier() { @Override public String get() { return N.guid(); } }; private static final Supplier EMPTY_BOOLEAN_ARRAY = new Supplier() { @Override public boolean[] get() { return N.EMPTY_BOOLEAN_ARRAY; } }; private static final Supplier EMPTY_CHAR_ARRAY = new Supplier() { @Override public char[] get() { return N.EMPTY_CHAR_ARRAY; } }; private static final Supplier EMPTY_BYTE_ARRAY = new Supplier() { @Override public byte[] get() { return N.EMPTY_BYTE_ARRAY; } }; private static final Supplier EMPTY_SHORT_ARRAY = new Supplier() { @Override public short[] get() { return N.EMPTY_SHORT_ARRAY; } }; private static final Supplier EMPTY_INT_ARRAY = new Supplier() { @Override public int[] get() { return N.EMPTY_INT_ARRAY; } }; private static final Supplier EMPTY_LONG_ARRAY = new Supplier() { @Override public long[] get() { return N.EMPTY_LONG_ARRAY; } }; private static final Supplier EMPTY_FLOAT_ARRAY = new Supplier() { @Override public float[] get() { return N.EMPTY_FLOAT_ARRAY; } }; private static final Supplier EMPTY_DOUBLE_ARRAY = new Supplier() { @Override public double[] get() { return N.EMPTY_DOUBLE_ARRAY; } }; private static final Supplier EMPTY_STRING_ARRAY = new Supplier() { @Override public String[] get() { return N.EMPTY_STRING_ARRAY; } }; private static final Supplier EMPTY_OBJECT_ARRAY = new Supplier() { @Override public Object[] get() { return N.EMPTY_OBJECT_ARRAY; } }; private static final Supplier BOOLEAN_LIST = new Supplier() { @Override public BooleanList get() { return new BooleanList(); } }; private static final Supplier CHAR_LIST = new Supplier() { @Override public CharList get() { return new CharList(); } }; private static final Supplier BYTE_LIST = new Supplier() { @Override public ByteList get() { return new ByteList(); } }; private static final Supplier SHORT_LIST = new Supplier() { @Override public ShortList get() { return new ShortList(); } }; private static final Supplier INT_LIST = new Supplier() { @Override public IntList get() { return new IntList(); } }; private static final Supplier LONG_LIST = new Supplier() { @Override public LongList get() { return new LongList(); } }; private static final Supplier FLOAT_LIST = new Supplier() { @Override public FloatList get() { return new FloatList(); } }; private static final Supplier DOUBLE_LIST = new Supplier() { @Override public DoubleList get() { return new DoubleList(); } }; @SuppressWarnings("rawtypes") private static final Supplier LIST = new Supplier() { @Override public List get() { return new ArrayList(); } }; @SuppressWarnings("rawtypes") private static final Supplier LINKED_LIST = new Supplier() { @Override public LinkedList get() { return new LinkedList(); } }; @SuppressWarnings("rawtypes") private static final Supplier SET = new Supplier() { @Override public Set get() { return new HashSet(); } }; @SuppressWarnings("rawtypes") private static final Supplier LINKED_HASH_SET = new Supplier() { @Override public LinkedHashSet get() { return new LinkedHashSet(); } }; @SuppressWarnings("rawtypes") private static final Supplier TREE_SET = new Supplier() { @Override public TreeSet get() { return new TreeSet(); } }; @SuppressWarnings("rawtypes") private static final Supplier MAP = new Supplier() { @Override public Map get() { return new HashMap(); } }; @SuppressWarnings("rawtypes") private static final Supplier LINKED_HASH_MAP = new Supplier() { @Override public LinkedHashMap get() { return new LinkedHashMap(); } }; @SuppressWarnings("rawtypes") private static final Supplier TREE_MAP = new Supplier() { @Override public TreeMap get() { return new TreeMap(); } }; @SuppressWarnings("rawtypes") private static final Supplier CONCURRENT_HASH_MAP = new Supplier() { @Override public ConcurrentHashMap get() { return new ConcurrentHashMap(); } }; @SuppressWarnings("rawtypes") private static final Supplier QUEUE = new Supplier() { @Override public Queue get() { return new LinkedList(); } }; @SuppressWarnings("rawtypes") private static final Supplier ARRAY_DEQUE = new Supplier() { @Override public ArrayDeque get() { return new ArrayDeque(); } }; @SuppressWarnings("rawtypes") private static final Supplier LINKED_BLOCKING_QUEUE = new Supplier() { @Override public LinkedBlockingQueue get() { return new LinkedBlockingQueue(); } }; @SuppressWarnings("rawtypes") private static final Supplier CONCURRENT_LINKED_QUEUE = new Supplier() { @Override public ConcurrentLinkedQueue get() { return new ConcurrentLinkedQueue(); } }; @SuppressWarnings("rawtypes") private static final Supplier PRIORITY_QUEUE = new Supplier() { @Override public PriorityQueue get() { return new PriorityQueue(); } }; private Suppliers() { // singleton. } public static Supplier ofUUID() { return UUID; } public static Supplier ofGUID() { return GUID; } public static Supplier ofEmptyBooleanArray() { return EMPTY_BOOLEAN_ARRAY; } public static Supplier ofEmptyCharArray() { return EMPTY_CHAR_ARRAY; } public static Supplier ofEmptyByteArray() { return EMPTY_BYTE_ARRAY; } public static Supplier ofEmptyShortArray() { return EMPTY_SHORT_ARRAY; } public static Supplier ofEmptyIntArray() { return EMPTY_INT_ARRAY; } public static Supplier ofEmptyLongArray() { return EMPTY_LONG_ARRAY; } public static Supplier ofEmptyFloatArray() { return EMPTY_FLOAT_ARRAY; } public static Supplier ofEmptyDoubleArray() { return EMPTY_DOUBLE_ARRAY; } public static Supplier ofEmptyStringArray() { return EMPTY_STRING_ARRAY; } public static Supplier ofEmptyObjectArray() { return EMPTY_OBJECT_ARRAY; } public static Supplier ofBooleanList() { return BOOLEAN_LIST; } public static Supplier ofCharList() { return CHAR_LIST; } public static Supplier ofByteList() { return BYTE_LIST; } public static Supplier ofShortList() { return SHORT_LIST; } public static Supplier ofIntList() { return INT_LIST; } public static Supplier ofLongList() { return LONG_LIST; } public static Supplier ofFloatList() { return FLOAT_LIST; } public static Supplier ofDoubleList() { return DOUBLE_LIST; } @SuppressWarnings("rawtypes") public static Supplier> ofList() { return (Supplier) LIST; } @SuppressWarnings("rawtypes") public static Supplier> ofLinkedList() { return (Supplier) LINKED_LIST; } @SuppressWarnings("rawtypes") public static Supplier> ofSet() { return (Supplier) SET; } @SuppressWarnings("rawtypes") public static Supplier> ofLinkedHashSet() { return (Supplier) LINKED_HASH_SET; } @SuppressWarnings("rawtypes") public static Supplier> ofTreeSet() { return (Supplier) TREE_SET; } @SuppressWarnings("rawtypes") public static Supplier> ofMap() { return (Supplier) MAP; } @SuppressWarnings("rawtypes") public static Supplier> ofLinkedHashMap() { return (Supplier) LINKED_HASH_MAP; } @SuppressWarnings("rawtypes") public static Supplier> ofTreeMap() { return (Supplier) TREE_MAP; } @SuppressWarnings("rawtypes") public static Supplier> ofConcurrentHashMap() { return (Supplier) CONCURRENT_HASH_MAP; } @SuppressWarnings("rawtypes") public static Supplier> ofQueue() { return (Supplier) QUEUE; } @SuppressWarnings("rawtypes") public static Supplier> ofArrayDeque() { return (Supplier) ARRAY_DEQUE; } @SuppressWarnings("rawtypes") public static Supplier> ofLinkedBlockingQueue() { return (Supplier) LINKED_BLOCKING_QUEUE; } @SuppressWarnings("rawtypes") public static Supplier> ofConcurrentLinkedQueue() { return (Supplier) CONCURRENT_LINKED_QUEUE; } @SuppressWarnings("rawtypes") public static Supplier> ofPriorityQueue() { return (Supplier) PRIORITY_QUEUE; } } public static final class Predicates { private Predicates() { // singleton. } public static Predicate of(final U u, final BiPredicate predicate) { N.requireNonNull(predicate); return new Predicate() { @Override public boolean test(T t) { return predicate.test(t, u); } }; } /** * Remove the continuous repeat elements. * Returns a stateful predicate which should not be used in parallel stream. * * @return */ public static Predicate skipRepeats() { return new Predicate() { private T pre = (T) NULL; @Override public boolean test(T value) { boolean res = pre == NULL || N.equals(value, pre) == false; pre = value; return res; } }; } public static Predicate indexed(final IndexedPredicate predicate) { return Fn.indexed(predicate); } } public static final class BiPredicates { @SuppressWarnings("rawtypes") private static final BiPredicate ALWAYS_TRUE = new BiPredicate() { @Override public boolean test(Object t, Object u) { return true; } }; @SuppressWarnings("rawtypes") private static final BiPredicate ALWAYS_FALSE = new BiPredicate() { @Override public boolean test(Object t, Object u) { return false; } }; @SuppressWarnings("rawtypes") private static final BiPredicate EQUAL = new BiPredicate() { @Override public boolean test(Object t, Object u) { return N.equals(t, u); } }; @SuppressWarnings("rawtypes") private static final BiPredicate NOT_EQUAL = new BiPredicate() { @Override public boolean test(Object t, Object u) { return !N.equals(t, u); } }; @SuppressWarnings("rawtypes") private static final BiPredicate GREATER_THAN = new BiPredicate() { @Override public boolean test(Comparable t, Comparable u) { return N.compare(t, u) > 0; } }; @SuppressWarnings("rawtypes") private static final BiPredicate GREATER_EQUAL = new BiPredicate() { @Override public boolean test(Comparable t, Comparable u) { return N.compare(t, u) >= 0; } }; @SuppressWarnings("rawtypes") private static final BiPredicate LESS_THAN = new BiPredicate() { @Override public boolean test(Comparable t, Comparable u) { return N.compare(t, u) < 0; } }; @SuppressWarnings("rawtypes") private static final BiPredicate LESS_EQUAL = new BiPredicate() { @Override public boolean test(Comparable t, Comparable u) { return N.compare(t, u) <= 0; } }; private BiPredicates() { // singleton. } public static BiPredicate alwaysTrue() { return ALWAYS_TRUE; } public static BiPredicate alwaysFalse() { return ALWAYS_FALSE; } public static BiPredicate indexed(final IndexedBiPredicate predicate) { return Fn.indexed(predicate); } } public static final class TriPredicates { @SuppressWarnings("rawtypes") private static final TriPredicate ALWAYS_TRUE = new TriPredicate() { @Override public boolean test(Object a, Object b, Object c) { return true; } }; @SuppressWarnings("rawtypes") private static final TriPredicate ALWAYS_FALSE = new TriPredicate() { @Override public boolean test(Object a, Object b, Object c) { return false; } }; private TriPredicates() { // singleton. } public static TriPredicate alwaysTrue() { return ALWAYS_TRUE; } public static TriPredicate alwaysFalse() { return ALWAYS_FALSE; } } public static final class Consumers { private Consumers() { // singleton. } public static Consumer of(final U u, final BiConsumer action) { N.requireNonNull(action); return new Consumer() { @Override public void accept(T t) { action.accept(t, u); } }; } /** * Returns a Consumer which calls the specified func. * * @param func * @return */ public static Consumer of(final Function func) { return new Consumer() { @Override public void accept(T t) { func.apply(t); } }; } public static Consumer indexed(final IndexedConsumer action) { return Fn.indexeed(action); } } public static final class BiConsumers { @SuppressWarnings("rawtypes") private static final BiConsumer DO_NOTHING = new BiConsumer() { @Override public void accept(Object t, Object u) { // do nothing. } }; private static final BiConsumer, Object> ADD = new BiConsumer, Object>() { @Override public void accept(Collection t, Object u) { t.add(u); } }; private static final BiConsumer, Collection> ADD_ALL = new BiConsumer, Collection>() { @Override public void accept(Collection t, Collection u) { t.addAll(u); } }; @SuppressWarnings("rawtypes") private static final BiConsumer ADD_ALL_2 = new BiConsumer() { @Override public void accept(PrimitiveList t, PrimitiveList u) { t.addAll(u); } }; private static final BiConsumer, Object> REMOVE = new BiConsumer, Object>() { @Override public void accept(Collection t, Object u) { t.remove(u); } }; private static final BiConsumer, Collection> REMOVE_ALL = new BiConsumer, Collection>() { @Override public void accept(Collection t, Collection u) { t.removeAll(u); } }; @SuppressWarnings("rawtypes") private static final BiConsumer REMOVE_ALL_2 = new BiConsumer() { @Override public void accept(PrimitiveList t, PrimitiveList u) { t.removeAll(u); } }; private static final BiConsumer, Map.Entry> PUT = new BiConsumer, Map.Entry>() { @Override public void accept(Map t, Map.Entry u) { t.put(u.getKey(), u.getValue()); } }; private static final BiConsumer, Map> PUT_ALL = new BiConsumer, Map>() { @Override public void accept(Map t, Map u) { t.putAll(u); } }; private static final BiConsumer, Object> REMOVE_BY_KEY = new BiConsumer, Object>() { @Override public void accept(Map t, Object u) { t.remove(u); } }; private static final BiConsumer MERGE = new BiConsumer() { @Override public void accept(Joiner t, Joiner u) { t.merge(u); } }; private static final BiConsumer APPEND = new BiConsumer() { @Override public void accept(StringBuilder t, Object u) { t.append(u); } }; private BiConsumers() { // singleton. } public static BiConsumer doNothing() { return DO_NOTHING; } public static > BiConsumer ofAdd() { return (BiConsumer) ADD; } public static > BiConsumer ofAddAll() { return (BiConsumer) ADD_ALL; } @SuppressWarnings("rawtypes") public static BiConsumer ofAddAll2() { return (BiConsumer) ADD_ALL_2; } public static > BiConsumer ofRemove() { return (BiConsumer) REMOVE; } public static > BiConsumer ofRemoveAll() { return (BiConsumer) REMOVE_ALL; } @SuppressWarnings("rawtypes") public static BiConsumer ofRemoveAll2() { return (BiConsumer) REMOVE_ALL_2; } public static , E extends Map.Entry> BiConsumer ofPut() { return (BiConsumer) PUT; } public static > BiConsumer ofPutAll() { return (BiConsumer) PUT_ALL; } public static > BiConsumer ofRemoveByKey() { return (BiConsumer) REMOVE_BY_KEY; } public static BiConsumer ofMerge() { return MERGE; } public static BiConsumer ofAppend() { return (BiConsumer) APPEND; } /** * Returns a BiConsumer which calls the specified func. * * @param func * @return */ public static BiConsumer of(final BiFunction func) { return new BiConsumer() { @Override public void accept(T t, U u) { func.apply(t, u); } }; } public static BiConsumer indexed(final IndexedBiConsumer action) { return Fn.indexeed(action); } } public static final class TriConsumers { private TriConsumers() { // singleton. } /** * Returns a TriConsumer which calls the specified func. * * @param func * @return */ public static TriConsumer of(final TriFunction func) { return new TriConsumer() { @Override public void accept(A a, B b, C c) { func.apply(a, b, c); } }; } } public static final class Functions { private Functions() { // singleton. } public static Function of(final U u, final BiFunction func) { N.requireNonNull(func); return new Function() { @Override public R apply(T t) { return func.apply(t, u); } }; } /** * Returns a Function which calls the specified action and always return an emptyOptional if action is executed successfully. * * @param action * @return */ public static Function> of(final Consumer action) { return new Function>() { @Override public Optional apply(T t) { action.accept(t); return Optional.empty(); } }; } public static Function indexed(final IndexedFunction func) { return Fn.indexeD(func); } } public static final class BiFunctions { private static final BiFunction RETURN_FIRST = new BiFunction() { @Override public Object apply(Object t, Object u) { return t; } }; private static final BiFunction RETURN_SECOND = new BiFunction() { @Override public Object apply(Object t, Object u) { return u; } }; @SuppressWarnings("rawtypes") private static final BiFunction TUPLE = new BiFunction() { @Override public Tuple2 apply(Object t, Object u) { return Tuple.of(t, u); } }; private static final BiFunction, Object, Collection> ADD = new BiFunction, Object, Collection>() { @Override public Collection apply(Collection t, Object u) { t.add(u); return t; } }; private static final BiFunction, Collection, Collection> ADD_ALL = new BiFunction, Collection, Collection>() { @Override public Collection apply(Collection t, Collection u) { t.addAll(u); return t; } }; @SuppressWarnings("rawtypes") private static final BiFunction ADD_ALL_2 = new BiFunction() { @Override public PrimitiveList apply(PrimitiveList t, PrimitiveList u) { t.addAll(u); return t; } }; private static final BiFunction, Object, Collection> REMOVE = new BiFunction, Object, Collection>() { @Override public Collection apply(Collection t, Object u) { t.remove(u); return t; } }; private static final BiFunction, Collection, Collection> REMOVE_ALL = new BiFunction, Collection, Collection>() { @Override public Collection apply(Collection t, Collection u) { t.removeAll(u); return t; } }; @SuppressWarnings("rawtypes") private static final BiFunction REMOVE_ALL_2 = new BiFunction() { @Override public PrimitiveList apply(PrimitiveList t, PrimitiveList u) { t.removeAll(u); return t; } }; private static final BiFunction, Map.Entry, Map> PUT = new BiFunction, Map.Entry, Map>() { @Override public Map apply(Map t, Map.Entry u) { t.put(u.getKey(), u.getValue()); return t; } }; private static final BiFunction, Map, Map> PUT_ALL = new BiFunction, Map, Map>() { @Override public Map apply(Map t, Map u) { t.putAll(u); return t; } }; private static final BiFunction, Object, Map> REMOVE_BY_KEY = new BiFunction, Object, Map>() { @Override public Map apply(Map t, Object u) { t.remove(u); return t; } }; private static final BiFunction MERGE = new BiFunction() { @Override public Joiner apply(Joiner t, Joiner u) { return t.merge(u); } }; private static final BiFunction APPEND = new BiFunction() { @Override public StringBuilder apply(StringBuilder t, Object u) { return t.append(u); } }; private BiFunctions() { // singleton. } public static BiFunction returnFirst() { return (BiFunction) RETURN_FIRST; } public static BiFunction returnSecond() { return (BiFunction) RETURN_SECOND; } @SuppressWarnings("rawtypes") public static BiFunction> ofTuple() { return (BiFunction) TUPLE; } public static > BiFunction ofAdd() { return (BiFunction) ADD; } public static > BiFunction ofAddAll() { return (BiFunction) ADD_ALL; } @SuppressWarnings("rawtypes") public static BiFunction ofAddAll2() { return (BiFunction) ADD_ALL_2; } public static > BiFunction ofRemove() { return (BiFunction) REMOVE; } public static > BiFunction ofRemoveAll() { return (BiFunction) REMOVE_ALL; } @SuppressWarnings("rawtypes") public static BiFunction ofRemoveAll2() { return (BiFunction) REMOVE_ALL_2; } public static , E extends Map.Entry> BiFunction ofPut() { return (BiFunction) PUT; } public static > BiFunction ofPutAll() { return (BiFunction) PUT_ALL; } public static , U> BiFunction ofRemoveByKey() { return (BiFunction) REMOVE_BY_KEY; } public static BiFunction ofMerge() { return MERGE; } public static BiFunction ofAppend() { return (BiFunction) APPEND; } /** * Returns a BiFunction which calls the specified action and always return an emptyOptional if action is executed successfully. * * @param action * @return */ public static BiFunction> of(final BiConsumer action) { return new BiFunction>() { @Override public Optional apply(T t, U u) { action.accept(t, u); return Optional.empty(); } }; } public static BiFunction indexed(final IndexedBiFunction func) { return Fn.indexeD(func); } } public static final class TriFunctions { @SuppressWarnings("rawtypes") private static final TriFunction TUPLE = new TriFunction() { @Override public Tuple3 apply(Object a, Object b, Object c) { return Tuple.of(a, b, c); } }; private TriFunctions() { // singleton. } @SuppressWarnings("rawtypes") public static TriFunction> ofTuple() { return (TriFunction) TUPLE; } /** * Returns a TriFunction which calls the specified action and always return an emptyOptional if action is executed successfully. * * @param action * @return */ public static TriFunction> of(final TriConsumer action) { return new TriFunction>() { @Override public Optional apply(A a, B b, C c) { action.accept(a, b, c); return Optional.empty(); } }; } } public static final class BinaryOperators { @SuppressWarnings("rawtypes") private static final BinaryOperator THROWING_MERGER = new BinaryOperator() { @Override public Object apply(Object t, Object u) { throw new IllegalStateException(String.format("Duplicate key (attempted merging values %s and %s)", t, u)); } }; @SuppressWarnings("rawtypes") private static final BinaryOperator IGNORING_MERGER = new BinaryOperator() { @Override public Object apply(Object t, Object u) { return t; } }; @SuppressWarnings("rawtypes") private static final BinaryOperator REPLACING_MERGER = new BinaryOperator() { @Override public Object apply(Object t, Object u) { return u; } }; private static final BinaryOperator> ADD_ALL = new BinaryOperator>() { @Override public Collection apply(Collection t, Collection u) { t.addAll(u); return t; } }; private static final BinaryOperator> REMOVE_ALL = new BinaryOperator>() { @Override public Collection apply(Collection t, Collection u) { t.removeAll(u); return t; } }; private static final BinaryOperator> PUT_ALL = new BinaryOperator>() { @Override public Map apply(Map t, Map u) { t.putAll(u); return t; } }; private BinaryOperators() { // singleton. } public static > BinaryOperator ofAddAll() { return (BinaryOperator) ADD_ALL; } public static > BinaryOperator ofRemoveAll() { return (BinaryOperator) REMOVE_ALL; } public static > BinaryOperator ofPutAll() { return (BinaryOperator) PUT_ALL; } public static BinaryOperator ofMerge() { return new BinaryOperator() { @Override public Joiner apply(Joiner t, Joiner u) { return t.merge(u); } }; } public static BinaryOperator ofAppend() { return new BinaryOperator() { @Override public StringBuilder apply(StringBuilder t, StringBuilder u) { return t.append(u); } }; } public static BinaryOperator ofJoin(final String seperator) { return new BinaryOperator() { @Override public String apply(String t, String u) { return t + seperator + u; } }; } public static BinaryOperator minBy(final Comparator comparator) { N.requireNonNull(comparator); return new BinaryOperator() { @Override public T apply(T t, T u) { return comparator.compare(t, u) <= 0 ? t : u; } }; } public static BinaryOperator maxBy(final Comparator comparator) { N.requireNonNull(comparator); return new BinaryOperator() { @Override public T apply(T t, T u) { return comparator.compare(t, u) >= 0 ? t : u; } }; } } public static final class UnaryOperators { @SuppressWarnings("rawtypes") private static final UnaryOperator IDENTITY = new UnaryOperator() { @Override public Object apply(Object t) { return t; } }; private UnaryOperators() { // singleton. } public static UnaryOperator identity() { return IDENTITY; } } }