enumerable4j is a Ruby's well known Enumerable ported to java as interface with set of default methods which simplify typical operations with collections.
/** * The iterable with primitive operations witch simplify typical actions like count, map, etc. * * The API is based on Ruby's Enumerable: * https://ruby-doc.org/core-2.6/Enumerable.html. * * The Enumerable provides methods with several traversal and searching features, and with the * ability to sort. The class must provide a method each, which yields successive members of the * collection. * * @param <T> The type of entities. * @since 0.1.0 */ public interface Enumerable<T> extends Collection<T> { /** * Passes each element of the collection to the each given function. * The given null predicates are skipped. * If no predicate (null) is given, then false is returned instead. * @param first The function to match each element. * @param other The array of functions to match each element. * @return True if the functions never return false. */ default boolean all(Predicate<T> first, Predicate<T>... other) { // ... } /** * Passes at least one element of the collection to the each given function. * The given null predicates are skipped. * If no predicate (null) is given, then false is returned instead. * @param first The function to match at least one element. * @param other The array of functions to match at least one element. * @return True if functions never return true at least once. */ default boolean any(Predicate<T> first, Predicate<T>... other) { // ... } /** * Doesn't passes elements of the collection to the each given function. * The given null predicates are skipped. * If no predicate (null) is given, then true is returned instead. * @param first The function to match none elements. * @param other The array of functions to match none elements. * @return True if the functions never returns false or nil. */ default boolean none(Predicate<T> first, Predicate<T>... other) { // ... } /** * Returns an enumerable containing all elements of enumerable for which the given functions * return a true value. * The given null predicates are skipped. * If no predicate (null) is given, then an empty enumerable is returned instead. * @param first The function to match each element. * @param other The array of functions to match each element. * @return The enumerable. */ default Enumerable<T> select(Predicate<T> first, Predicate<T>... other) { // ... } /** * Returns an enumerable containing all elements of enumerable for which the given function * returns a false value. * The given null predicates are skipped. * If no predicate (null) is given, then 'this' is returned instead. * @param first The function to match each element. * @param other The array of functions to match each element. * @return The enumerable. */ default Enumerable<T> reject(Predicate<T> first, Predicate<T>... other) { // ... } /** * Returns an enumerable containing first element of enumerable for which the given function * returns a true value. * The given null predicates are skipped. * If no predicate (null) is given, or no element found then null is returned instead. * @param first The function to match each element. * @param other The array of functions to match each element. * @return The first element of enumerable, that matches predicate. */ default T find(Predicate<T> first, Predicate<T>... other) { // ... } /** * Returns an enumerable containing first element of enumerable for which the given function * returns a true value. * The given null predicates are skipped. * If no predicate (null) is given, or no element found then alternative is returned instead. * @param alt The alternative to return in case of null predicate or no element found. * @param first The function to match each element. * @param other The array of functions to match each element. * @return The first element of enumerable, that matches predicate. */ default T find(X alt, Predicate<T> first, Predicate<T>... other) { // ... } /** * Returns an enumerable containing all elements, on which given function was applied. * If no function (null) is given, then 'this' is returned instead. * @param fnc The function to apply to each element. * @param <R> The type of target entity. * @return The enumerable. */ default <R> Enumerable<R> map(Function<? super T, ? extends R> fnc) { // ... } /** * Returns the number of elements that are present in enumerable for which the given * function return true. * The given null predicates are skipped. * If no function (null) is given, then 0 is returned instead. * @param first The function to match each element. * @param other The array of functions to match each element. * @return Number of elements satisfying the given function. */ default long count(Predicate<T> first, Predicate<T>... other) { // ... } /** * Returns a result of the reduction of the elements in this stream, * using provided identity value and accumulation function operator. * If no function (null) is given, then identity is returned instead. * @param idn The identity value of the accumulation function. * @param opr The accumulation function operator which combining previous and current values. * @return Result of of combining elements. */ default T reduce(T idn, BinaryOperator<T> opr) { // ... } /** * Returns an enumerable containing all elements of enumerable * after the first one which corresponds the condition. * If no predicate (null) is given, then empty enumerable is returned instead. * @param prd The function to match element after which enumerable elements should be returned. * @return The enumerable. */ default Enumerable<T> after(Predicate<T> prd) { // ... } /** * Returns an enumerable containing a certain number of elements of enumerable * after the first one which corresponds the condition. * If no predicate (null) is given, then empty enumerable is returned instead. * @param prd The function to match element after which enumerable elements should be returned. * @param size The number of elements the enumerable should be limited to. * @return The enumerable. * @throws IllegalArgumentException If the size is negative. */ default Enumerable<T> after(Predicate<T> prd, long size) { // ... } /** * Returns the next element of enumerable after the first one which corresponds the condition. * If no predicate (null) is given, or no element found then null is returned instead. * @param prd The function to match element after which enumerable element should be returned. * @return The next element of enumerable after the first one which corresponds the condition. */ default T next(Predicate<T> prd) { // ... } /** * Returns the next element of enumerable after the first one which corresponds the condition. * If no predicate (null) is given, or no element found then alternative is returned instead. * @param prd The function to match element after which enumerable element should be returned. * @param alt The alternative to return in case of null predicate or no element found. * @return The next element of enumerable after the first one which corresponds the condition. */ default T next(Predicate<T> prd, T alt) { // ... } /** * Returns a new enumerable which contains the items of the original collection * and the added items of the given enumerable. * If no enumerable (null) is given, then 'this' is returned instead. * @param enm The given enumerable. * @return The enumerable. */ default Enumerable<T> chain(Enumerable<T> enm) { // ... } /** * Returns an enumerable consisting of the elements of the collection, * additionally performing the provided action on each element of the enumerable. * @param act An action to perform on the elements. * @return The enumerable. */ default Enumerable<T> each(Consumer<T> act) { // ... } /** * Returns an enumerable containing first elements of specified size from the enumerable. * @param num The number of elements the enumerable should be limited to. * @return The enumerable. * @throws IllegalArgumentException If the size is negative. */ default Enumerable<T> take(long num) { // ... } /** * Drops first elements of specified size, * and returns an enumerable containing the rest of the elements. * @param num The number of elements to be dropped. * @return The enumerable. * @throws IllegalArgumentException If the size is negative. */ default Enumerable<T> drop(long num) { // ... } /** * The method returns true if the functions return true exactly once. * The given null predicates are skipped. * If no predicate (null) is given, then false is returned instead. * @param first The function to match each element. * @param other The array of functions to match each element. * @return True if the functions returns true exactly once. */ default boolean one(Predicate<T> first, Predicate<T>... other) { // ... } /** * Returns a new enumerable containing the unique elements. * It compares values using the {@link #hashCode} and {@link #equals} methods for efficiency. * @return The enumerable. */ default Enumerable<T> uniq() { // ... } /** * Returns a new enumerable containing the unique elements which corresponds the condition * of the given function. * If no function (null) is given, then empty enumerable is returned instead. * @param fnc The function to apply to each element. * @param <R> The type of function result entity. * @return The enumerable. */ default <R> Enumerable<T> uniq(Function<? super T, ? extends R> fnc) { // ... } /** * Returns an enumerable of collections which contains each element of original collection * and corresponding elements from each argument collections. * The length of the resulting enumerable is {@link Enumerable#size}. * If the size of any argument is less than {@link Enumerable#size}, null values are supplied. * @param first The array of enumerable to merge. * @param other The array of enumerable to merge. * @return The enumerable. */ default Enumerable<Enumerable<T>> zip(Enumerable<T> first, Enumerable<T>... other) { // ... } }See more.
-
Get the latest version here:
<dependency> <groupId>io.github.dgroup</groupId> <artifactId>enumerable4j</artifactId> <version>${version}</version> </dependency>
-
Assign the Enumerable interface with default methods to your own collection
/** * The collection which you implemented in your project for some purposes. */ public class YourOwnCollection<T> extends Collection<T> implements Enumerable<T> { // }
You may (but not required) override the default implementations of methods from Enumerable if needed.
-
Java version required: 1.8+.
-
Comparing matrix with other libs:
enumerable4j (MIT) Java 8 cactoos (MIT) eclipse-collections (EDL) .all(...).stream().allMatch(...)new And<>(...,...).value()tbd .any(...).stream().anyMatch(...)new Or<>(...,...).value()tbd .none(...).stream().noneMatch(...)new And<>(...,...).value()tbd .select(...).stream().filter(...).collect(Collectors.toList())new Filtered<>(...,...)tbd .reject(...).stream().filter((...).negate()).collect(Collectors.toList())new Filtered<>(...,...)tbd .map(...).stream().map(...).collect(Collectors.toList())new Mapped<>(...,...)tbd .count(...).stream().filter(...).count()new Filtered<>(...).size()tbd .find(...).stream().filter(...).findFirst().orElse(...)new FirstOf<>(...,...).value()tbd .reduce(...,...).stream().reduce(...,...)new Reduced<>(...,...).value()tbd .after(...)tbd .next(...)tbd .chain(...)tbd .each(...).stream().forEach(...)new ForEach<>(...).exec(...)tbd .take(...).stream().limit(...).collect(Collectors.toList())new Sliced<>(0,...,...)tbd .drop(...).stream().skip(...).collect(Collectors.toList())new Sliced<>(...,...,...)tbd .one(...).stream().filter(...).count() == 1new Filtered<>(...).size() == 1tbd .uniq(...).stream().skip(...).collect(Collectors.toSet())tbd .zip(...)tbd
YourOwnCollection<Integer> src = ... // with elements [1, 2, 3] boolean allPositive = src.all(val -> val > 0); // true YourOwnCollection<Integer> src = ... // with elements [-1, 0, 1] boolean oneIsPositive = src.any(val -> val > 0); // true YourOwnCollection<Integer> src = ... // with elements [-2, -1, 0] boolean noneIsPositive = src.none(val -> val > 0); // true YourOwnCollection<Integer> src = ... // with elements [-1, 1, 2] Enumerable<Integer> positive = src.select(val -> val > 0); // [1, 2] YourOwnCollection<Integer> src = ... // with elements [-1, 1, 2] Enumerable<Integer> negative = src.reject(val -> val > 0); // [-1]YourOwnCollection<Integer> src = ... // with elements [0, 1, 2] Enumerable<Integer> positive = src.map(val -> val + 1); // [1, 2, 3] YourOwnCollection<Integer> src = ... // with elements [-1, 0, 1] long countNegative = src.count(val -> val < 0); // 1YourOwnCollection<Integer> src = ... // with elements [-1, 0, 1] Integer first = src.find(val -> val > 0); // 1 Integer alternative = src.find(50, val -> val > 5); // 50 YourOwnCollection<Integer> src = ... // with elements [1, 2, 3] Integer sum = src.reduce(0, Integer::sum); // 6 YourOwnCollection<Integer> src = ... // with elements [2, 3, 4, 5, 6] Enumerable<Integer> afterThree = src.after(val -> val == 3); // [4, 5, 6] Enumerable<Integer> firstTwoAfterThree = src.after(val -> val == 3, 2); // [4, 5] YourOwnCollection<Integer> src = ... // with elements [1, 2, 3, 4] Integer next = src.next(val -> val == 2); // 3 Integer alternative = src.next(val -> val > 5, -1); // -1 YourOwnCollection<Integer> src = ... // with elements [1, 2] Enumerable<Integer> joined = src.chain(new Linked<>(3)).chain(new Linked<>(4, 5)); // [1, 2, 3, 4, 5] YourOwnCollection<Integer> src = ... // with elements [1, 2, 3] Enumerable<Integer> buf = src.each(System.out::print); // [1, 2, 3] , printed: "123"YourOwnCollection<Integer> src = ... // with elements [1, 2, 3] Enumerable<Integer> taken = src.take(2); // [1, 2]YourOwnCollection<Integer> src = ... // with elements [1, 2, 3] Enumerable<Integer> taken = src.drop(2); // [3]YourOwnCollection<Integer> src = ... // with elements [-1, 0, 1] boolean onePositive = src.one(val -> val > 0); // trueYourOwnCollection<Linked<Integer>> src = ... // with elements [[1, 2], [3, 4], [1, 2], [3, 4, 5]] Enumerable<Linked<Integer>> unique = src.uniq(); // [[1, 2], [3, 4], [3, 4, 5]] Enumerable<Linked<Integer>> uniqueByKey = src.uniq(enm -> enm.get(0)); // [[1, 2], [3, 4]]YourOwnCollection<Integer> src = ... // with elements [1, 2, 3] YourOwnCollection<Integer> src2 = ... // with elements [4, 5, 6] Enumerable<Enumerable<Integer>> zip = src.zip(src2); // [[1, 4]], [2, 5], [3, 6]]- Pull requests are welcome! Don't forget to add your name to contribution section and run this, beforehand:
mvn -Pqulice clean install
- Everyone interacting in this project’s codebases, issue trackers, chat rooms is expected to follow the code of conduct.
- Latest maven coordinates here:
<dependency> <groupId>io.github.dgroup</groupId> <artifactId>enumerable4j</artifactId> <version>${version}</version> </dependency>
- dgroup as Yurii Dubinka (yurii.dubinka@gmail.com)
- smithros as Rostyslav Koval (kovalr2000@gmail.com)
- ashutosh as Ashutosh Singh (s.ashutosh@hotmail.com)
- dykov as Oleksii Dykov (dykovoleksii@gmail.com)