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]]
- 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 ([email protected])
- smithros as Rostyslav Koval ([email protected])
- ashutosh as Ashutosh Singh ([email protected])
- dykov as Oleksii Dykov ([email protected])