Amazing Ruby's "Enumerable" ported to Java
MIT License
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() == 1 |
new Filtered<>(...).size() == 1 |
tbd |
.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); // 1
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
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); // true
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]]
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]]
mvn -Pqulice clean install
<dependency>
<groupId>io.github.dgroup</groupId>
<artifactId>enumerable4j</artifactId>
<version>${version}</version>
</dependency>