Skip to content

dgroup/enumerable4j

Folders and files

NameName
Last commit message
Last commit date
Apr 15, 2021
Jun 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Jul 10, 2021
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Mar 6, 2021
Aug 28, 2023
May 30, 2021

Repository files navigation

Maven Javadocs License: MIT Commit activity Hits-of-Code

CI 0pdd Dependency Status Known Vulnerabilities

DevOps By Rultor.com EO badge We recommend IntelliJ IDEA

Qulice Maintainability Rating Codebeat Badge Codacy Badge Codecov

Overview

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.

How to use

  1. Get the latest version here:

    <dependency>
      <groupId>io.github.dgroup</groupId>
      <artifactId>enumerable4j</artifactId>
      <version>${version}</version>
    </dependency>
  2. 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.

  3. Java version required: 1.8+.

  4. 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() == 1 new Filtered<>(...).size() == 1 tbd
    .uniq(...) .stream().skip(...).collect(Collectors.toSet()) tbd
    .zip(...) tbd

.all

YourOwnCollection<Integer> src = ...           // with elements [1, 2, 3]   
boolean allPositive = src.all(val -> val > 0); // true 

.any

YourOwnCollection<Integer> src = ...             // with elements [-1, 0, 1]
boolean oneIsPositive = src.any(val -> val > 0); // true 

.none

YourOwnCollection<Integer> src = ...               // with elements [-2, -1, 0]
boolean noneIsPositive = src.none(val -> val > 0); // true 

.select

YourOwnCollection<Integer> src = ...                       // with elements [-1, 1, 2]
Enumerable<Integer> positive = src.select(val -> val > 0); // [1, 2] 

.reject

YourOwnCollection<Integer> src = ...                       // with elements [-1, 1, 2]
Enumerable<Integer> negative = src.reject(val -> val > 0); // [-1]

.map

YourOwnCollection<Integer> src = ...                    // with elements [0, 1, 2]
Enumerable<Integer> positive = src.map(val -> val + 1); // [1, 2, 3] 

.count

YourOwnCollection<Integer> src = ...            // with elements [-1, 0, 1]
long countNegative = src.count(val -> val < 0); // 1

.find

YourOwnCollection<Integer> src = ...                // with elements [-1, 0, 1]
Integer first = src.find(val -> val > 0);           // 1 
Integer alternative = src.find(50, val -> val > 5); // 50                

.reduce

YourOwnCollection<Integer> src = ...       // with elements [1, 2, 3]   
Integer sum = src.reduce(0, Integer::sum); // 6 

.after

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]                

.next

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                

.chain

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] 

.each

YourOwnCollection<Integer> src = ...                   // with elements [1, 2, 3]
Enumerable<Integer> buf = src.each(System.out::print); // [1, 2, 3] , printed: "123"

.take

YourOwnCollection<Integer> src = ...     // with elements [1, 2, 3]
Enumerable<Integer> taken = src.take(2); // [1, 2]

.drop

YourOwnCollection<Integer> src = ...     // with elements [1, 2, 3]
Enumerable<Integer> taken = src.drop(2); // [3]

.one

YourOwnCollection<Integer> src = ...           // with elements [-1, 0, 1]
boolean onePositive = src.one(val -> val > 0); // true

.uniq

YourOwnCollection<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]]

.zip

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]]

How to contribute?

EO badge

  1. Pull requests are welcome! Don't forget to add your name to contribution section and run this, beforehand:
    mvn -Pqulice clean install
  2. Everyone interacting in this project’s codebases, issue trackers, chat rooms is expected to follow the code of conduct.
  3. Latest maven coordinates here:
    <dependency>
        <groupId>io.github.dgroup</groupId>
        <artifactId>enumerable4j</artifactId>
        <version>${version}</version>
    </dependency>

Contributors