com.xyzwps.lib.dollar.Dollar Maven / Gradle / Ivy
Show all versions of xyzwps-dollar Show documentation
package com.xyzwps.lib.dollar;
import com.xyzwps.lib.dollar.function.Function3;
import com.xyzwps.lib.dollar.function.ObjIntFunction;
import com.xyzwps.lib.dollar.iterable.Range;
import java.util.*;
import java.util.function.*;
import java.util.regex.Pattern;
import static com.xyzwps.lib.dollar.Helper.*;
/**
* Where to start.
*
* TODO: optimize for RandomAccess
* TODO: 写中文文档
* TODO: add examples
*/
public final class Dollar {
/**
* Create a stage chain from a {@link List}.
*
* @param list source list. Null is acceptable.
* @param list element type
* @return a list stage
*/
public static Seq $(List list) {
return $.isEmpty(list) ? Seq.empty() : list::forEach;
}
/**
* Create a stage chain from a map.
*
* @param map source map. Null is acceptable.
* @param map key type
* @param map value type
* @return a map stage
*/
public static MESeq $(Map map) {
return $.isEmpty(map) ? MESeq.empty() : map::forEach;
}
public static class $ {
/**
* Count the elements of a collection
.
* Return 0 if collection
is null
.
*
* @param collection which to handle
* @param collection element type
* @return count of elements in collection
*/
public static int size(Collection collection) {
return collection == null ? 0 : collection.size();
}
/**
* Count the entries of a map
.
* Return 0 if map
is null
.
*
* @param map which to handle
* @param type of keys
* @param type of values
* @return count of entries in map
*/
public static int size(Map map) {
return map == null ? 0 : map.size();
}
/**
* Checks value
to determine whether a public static value
* should be returned in its place. The defaultValue
* is returned when value
is null
.
*
* @param value The value to check
* @param defaultValue The public static value
* @param value type
* @return resolved value
*/
public static T defaultTo(T value, T defaultValue) {
return value == null ? defaultValue : value;
}
/**
* Check value which is falsey or not. The values null
, false
,
* 0(.0)
and ""
are falsey.
*
* @param value value to be checked
* @return true if the value is falsey
* @see #compact
*/
public static boolean isFalsey(Object value) {
return value == null
|| Objects.equals(value, false)
|| "".equals(value)
|| Objects.equals(value, 0)
|| Objects.equals(value, 0L)
|| Objects.equals(value, 0.0)
|| Objects.equals(value, 0.0f);
}
/**
* Creates a list of elements split into groups the length of size.
* If list can't be split evenly, the final chunk will be the remaining elements.
*
* @param list The list to handle
* @param size Chunk size which should be greater than 0.
* @param Element type
* @return new list of chunks
*/
public static List> chunk(List list, int size) {
if (size < 1) {
throw new IllegalArgumentException("Chunk size should be greater than 0.");
}
if (isEmpty(list)) {
return new ArrayList<>();
}
int listSize = list.size();
int chunksCapacity = listSize / size + 1;
List> chunks = new ArrayList<>(chunksCapacity);
List chunk = null;
int counter = 0;
int i = 0;
for (T element : list) {
if (counter == 0) {
chunk = new ArrayList<>(size);
}
chunk.add(element);
counter++;
i++;
if (counter == size || i == listSize) {
chunks.add(chunk);
chunk = null;
counter = 0;
}
}
return chunks;
}
/**
* Filter list with the elements which are not falsey.
*
* The definition of falsey can be seen at {@link #isFalsey}
*
* @param list The list to filter. Null is acceptable.
* @param List element type
* @return new compacted list
* @see #isFalsey
*/
public static List compact(List list) {
return filter(list, it -> !isFalsey(it));
}
/**
* Creates a new list which concatenating all lists in order.
*
* @param lists The lists to concatenate
* @param Element type
* @return concatenated new list
*/
@SafeVarargs
public static List concat(List... lists) {
if (lists.length == 0) {
return new ArrayList<>();
}
int capacity = 0;
for (List list : lists) {
if (isNotEmpty(list)) {
capacity += list.size();
}
}
if (capacity == 0) {
return new ArrayList<>();
}
ArrayList result = new ArrayList<>(capacity);
for (List list : lists) {
if (isNotEmpty(list)) {
result.addAll(list);
}
}
return result;
}
/**
* Iterate over the list and retaining the elements which are predicated true.
*
* @param list The list to iterate. Null is acceptable.
* @param predicate Predicate function. Cannot be null.
* @param Element type
* @return new filtered list
*/
public static List filter(List list, Predicate predicate) {
Objects.requireNonNull(predicate);
return filter(list, (e, i) -> predicate.test(e));
}
/**
* Iterate over the list and retaining the elements which are predicated true.
*
* @param list The list to iterate. Null is acceptable.
* @param predicate Predicate function with element index. Cannot be null.
* @param Element type
* @return new filtered list
*/
public static List filter(List list, BiPredicate predicate) {
Objects.requireNonNull(predicate);
if (list == null) {
return new ArrayList<>();
}
List result = new ArrayList<>();
int i = 0;
for (T element : list) {
if (predicate.test(element, i++)) {
result.add(element);
}
}
return result;
}
/**
* Create a list.
*
* @param args elements of list
* @param type of elements
* @return new list
*/
@SafeVarargs
public static List listOf(T... args) {
List list = Arrays.asList(args);
return list instanceof ArrayList ? (ArrayList) list : new ArrayList<>(list);
}
/**
* Create a list from an {@link Iterator}.
*
* @param itr which provide elements
* @param type of elements
* @return new list
*/
public static List listFrom(Iterator itr) {
List list = new ArrayList<>();
if (itr != null) {
while (itr.hasNext()) list.add(itr.next());
}
return list;
}
/**
* Map a list to another.
*
* @param iterable which to handle
* @param mapFn map function
* @param element type of list
* @param map result type
* @return new list
*/
public static List map(Iterable iterable, Function mapFn) {
Objects.requireNonNull(mapFn);
if (iterable == null) {
return new ArrayList<>();
}
int capacity = 16;
if (iterable instanceof List) {
List list = (List) iterable;
capacity = list.size();
}
List result = new ArrayList<>(capacity);
for (T t : iterable) {
result.add(mapFn.apply(t));
}
return result;
}
/**
* Mapping a list of elements to another.
*
* @param iterable to be mapped
* @param mapFn mapping function
* @param type of elements applied to mapping function
* @param type of elements returned by mapping function
* @return mapping result
*/
public static List map(Iterable iterable, ObjIntFunction mapFn) {
Objects.requireNonNull(mapFn);
if (iterable == null) {
return new ArrayList<>();
}
int capacity = 16;
if (iterable instanceof List) {
List list = (List) iterable;
capacity = list.size();
}
List result = new ArrayList<>(capacity);
int index = 0;
for (T t : iterable) {
result.add(mapFn.apply(t, index++));
}
return result;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf() {
return new HashMap<>();
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1) {
Map map = new HashMap<>();
map.put(k1, v1);
return map;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param k2 the second key
* @param v2 the second value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1, K k2, V v2) {
Map map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
return map;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param k2 the second key
* @param v2 the second value
* @param k3 the third key
* @param v3 the third value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1, K k2, V v2, K k3, V v3) {
Map map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
map.put(k3, v3);
return map;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param k2 the second key
* @param v2 the second value
* @param k3 the third key
* @param v3 the third value
* @param k4 the fourth key
* @param v4 the fourth value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
Map map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
map.put(k3, v3);
map.put(k4, v4);
return map;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param k2 the second key
* @param v2 the second value
* @param k3 the third key
* @param v3 the third value
* @param k4 the fourth key
* @param v4 the fourth value
* @param k5 the fifth key
* @param v5 the fifth value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
Map map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
map.put(k3, v3);
map.put(k4, v4);
map.put(k5, v5);
return map;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param k2 the second key
* @param v2 the second value
* @param k3 the third key
* @param v3 the third value
* @param k4 the fourth key
* @param v4 the fourth value
* @param k5 the fifth key
* @param v5 the fifth value
* @param k6 the sixth key
* @param v6 the sixth value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) {
Map map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
map.put(k3, v3);
map.put(k4, v4);
map.put(k5, v5);
map.put(k6, v6);
return map;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param k2 the second key
* @param v2 the second value
* @param k3 the third key
* @param v3 the third value
* @param k4 the fourth key
* @param v4 the fourth value
* @param k5 the fifth key
* @param v5 the fifth value
* @param k6 the sixth key
* @param v6 the sixth value
* @param k7 the seventh key
* @param v7 the seventh value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) {
Map map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
map.put(k3, v3);
map.put(k4, v4);
map.put(k5, v5);
map.put(k6, v6);
map.put(k7, v7);
return map;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param k2 the second key
* @param v2 the second value
* @param k3 the third key
* @param v3 the third value
* @param k4 the fourth key
* @param v4 the fourth value
* @param k5 the fifth key
* @param v5 the fifth value
* @param k6 the sixth key
* @param v6 the sixth value
* @param k7 the seventh key
* @param v7 the seventh value
* @param k8 the eighth key
* @param v8 the eighth value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) {
Map map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
map.put(k3, v3);
map.put(k4, v4);
map.put(k5, v5);
map.put(k6, v6);
map.put(k7, v7);
map.put(k8, v8);
return map;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param k2 the second key
* @param v2 the second value
* @param k3 the third key
* @param v3 the third value
* @param k4 the fourth key
* @param v4 the fourth value
* @param k5 the fifth key
* @param v5 the fifth value
* @param k6 the sixth key
* @param v6 the sixth value
* @param k7 the seventh key
* @param v7 the seventh value
* @param k8 the eighth key
* @param v8 the eighth value
* @param k9 the ninth key
* @param v9 the ninth value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
Map map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
map.put(k3, v3);
map.put(k4, v4);
map.put(k5, v5);
map.put(k6, v6);
map.put(k7, v7);
map.put(k8, v8);
map.put(k9, v9);
return map;
}
/**
* Create a {@link Map} with key-value pairs.
*
* @param k1 the first key
* @param v1 the first value
* @param k2 the second key
* @param v2 the second value
* @param k3 the third key
* @param v3 the third value
* @param k4 the fourth key
* @param v4 the fourth value
* @param k5 the fifth key
* @param v5 the fifth value
* @param k6 the sixth key
* @param v6 the sixth value
* @param k7 the seventh key
* @param v7 the seventh value
* @param k8 the eighth key
* @param v8 the eighth value
* @param k9 the ninth key
* @param v9 the ninth value
* @param k10 the tenth key
* @param v10 the tenth value
* @param key type
* @param value type
* @return new HashMap
*/
public static Map mapOf(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
Map map = new HashMap<>();
map.put(k1, v1);
map.put(k2, v2);
map.put(k3, v3);
map.put(k4, v4);
map.put(k5, v5);
map.put(k6, v6);
map.put(k7, v7);
map.put(k8, v8);
map.put(k9, v9);
map.put(k10, v10);
return map;
}
/**
* Check if a string is empty or not.
*
* @param string to be checked
* @return true if string is null, or it's length is 0
*/
public static boolean isEmpty(String string) {
return string == null || string.isEmpty();
}
/**
* Check if a {@link Map} is empty of not.
*
* @param map to be checked
* @return true if map is null, or it has no any entries.
*/
public static boolean isEmpty(Map map) {
return map == null || map.isEmpty();
}
/**
* Check if the collection is not empty.
*
* @param collection to be checked
* @param type of elements
* @return true if collection {@link #isEmpty(Collection)} is false
*/
public static boolean isNotEmpty(Collection collection) {
return !isEmpty(collection);
}
/**
* Check if a {@link Collection} is empty of not.
*
* @param c to be checked
* @return true if map is null, or it has no any entries.
*/
public static boolean isEmpty(Collection c) {
return c == null || c.isEmpty();
}
/**
* Check if a {@link Map} is not empty.
*
* @param map to be checked
* @return true if map {@link #isEmpty(Map)} is false
*/
public static boolean isNotEmpty(Map map) {
return !isEmpty(map);
}
/**
* Check if the string is not empty.
*
* @param string to be checked
* @return true if string {@link #isEmpty(String)} is false
*/
public static boolean isNotEmpty(String string) {
return !isEmpty(string);
}
/**
* Pads string
on the left and right sides if it's shorter than length
.
* Padding characters are truncated if they can't be evenly divided by length
.
*
* @param string The string to pad
* @param length The padding length
* @param chars The string used as padding
* @return Padded string
*/
public static String pad(String string, int length, String chars) {
if (length < 0) {
throw new IllegalArgumentException("Argument length cannot be less than 0");
}
string = defaultTo(string, "");
if (string.length() >= length) {
return string;
}
char[] padChars = (isEmpty(chars) ? " " : chars).toCharArray();
StringBuilder sb = new StringBuilder();
int padLength = length - string.length();
int padHalf = padLength / 2;
for (int i = 0; i < padHalf; i++) {
sb.append(padChars[i % padChars.length]);
}
sb.append(string);
for (int i = padHalf; i < padLength; i++) {
sb.append(padChars[i % padChars.length]);
}
return sb.toString();
}
/**
* Pads string
on the right side if it's shorter than length
.
* Padding characters are truncated if they exceed length
.
*
* @param string The string to pad
* @param length The padding length
* @param chars The string used as padding
* @return Padded string
*/
public static String padEnd(String string, int length, String chars) {
if (length < 0) {
throw new IllegalArgumentException("Argument length cannot be less than 0");
}
string = defaultTo(string, "");
if (string.length() >= length) {
return string;
}
char[] padChars = (isEmpty(chars) ? " " : chars).toCharArray();
StringBuilder sb = new StringBuilder(string);
int padLength = length - string.length();
for (int i = 0; i < padLength; i++) {
sb.append(padChars[i % padChars.length]);
}
return sb.toString();
}
/**
* Pads string
on the left side if it's shorter than length
.
* Padding characters are truncated if they exceed length
.
*
* @param string The string to pad
* @param length The padding length
* @param chars The string used as padding
* @return Padded string
*/
public static String padStart(String string, int length, String chars) {
if (length < 0) {
throw new IllegalArgumentException("Argument length cannot be less than 0");
}
string = defaultTo(string, "");
if (string.length() >= length) {
return string;
}
char[] padChars = (isEmpty(chars) ? " " : chars).toCharArray();
StringBuilder sb = new StringBuilder();
int padLength = length - string.length();
for (int i = 0; i < padLength; i++) {
sb.append(padChars[i % padChars.length]);
}
sb.append(string);
return sb.toString();
}
/**
* Replace all substrings that match the given pattern with the result of the function.
* For example:
*
* var pattern = Pattern.compile("\\{}");
* System.out.println(replaceAll("a={} b={} c={}", pattern, i -> "{" + i + "}"));
*
* Output:
*
* a={0} b={1} c={2}
*
*
* If any of the arguments is {@code null}, the method will return the original string.
*
* @param string to be replaced
* @param pattern to match
* @param replacementGen to generate the replacement string by index
* @return the replaced string
*/
public static String replaceAll(String string, Pattern pattern, IntFunction replacementGen) {
if (string == null || pattern == null || replacementGen == null) {
return string;
}
var matcher = pattern.matcher(string);
boolean result = matcher.find();
if (result) {
StringBuilder sb = new StringBuilder();
int start = 0;
do {
matcher.appendReplacement(sb, replacementGen.apply(start++));
result = matcher.find();
} while (result);
matcher.appendTail(sb);
return sb.toString();
}
return string;
}
/**
* Create an empty list stage.
*
* @param element type
* @return list stage
*/
public static Seq empty() {
return Seq.empty();
}
/**
* Create a stage from elements.
*
* @param args elements to be handled
* @param type of elements
* @return list stage
*/
@SafeVarargs
public static Seq just(T... args) {
return tConsumer -> {
for (T t : args) {
tConsumer.accept(t);
}
};
}
/**
* Handle a range.
*
* @param start range start - included
* @param end range end - excluded
* @return list stage
*/
public static Seq range(int start, int end) {
return new Range(start, end)::forEach;
}
/**
* Get the first element from {@link Iterable}.
*
* Warning: When {@link Optional#empty()} is returned, uou cannot recognize
* that the iterable
is empty, or it's first element is null.
*
* @param iterable to be handled
* @param type of the first element
* @return {@link Optional} of the first element
*/
public static Optional first(Iterable iterable) {
if (iterable == null) {
return Optional.empty();
}
if (iterable instanceof List) {
List list = (List) iterable;
return list.isEmpty() ? Optional.empty() : Optional.ofNullable(list.get(0));
}
Iterator itr = iterable.iterator();
return itr.hasNext() ? Optional.ofNullable(itr.next()) : Optional.empty();
}
/**
* Alias for {@link #first(Iterable)}.
*
* @param iterable to be handled
* @param type of the first element
* @return {@link Optional} of the first element
*/
public static Optional head(Iterable iterable) {
return first(iterable);
}
/**
* Map elements to {@link Iterable}s in order and flat them into next stage.
*
* @param flatMapFn which map an element to an {@link Iterable}
* @param flatten elements type
* @return next stage
*/
public static List flatMap(Iterable iterable, Function> flatMapFn) {
Objects.requireNonNull(flatMapFn);
if (iterable == null) {
return new ArrayList<>();
}
ArrayList result = new ArrayList<>();
for (T t : iterable) {
Iterable itr = flatMapFn.apply(t);
if (itr != null) {
itr.forEach(result::add);
}
}
return result;
}
/**
* Mapping {@link Map} values to another.
*
* @param map {@link Map} to be handled.
* @param mapFn mapping function
* @param type of {@link Map} key
* @param type of {@link Map} value
* @param type of mapping result
* @return a new map
*/
public static Map mapValues(Map map, Function mapFn) {
Objects.requireNonNull(mapFn);
if (isEmpty(map)) {
return new HashMap<>();
}
Map result = new HashMap<>();
map.forEach((k, v) -> result.put(k, mapFn.apply(v)));
return result;
}
/**
* Mapping {@link Map} values to another.
*
* @param map {@link Map} to be handled.
* @param mapFn mapping function which accept key as the second argument
* @param type of {@link Map} key
* @param type of {@link Map} value
* @param type of mapping result
* @return a new map
*/
public static Map mapValues(Map map, BiFunction mapFn) {
Objects.requireNonNull(mapFn);
if (isEmpty(map)) {
return new HashMap<>();
}
Map result = new HashMap<>();
map.forEach((k, v) -> result.put(k, mapFn.apply(v, k)));
return result;
}
/**
* Create a new {@link Map} with new keys, which are mapped from the old keys.
* If two new keys of old keys are the same, the last reached entry would be discarded.
*
* @param map to be handled
* @param mapFn mapping function
* @param type of keys
* @param type of values
* @param type of mapped keys
* @return new {@link Map}
*/
public static Map mapKeys(Map map, Function mapFn) {
Objects.requireNonNull(mapFn);
if (isEmpty(map)) {
return new HashMap<>();
}
Map result = new HashMap<>();
map.forEach((k, v) -> {
K2 k2 = mapFn.apply(k);
if (!result.containsKey(k2)) {
result.put(k2, v);
}
});
return result;
}
/**
* Create a new {@link Map} with new keys, which are mapped from the old keys.
* If two new keys of different entries are equal, the last reached entry would be discarded.
*
* @param map to be handled
* @param mapFn mapping function
* @param type of keys
* @param type of values
* @param type of mapped keys
* @return new {@link Map}
*/
public static Map mapKeys(Map map, BiFunction mapFn) {
Objects.requireNonNull(mapFn);
if (isEmpty(map)) {
return new HashMap<>();
}
Map result = new HashMap<>();
map.forEach((k, v) -> {
K2 k2 = mapFn.apply(k, v);
if (!result.containsKey(k2)) {
result.put(k2, v);
}
});
return result;
}
/**
* Create a new {@link Map} from {@link Iterable}.
* The values are {@link Iterable} elements,
* and the keys are computed from corresponding elements.
* If two keys of different elements are equal, the first entry would be covered.
*
* @param iterable to be handled
* @param toKey function mapping an element to it's key
* @param type of iterable elements
* @param type of key
* @return new {@link Map}
*/
public static Map keyBy(Iterable iterable, Function toKey) {
Objects.requireNonNull(toKey);
if (iterable == null) {
return new HashMap<>();
}
Map result = new HashMap<>();
iterable.forEach(it -> result.computeIfAbsent(toKey.apply(it), k -> it));
return result;
}
/**
* Create a new {@link Map} from {@link Iterable}.
* The values are {@link List} of elements with the same key,
* and the keys are computed from corresponding elements.
*
* @param iterable to be handled
* @param toKey function mapping an element to it's key
* @param type of iterable elements
* @param type of key
* @return new {@link Map}
*/
public static Map> groupBy(Iterable iterable, Function toKey) {
Objects.requireNonNull(toKey);
if (iterable == null) {
return new HashMap<>();
}
Map> result = new HashMap<>();
iterable.forEach(it -> result.computeIfAbsent(toKey.apply(it), k -> new ArrayList<>()).add(it));
return result;
}
/**
* Order iterable into a list by element keys with specified direction.
*
* @param iterable to be ordered
* @param toKey a function to get element key
* @param direction order direction
* @param type of elements
* @param type of element keys
* @return a list with sorted elements
*/
public static > List orderBy(Iterable iterable, Function toKey, Direction direction) {
Objects.requireNonNull(toKey);
Objects.requireNonNull(direction);
if (iterable == null) {
return new ArrayList<>();
}
List list = $.listFrom(iterable.iterator());
Comparator comparator = direction == Direction.DESC ? descComparator(toKey) : ascComparator(toKey);
list.sort(comparator);
return list;
}
/**
* Reducing {@link Iterable} to a value which is the accumulated result of running each element in
* {@link Iterable} through reducer.
*
* @param iterable to be handled
* @param initValue the init value
* @param reducer reducer
* @param type of elements
* @param type of result
* @return reducing result
*/
public static R reduce(Iterable iterable, R initValue, BiFunction reducer) {
Objects.requireNonNull(reducer);
if (iterable == null) {
return initValue;
}
R result = initValue;
for (T t : iterable) {
result = reducer.apply(result, t);
}
return result;
}
/**
* Reducing {@link Iterable} to a value which is the accumulated result of running each element in
* {@link Iterable} through reducer.
*
* @param map to be handled
* @param initValue the init value
* @param reducer reducer
* @param type of map keys
* @param type of map values
* @param type of result
* @return reducing result
*/
public static R reduce(Map map, R initValue, Function3 reducer) {
Objects.requireNonNull(reducer);
if (map == null) {
return initValue;
}
final Env1 env = new Env1<>();
env.t = initValue;
map.forEach((k, v) -> env.t = reducer.apply(env.t, k, v));
return env.t;
}
private static class Env1 {
T t;
}
/**
* Reverse elements from an iterable into a list.
*
* @param iterable to be reversed
* @param type of elements
* @return a list of elements in reversed order
*/
public static List reverse(Iterable iterable) {
ArrayList list = reduce(iterable, new ArrayList<>(), (li, it) -> {
li.add(it);
return li;
});
int last = list.size() - 1;
int half = list.size() / 2;
for (int i = 0; i < half; i++) {
T t1 = list.get(i);
T t2 = list.get(last - i);
list.set(last - i, t1);
list.set(i, t2);
}
return list;
}
/**
* Take the first n
elements.
*
* @param iterable to be handled.
* @param n count of element to be taken which should be greater than 0
* @param type of elements
* @return a list of elements to be taken
*/
public static List take(Iterable iterable, int n) {
if (n < 1) {
throw new IllegalArgumentException("You should take at least one element.");
}
if (iterable == null) {
return new ArrayList<>();
}
ArrayList list = new ArrayList<>();
int i = 0;
for (T t : iterable) {
if (i < n) {
list.add(t);
i++;
} else {
break;
}
}
return list;
}
/**
* Take elements from iterable until the first element predicated to be false is found.
*
* @param iterable to be handled.
* @param predicate a function to test elements
* @param type of elements
* @return a list of elements to be taken
*/
public static List takeWhile(Iterable iterable, Predicate predicate) {
Objects.requireNonNull(predicate);
if (iterable == null) {
return new ArrayList<>();
}
ArrayList list = new ArrayList<>();
for (T t : iterable) {
if (predicate.test(t)) {
list.add(t);
} else {
break;
}
}
return list;
}
/**
* Add all elements from iterable into a {@link Set}.
*
* @param iterable to be handled
* @param type of elements
* @return a set of elements from iterable
*/
public static Set toSet(Iterable iterable) {
if (iterable == null) {
return new HashSet<>();
}
Set set = new HashSet<>();
iterable.forEach(set::add);
return set;
}
/**
* Iterates over elements of {@link Iterable} and each element will be consumed by handler in order.
*
* @param iterable to be handled
* @param handler element handler
* @param type of elements
*/
public static void forEach(Iterable