Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.codefilarete.tool.collection;
import javax.annotation.Nullable;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedMap;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.codefilarete.tool.Duo;
import org.codefilarete.tool.collection.PairIterator.UntilBothIterator;
import org.codefilarete.tool.trace.ModifiableInt;
/**
* @author Guillaume Mary
*/
public final class Iterables {
/**
* Transforms an {@link Iterator} to an {@link Iterable}
*
* @param iterator the surrogate
* @param the content typed of the {@link Iterator}
* @return an {@link Iterable} which {@link Iterable#iterator()} returns the given {@link Iterator}
*/
public static Iterable asIterable(Iterator iterator) {
return () -> iterator;
}
/**
* @param iterable a nullable {@link Iterable}
* @return the first element of the argument or null if argument is empty
*/
@Nullable
public static E first(@Nullable Iterable iterable) {
return first(iterable, null);
}
/**
* @param iterable a nullable {@link Iterable}
* @return the first element of the argument or the given default value if argument is empty
*/
public static E first(@Nullable Iterable iterable, E defaultValue) {
if (iterable == null) {
return defaultValue;
} else {
return first(iterable.iterator());
}
}
/**
* @param iterator a nullable {@link Iterator}
* @return the first element of the argument or null if argument is empty
*/
@Nullable
public static E first(Iterator iterator) {
return first(iterator, null);
}
/**
* @param iterator a nullable {@link Iterator}
* @return the first element of the argument or the given default value if argument is empty
*/
public static E first(Iterator iterator, E defaultValue) {
return iterator != null && iterator.hasNext() ? iterator.next() : defaultValue;
}
/**
* Optimized version of {@link #first(Iterable)} for {@link List} : will use {@code get(0)} on the list to get first element (instead of hasNext())
*
* @param iterable a nullable {@link List}
* @return the first element of the argument or null if argument is empty
*/
@Nullable
public static E first(List iterable) {
return first(iterable, null);
}
/**
* Optimized version of {@link #first(Iterable)} for {@link List} : will use {@code get(0)} on the list to get first element (instead of hasNext())
*
* @param iterable a nullable {@link List}
* @return the first element of the argument or the given default value if argument is empty
*/
public static E first(List iterable, E defaultValue) {
if (Collections.isEmpty(iterable)) {
return defaultValue;
} else {
return iterable.get(0);
}
}
/**
* Optimized version of {@link #first(Iterable)} for arrays : will use {@code [0]} on the array to get first element (instead of hasNext())
*
* @param array a nullable array
* @return the first element of the argument or null if argument is empty
*/
@Nullable
public static E first(E[] array) {
return first(array, null);
}
/**
* Optimized version of {@link #first(Iterable)} for arrays : will use {@code [0]} on the array to get first element (instead of hasNext())
*
* @param array a nullable array
* @return the first element of the argument or the given default value if argument is empty
*/
public static E first(E[] array, E defaultValue) {
if (Arrays.isEmpty(array)) {
return defaultValue;
} else {
return array[0];
}
}
/**
* Returns the first entry of a {@link Map}, only makes sense on a {@link SortedMap} or a {@link LinkedHashMap}
*
* @param iterable a Map : Sorted or Linked (else it has no purpose)
* @return the first {@link Entry} of the Map, or null if argument is empty or null
*/
@Nullable
public static Map.Entry first(@Nullable Map iterable) {
return first(iterable, null);
}
/**
* Returns the first entry of a {@link Map}, only makes sense on a {@link SortedMap} or a {@link LinkedHashMap}
*
* @param iterable a Map : Sorted or Linked (else it has no purpose)
* @return the first {@link Entry} of the Map, or the given default {@link Entry} if argument is empty or null
*/
public static Map.Entry first(@Nullable Map iterable, Map.Entry defaultValue) {
if (iterable == null) {
return defaultValue;
} else {
return first(iterable.entrySet());
}
}
/**
* Returns the first value of a {@link Map}, only makes sense on a {@link SortedMap} or a {@link LinkedHashMap}
*
* @param iterable a Map : Sorted or Linked (else it has no purpose)
* @return the first value of the Map, null if argument is null
*/
@Nullable
public static V firstValue(@Nullable Map, V> iterable) {
return firstValue(iterable, null);
}
/**
* Returns the first value of a {@link Map}, only makes sense on a {@link SortedMap} or a {@link LinkedHashMap}
*
* @param iterable a Map : Sorted or Linked (else it has no purpose)
* @return the first value of the Map, or the given default value if argument is empty or null
*/
@Nullable
public static V firstValue(@Nullable Map, V> iterable, V defaultValue) {
Entry, V> firstEntry = first(iterable);
return firstEntry == null ? defaultValue : firstEntry.getValue();
}
/**
* Indicates if an {@link Iterable} is empty or not.
* Implementation is optimized for {@link Collection}s by using {@link Collection#isEmpty()}, else will use {@link Iterator#hasNext()}.
*
* @param iterable a nullable {@link Iterable}
* @return true if given argument is null or has no element
*/
public static boolean isEmpty(@Nullable Iterable iterable) {
return iterable == null
|| ((iterable instanceof Collection) ? ((Collection) iterable).isEmpty() : !iterable.iterator().hasNext()) ;
}
/**
* @param iterable a nullable {@link List}
* @return the last element of the argument or null if argument is empty or null
*/
@Nullable
public static E last(@Nullable List iterable) {
return last(iterable, null);
}
/**
* @param iterable a nullable {@link List}
* @return the last element of the argument or the given default value if argument is empty or null
*/
public static E last(@Nullable List iterable, E defaultValue) {
if (iterable == null || iterable.isEmpty()) {
return defaultValue;
} else {
return iterable.get(iterable.size() - 1);
}
}
/**
* @param iterable a nullable {@link Iterable}
* @return the last element of the argument or null
*/
public static E last(@Nullable Iterable iterable) {
return last(iterable, null);
}
/**
* @param iterable a nullable {@link Iterable}
* @param defaultValue value to be return if iterable is empty
* @return the last element of the argument or the given default value if argument is empty or null
*/
public static E last(@Nullable Iterable iterable, @Nullable E defaultValue) {
if (iterable == null) {
return defaultValue;
} else {
Iterator iterator = iterable.iterator();
E result = null;
if (!iterator.hasNext()) {
result = defaultValue;
}
while (iterator.hasNext()) {
result = iterator.next();
}
return result;
}
}
/**
* Collects iterable elements until a given element
*
* @param iterable the iterable to scan
* @param untilExcluded stopping element
* @param elements type
* @return firsts elements of the iterable that differ from {@code untilExcluded}, in the iteration order, without {@code untilExcluded}
*/
public static List head(Iterable iterable, E untilExcluded) {
List result = new ArrayList<>();
for (E e : iterable) {
if (untilExcluded.equals(e)) {
break;
} else {
result.add(e);
}
}
return result;
}
/**
* Maps an {@link Iterable} on a key took as a {@link Function} of its beans. The value is also a function took on them.
*
* @param iterable the iterable to map
* @param keyMapper the key provider
* @param valueMapper the value provider
* @param iterated objets type
* @param keys type
* @param values type
* @return a new (Hash)Map
*/
public static Map map(Iterable iterable,
Function super T, ? extends K> keyMapper,
Function super T, ? extends V> valueMapper) {
return map(iterable, keyMapper, valueMapper, HashMap::new);
}
/**
* Maps an {@link Iterable} on a key took as a {@link Function} of its beans. The value is also a function took on them.
*
* @param iterable the iterable to map
* @param keyMapper the key provider
* @param valueMapper the value provider
* @param target the map to be filled
* @param iterated objets type
* @param keys type
* @param values type
* @param returned {@link Map} type
* @return a new {@link Map} of type M filled with key and values from given parameters
*/
public static > M map(Iterable iterable,
Function super T, ? extends K> keyMapper,
Function super T, ? extends V> valueMapper,
Supplier target) {
M result = target.get();
for (T t : iterable) {
result.put(keyMapper.apply(t), valueMapper.apply(t));
}
return result;
}
/**
* Maps objects of an {@link Iterable} over a key took as a {@link Function} of them.
*
* @param iterable the iterable to map
* @param keyMapper the key provider
* @param iterated objets type
* @param keys type
* @return a new (Hash)Map
*/
public static Map map(Iterable iterable, Function super T, ? extends K> keyMapper) {
return map(iterable, keyMapper, Function.identity());
}
/**
* Maps an {@link Iterable} on a key took as a {@link Function} of its beans. The value is also a function took on them.
*
* @param iterable the iterable to map
* @param keyMapper the key provider
* @param target the map to be filled
* @param iterated objets type
* @param keys type
* @param returned {@link Map} type
* @return a new {@link Map} of type M filled with key and values from given parameters
*/
public static > M map(Iterable iterable, Function super T, ? extends K> keyMapper, Supplier target) {
return map(iterable, keyMapper, Function.identity(), target);
}
/**
* Equivalent to {@link #collect(Iterable, Function, Supplier)} collecting to a {@link List}
*
* @param iterable the source
* @param mapper the mapping function
* @param input type
* @param output type
* @return the collection given by the supplier
*/
public static List collectToList(Iterable extends I> iterable, Function mapper) {
return collect(iterable, mapper, ArrayList::new);
}
/**
* Applies a mapper over an {@link Iterable} and puts each object into a collection.
*
* @param iterable the source
* @param mapper the mapping function
* @param target the supplier of resulting collection
* @param the input type
* @param the output type
* @param the collecting type
* @return the collection given by the supplier
*/
public static > C collect(Iterable extends I> iterable, Function mapper, Supplier target) {
return collect(iterable, i -> true, mapper, target);
}
/**
* Applies a filter and a mapper over an {@link Iterable} to collect objects and puts them into a collection.
*
* @param iterable the source
* @param acceptFilter the accepting condition
* @param mapper the mapping function
* @param target the supplier of resulting collection
* @param the input type
* @param the output type
* @param the collecting type
* @return the collection given by the supplier
*/
public static > C collect(Iterable extends I> iterable, Predicate acceptFilter, Function mapper,
Supplier target) {
return collect(iterable, acceptFilter, mapper, x -> true, target);
}
/**
* Applies a filter and a mapper over an {@link Iterable} to collect objects and puts them into a collection if it's accepted by a second
* predicate.
*
* @param iterable the source
* @param acceptFilter the accepting condition
* @param mapper the mapping function
* @param mappedValueFilter the accepting condition for the mapped value
* @param target the supplier of resulting collection
* @param the input type
* @param the output type
* @param the collecting type
* @return the collection given by the supplier
*/
public static > C collect(Iterable extends I> iterable, Predicate acceptFilter, Function mapper,
Predicate mappedValueFilter, Supplier target) {
C result = target.get();
for (I pawn : iterable) {
if (acceptFilter.test(pawn)) {
O mappedPawn = mapper.apply(pawn);
if (mappedValueFilter.test(mappedPawn)) {
result.add(mappedPawn);
}
}
}
return result;
}
/**
* Copies an {@link Iterable} to a {@link List}
*
* @param iterable an {@link Iterable}, not null
* @return a new {@link List} containing all elements of iterable
*/
public static List copy(Iterable extends E> iterable) {
return copy(iterable, new ArrayList<>());
}
/**
* Copies an {@link Iterator} to a {@link List}
*
* @param iterator an {@link Iterator}, not null
* @return a new {@link List} containing all elements of iterator
*/
public static List copy(Iterator extends E> iterator) {
return copy(iterator, new ArrayList<>());
}
/**
* Copies an {@link Iterable} to a given {@link Collection}
*
* @param iterable an {@link Iterable}, not null
* @return the given {@link List}
*/
public static > C copy(Iterable extends E> iterable, C result) {
if (iterable instanceof Collection) {
result.addAll((Collection) iterable);
} else {
copy(iterable.iterator(), result);
}
return result;
}
/**
* Copies an {@link Iterator} to a given {@link List}
*
* @param iterator an {@link Iterator}, not null
* @return the given {@link List}
*/
public static > C copy(Iterator extends E> iterator, C result) {
iterator.forEachRemaining(result::add);
return result;
}
/**
* Gives the intersection between two {@link Collection}s.
* Implementation has no particular optimization, it is based on a {@link HashSet}, hence comparison is based on
* {@link Object#equals(Object)}).
*
* @param c1 a {@link Collection}, not null
* @param c2 a {@link Collection}, not null
* @param type of elements
* @return the intersection between two {@link Collection}s
*/
public static Set intersect(Collection extends E> c1, Collection extends E> c2) {
Set copy = new HashSet<>(c1);
copy.retainAll(c2);
return copy;
}
/**
* Gives the intersection between two {@link Collection}s by comparing objects with a {@link Comparator}
* Implementation has no particular optimization, it is based on a {@link java.util.TreeSet}.
*
* @param c1 a {@link Collection}, not null
* @param c2 a {@link Collection}, not null
* @param type of elements
* @return the intersection between two {@link Collection}s according to the given {@link Comparator}
*/
public static Set intersect(Collection c1, Collection c2, BiPredicate predicate) {
Set copy = new HashSet<>(c1);
copy.removeIf(e -> !contains(c2, c -> predicate.test(e, c)));
return copy;
}
/**
* Gives the complement of c2 in c1 : all elements of c1 that are not member of c2
* Implementation has no particular optimization, it is based on a {@link HashSet#removeAll(Collection)} and as such
* is based on {@link Object#equals}
*
* @param c1 a {@link Collection}, not null
* @param c2 a {@link Collection}, not null
* @param type of elements
* @return the complement of c1 in c2
*/
public static Set minus(Collection c1, Collection c2) {
return minus(c1, c2, (Function, HashSet>) HashSet::new);
}
/**
* Gives the complement of c2 in c1 : all elements of c1 that are not member of c2
* Implementation has no particular optimization, it is based on a {@link HashSet#removeAll(Collection)} and as such
* is based on {@link Object#equals}.
* Result is pushed to given resultHolder.
*
* @param c1 a {@link Collection}, not null
* @param c2 a {@link Collection}, not null
* @param resultHolder function expected to give resulting {@link Set}. Argument is c1.
* @param type of elements
* @return the complement of c1 in c2
*/
public static > S minus(Collection c1, Collection c2, Function, S> resultHolder) {
S copy = resultHolder.apply(c1);
copy.removeAll(c2);
return copy;
}
/**
* Gives the complement of c2 in c1 : all elements of c1 that are not member of c2 by comparing objects with a {@link Comparator}
* Implementation has no particular optimization, it is based on a {@link java.util.TreeSet}.
*
* @param c1 a {@link Collection}, not null
* @param c2 a {@link Collection}, not null
* @param type of elements
* @return the complement of c1 in c2
*/
public static Set minus(Collection c1, Collection c2, BiPredicate predicate) {
Set copy = new HashSet<>(c1);
copy.removeIf(e -> contains(c2, c -> predicate.test(e, c)));
return copy;
}
public static boolean equals(Iterable it1, Iterable it2, BiPredicate predicate) {
if (it1 == it2)
return true;
Iterator e1 = it1.iterator();
Iterator e2 = it2.iterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
E o2 = e2.next();
if ((o1 == null ^ o2 == null) || !predicate.test(o1, o2)) {
return false;
}
}
return !(e1.hasNext() || e2.hasNext());
}
/**
* Puts 2 {@link Iterator}s side by side in a {@link Map}.
* If {@link Iterator}s are not of same length then null elements will be used into the {@link Map}.
* This leads to a cumulative null key if {@code values} {@link Iterator} is larger than {@code keys} {@link Iterator} because all overflowing
* elements will be put onto a null key.
*
* @param keys {@link Iterator} which elements will be used as keys
* @param values {@link Iterator} which elements will be used as values
* @param type of keys
* @param type of values
* @return a new {@link HashMap} composed of keys and values from both {@link Iterator}s
*/
public static Map pair(Iterable keys, Iterable values) {
return pair(keys, values, HashMap::new);
}
/**
* Puts 2 {@link Iterator}s side by side in a {@link Map}.
* If {@link Iterator}s are not of same length then null elements will be used into the {@link Map}.
* This leads to a cumulative null key if {@code values} {@link Iterator} is larger than {@code keys} {@link Iterator} because all overflowing
* elements will be put onto a null key.
*
* @param keys {@link Iterator} which elements will be used as keys
* @param values {@link Iterator} which elements will be used as values
* @param target a provider of a {@link Map}
* @param type of keys
* @param type of values
* @return a new {@link HashMap} composed of keys and values from both {@link Iterator}s
*/
public static > M pair(Iterable keys, Iterable values, Supplier target) {
UntilBothIterator bothIterator = new UntilBothIterator<>(keys, values);
return map(() -> bothIterator, Duo::getLeft, Duo::getRight, target);
}
/**
* Creates an {@link Iterable} by applying a mapping function on each element of the {@link Iterator} given by
* the source {@link Iterable}.
*
* @param iterable the {@link Iterable} that gives the source of the {@link Iterator} on which the mapping function will be applied
* @param mapper the mapping function of each element
* @return an {@link Iterable} which {@link Iterator} is one backed by given {@link Iterable} {@link Iterator} combined with mapping function
* @param {@link Iterable} {@link Iterator} source element type
* @param {@link Iterable} {@link Iterator} result element type
* @see #mappingIterator(Iterator, Function)
*/
public static Iterable mappingIterator(Iterable iterable, Function mapper) {
return () -> mappingIterator(iterable.iterator(), mapper);
}
/**
* Creates an {@link Iterator} by applying a mapping function on each element of the given {@link Iterator}.
*
* @param iterator the {@link Iterator} on which the mapping function will be applied
* @param mapper the mapping function of each element
* @return an {@link Iterator} backed by given {@link Iterator} combined with mapping function
* @param {@link Iterator} source element type
* @param {@link Iterator} result element type
* @see #mappingIterator(Iterable, Function)
*/
public static Iterator mappingIterator(Iterator iterator, Function mapper) {
return new Iterator() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public O next() {
return mapper.apply(iterator.next());
}
};
}
/**
* Converts an {@link Iterator} to a {@link Stream}.
* If the {@link Iterator} comes from a {@link Collection}, then prefer usage of {@link Collection#stream()}
*
* @param iterator an {@link Iterator}, not null
* @return a {@link Stream} than will iterate over the {@link Iterator} passed as argument
*/
public static Stream stream(Iterator iterator) {
return stream(() -> iterator);
}
/**
* Converts an {@link Iterable} to a {@link Stream}.
* If the {@link Iterable} is a {@link Collection}, then prefer usage of {@link Collection#stream()}
*
* @param iterable an {@link Iterable}, not null
* @return a {@link Stream} than will iterate over the {@link Iterable} passed as argument
*/
public static Stream stream(Iterable extends E> iterable) {
// StreamSupport knows how to convert an Iterable to a stream
return (Stream) StreamSupport.stream(iterable.spliterator(), false);
}
/**
* Concatenates given {@link Iterable}s as a single one to have a linear view of all of them.
*
* @param iterables some {@link Iterable}s
* @return a {@link Iterable} than will iterate over all given {@link Iterable}s
*/
public static Iterator concat(Iterable... iterables) {
return new IteratorIterator<>(iterables);
}
/**
* Concatenates given {@link Iterator}s as a single one to have a linear view of all of them.
*
* @param iterators some {@link Iterator}s
* @return a {@link Iterator} than will iterate over all given {@link Iterator}s
*/
public static Iterator concat(Iterator... iterators) {
return new IteratorIterator<>(iterators);
}
/**
* Wraps given array of elements into an {@link Iterator}.
*
* @param elements elements to be iterated
* @return an {@link Iterator} of given elements
* @param the elements type
*/
@SafeVarargs // method body doesn't handle improperly varargs parameter so it would generate ClassCastException
public static Iterator ofElements(E... elements ) {
return new ArrayIterator<>(elements);
}
/**
* Consumes an {@link Iterable} with an action that gets index of each element of the {@link Iterable}
*
* @param iterable any {@link Iterable}
* @param action an action that needs index and element as argument
* @param {@link Iterable} elements type
*/
public static void iterate(Iterable iterable, BiConsumer action) {
int i = 0;
for (E e : iterable) {
action.accept(i++, e);
}
}
/**
* Consumes an {@link Iterator} with an action that gets index of each element of the {@link Iterator}
*
* @param iterator any {@link Iterator}
* @param action an action that needs index and element as argument
* @param {@link Iterator} elements type
*/
public static void iterate(Iterator iterator, BiConsumer action) {
iterate(() -> iterator, action);
}
/**
* Keep elements of an {@link Iterable} that doesn't match a {@link Predicate}
*
* @param iterable any {@link Iterable}
* @param includer any {@link Predicate}
* @param type of elements
* @return given iterable without elements that doesn't match the given predicate
*/
public static Iterable filter(Iterable iterable, Predicate includer) {
return () -> filter(iterable.iterator(), includer);
}
/**
* Keep elements of an {@link Iterator} that doesn't match a {@link Predicate}
*
* @param iterator any {@link Iterator}
* @param includer any {@link Predicate}
* @param type of elements
* @return given iterator without elements that doesn't match the given predicate
*/
public static Iterator filter(Iterator iterator, Predicate includer) {
return new Iterator() {
private boolean hasNext = true;
private E currentItem = null;
private final Iterator surrogate = iterator;
private void lookAhead() {
while (hasNext = surrogate.hasNext()) {
E item = surrogate.next();
if (!includer.test(item)) {
hasNext = false;
currentItem = null;
} else {
hasNext = true;
currentItem = item;
}
if (hasNext) {
break;
}
}
}
@Override
public boolean hasNext() {
lookAhead();
return hasNext;
}
@Override
public E next() {
if (!hasNext) {
// this is necessary to be compliant with Iterator#next(..) contract
throw new NoSuchElementException();
}
return currentItem;
}
@Override
public void remove() {
surrogate.remove();
}
};
}
/**
* Finds the first predicate-matching element into an {@link Iterable}
*
* @param iterable the {@link Iterable} to scan
* @param predicate the test to execute for equality
* @param input type
* @return null if no element matches the predicate
*/
public static I find(Iterable iterable, Predicate predicate) {
return find(iterable.iterator(), predicate);
}
/**
* Finds the first predicate-matching element into an {@link Iterator}
*
* @param iterator the {@link Iterator} to scan
* @param predicate the test to execute for equality
* @param input type
* @return null if no element matches the predicate
*/
@SuppressWarnings("squid:AssignmentInSubExpressionCheck" /* simple algorithm, doesn't require to extract the assignment from if */)
public static I find(Iterator iterator, Predicate predicate) {
I result = null;
boolean found = false;
while (iterator.hasNext() && !found) {
I step = iterator.next();
if (found = predicate.test(step)) {
result = step;
}
}
return result;
}
/**
* Finds the first predicate-matching element (according to mapper) into the {@link Iterator} of an {@link Iterable}
*
* @param iterable the {@link Iterable} to scan
* @param mapper the mapper to extract the value to test
* @param predicate the test to execute for equality
* @param input type
* @param output type
* @return null if no mapped values matches the predicate
*/
public static Duo find(Iterable iterable, Function mapper, Predicate predicate) {
return find(iterable.iterator(), mapper, predicate);
}
/**
* Finds the first predicate-matching element (according to mapper) into an {@link Iterator}
*
* @param iterator the {@link Iterator} to scan
* @param mapper the mapper to extract the value to test
* @param predicate the test to execute for equality
* @param input type
* @param output type
* @return null if no mapped values matches the predicate
*/
@SuppressWarnings("squid:AssignmentInSubExpressionCheck" /* simple algorithm, doesn't require to extract the assignment from if */)
public static Duo find(Iterator iterator, Function mapper, Predicate predicate) {
Duo result = null;
boolean found = false;
while (iterator.hasNext() && !found) {
I step = iterator.next();
O mapperResult = mapper.apply(step);
// voluntary variable reassignment
//noinspection ReassignedVariable
if (found = predicate.test(mapperResult)) {
result = new Duo<>(step, mapperResult);
}
}
return result;
}
/**
* Consumes all predicate-matching elements of an {@link Iterable}
*
* @param iterable the {@link Iterable} to scan
* @param matcher the test to execute for equality
* @param foundConsumer will be called with every matching element and its index
* @param input type
*/
public static void consume(Iterable iterable, Predicate matcher, BiConsumer foundConsumer) {
consume(iterable.iterator(), matcher, foundConsumer);
}
/**
* Consumes all predicate-matching elements of an {@link Iterator}
*
* @param iterator the {@link Iterator} to scan
* @param matcher the test to execute for equality
* @param foundConsumer will be called with every matching element and its index
* @param input type
*/
public static void consume(Iterator iterator, Predicate matcher, BiConsumer foundConsumer) {
int index = 0;
while (iterator.hasNext()) {
E step = iterator.next();
if (matcher.test(step)) {
foundConsumer.accept(step, index);
}
index++;
}
}
/**
* Equivalent of {@link #consume(Iterator, Predicate, BiConsumer)} with a {@link Stream} as input
*
* @param stream the {@link Stream} to scan
* @param matcher the test to execute for equality
* @param foundConsumer will be called with every matching element and its index
* @param input type
*/
public static void consume(Stream stream, Predicate matcher, BiConsumer foundConsumer) {
final ModifiableInt index = new ModifiableInt(-1);
stream.map(e -> new Duo<>(e, index.increment()))
.filter(d -> matcher.test(d.getLeft()))
.forEach(d -> foundConsumer.accept(d.getLeft(), d.getRight()));
}
/**
* Indicates if an {@link Iterator} contains a predicate-matching element
*
* @param iterator the {@link Iterator} to scan
* @param input type
* @return true if a value that matches the {@link Predicate} is found
*/
public static boolean contains(Iterator iterator, Predicate predicate) {
return find(iterator, predicate) != null;
}
/**
* Indicates if an {@link Iterable} contains a predicate-matching element
*
* @param iterable the {@link Iterable} to scan
* @param input type
* @return true if a value that matches the {@link Predicate} is found
*/
public static boolean contains(Iterable iterable, Predicate predicate) {
return find(iterable.iterator(), predicate) != null;
}
/**
* Indicates if an {@link Iterator} contains a predicate-matching element after applying a mapper to the elements
*
* @param iterator the {@link Iterator} to scan
* @param mapper the mapper to extract the value to test
* @param input type
* @param output type
* @return true if a value that matches the {@link Predicate} is found
*/
public static boolean contains(Iterator iterator, Function mapper, Predicate predicate) {
return find(iterator, mapper, predicate) != null;
}
/**
* Indicates if an {@link Iterable} contains a predicate-matching element after applying a mapper to the elements
*
* @param iterable the {@link Iterable} to scan
* @param mapper the mapper to extract the value to test
* @param input type
* @param output type
* @return true if a value that matches the {@link Predicate} is found
*/
public static