org.d2ab.sequence.EntrySequence Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sequence Show documentation
Show all versions of sequence Show documentation
A lightweight alternative to Java 8 sequential Stream
/*
* Copyright 2015 Daniel Skogquist Åborg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.d2ab.sequence;
import org.d2ab.function.QuaternaryFunction;
import org.d2ab.iterable.ChainingIterable;
import org.d2ab.iterable.Iterables;
import org.d2ab.iterator.*;
import org.d2ab.util.Entries;
import javax.annotation.Nullable;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.*;
import java.util.stream.Collector;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyIterator;
/**
* An {@link Iterable} sequence of elements with {@link Stream}-like operations for refining, transforming and
* collating the list of elements.
*/
@FunctionalInterface
public interface EntrySequence extends Iterable> {
static EntrySequence of(Entry item) {
return from(Collections.singleton(item));
}
@SafeVarargs
static EntrySequence of(Entry... items) {
return from(asList(items));
}
static EntrySequence ofEntry(K left, V right) {
return of(Entries.of(left, right));
}
@SafeVarargs
static EntrySequence from(Iterable extends Entry>... iterables) {
return () -> new ChainingIterator<>(iterables);
}
static EntrySequence from(Iterable> iterable) {
return iterable::iterator;
}
static EntrySequence empty() {
return from(emptyIterator());
}
static EntrySequence from(Iterator> iterator) {
return () -> iterator;
}
static EntrySequence from(Stream> stream) {
return stream::iterator;
}
static EntrySequence from(Supplier extends Iterator>> iteratorSupplier) {
return iteratorSupplier::get;
}
static EntrySequence recurse(@Nullable K keySeed,
@Nullable V valueSeed,
BiFunction> op) {
return () -> new RecursiveIterator<>(Entries.of(keySeed, valueSeed), Entries.asUnaryOperator(op));
}
static EntrySequence recurse(@Nullable K keySeed,
@Nullable V valueSeed,
BiFunction super K, ? super V, ? extends Entry> f,
BiFunction super KK, ? super VV, ? extends Entry> g) {
return () -> new RecursiveIterator<>(f.apply(keySeed, valueSeed), Entries.asUnaryOperator(f, g));
}
static EntrySequence from(Map map) {
return map.entrySet()::iterator;
}
default EntrySequence map(BiFunction super K, ? super V, ? extends Entry> mapper) {
return map(Entries.asFunction(mapper));
}
default EntrySequence map(Function super Entry, ? extends Entry> mapper) {
return () -> new MappingIterator<>(mapper).backedBy(iterator());
}
default EntrySequence map(Function super K, ? extends KK> keyMapper,
Function super V, ? extends VV> valueMapper) {
return map(Entries.asFunction(keyMapper, valueMapper));
}
default EntrySequence skip(int skip) {
return () -> new SkippingIterator>(skip).backedBy(iterator());
}
default EntrySequence limit(int limit) {
return () -> new LimitingIterator>(limit).backedBy(iterator());
}
@SuppressWarnings("unchecked")
default EntrySequence then(EntrySequence then) {
return () -> new ChainingIterator<>(this, then);
}
default EntrySequence filter(BiPredicate super K, ? super V> predicate) {
return filter(Entries.asPredicate(predicate));
}
default EntrySequence filter(Predicate super Entry> predicate) {
return () -> new FilteringIterator<>(predicate).backedBy(iterator());
}
default EntrySequence flatMap(BiFunction super K, ? super V, ? extends Iterable>>
mapper) {
return flatMap(Entries.asFunction(mapper));
}
default EntrySequence flatMap(Function super Entry, ? extends Iterable>>
mapper) {
ChainingIterable> result = new ChainingIterable<>();
toSequence(mapper).forEach(result::append);
return result::iterator;
}
default EntrySequence until(Entry terminal) {
return () -> new ExclusiveTerminalIterator<>(terminal).backedBy(iterator());
}
default EntrySequence endingAt(Entry terminal) {
return () -> new InclusiveTerminalIterator<>(terminal).backedBy(iterator());
}
default EntrySequence until(K key, V value) {
return until(Entries.of(key, value));
}
default EntrySequence endingAt(K key, V value) {
return endingAt(Entries.of(key, value));
}
default EntrySequence until(BiPredicate super K, ? super V> terminal) {
return until(Entries.asPredicate(terminal));
}
default EntrySequence endingAt(BiPredicate super K, ? super V> terminal) {
return endingAt(Entries.asPredicate(terminal));
}
default EntrySequence until(Predicate super Entry> terminal) {
return () -> new ExclusiveTerminalIterator<>(terminal).backedBy(iterator());
}
default EntrySequence endingAt(Predicate super Entry> terminal) {
return () -> new InclusiveTerminalIterator<>(terminal).backedBy(iterator());
}
default Entry[] toArray() {
return toArray(Entry[]::new);
}
default Entry[] toArray(IntFunction[]> constructor) {
List list = toList();
@SuppressWarnings("unchecked")
Entry[] array = (Entry[]) list.toArray(constructor.apply(list.size()));
return array;
}
default List> toList() {
return toList(ArrayList::new);
}
default List> toList(Supplier>> constructor) {
return toCollection(constructor);
}
default Set> toSet() {
return toSet(HashSet::new);
}
default >> S toSet(Supplier extends S> constructor) {
return toCollection(constructor);
}
default SortedSet> toSortedSet() {
return toSet(TreeSet::new);
}
default Map toMap() {
return toMap(HashMap::new);
}
default > M toMap(Supplier extends M> constructor) {
M result = constructor.get();
forEach(each -> Entries.put(result, each));
return result;
}
default SortedMap toSortedMap() {
return toMap(TreeMap::new);
}
default >> C toCollection(Supplier extends C> constructor) {
return collect(constructor, Collection::add);
}
default C collect(Supplier extends C> constructor, BiConsumer super C, ? super Entry> adder) {
C result = constructor.get();
forEach(each -> adder.accept(result, each));
return result;
}
default S collect(Collector, R, S> collector) {
R result = collector.supplier().get();
BiConsumer> accumulator = collector.accumulator();
forEach(each -> accumulator.accept(result, each));
return collector.finisher().apply(result);
}
default String join(String delimiter) {
return join("", delimiter, "");
}
default String join(String prefix, String delimiter, String suffix) {
StringBuilder result = new StringBuilder();
result.append(prefix);
boolean first = true;
for (Entry each : this) {
if (first)
first = false;
else
result.append(delimiter);
result.append(each);
}
result.append(suffix);
return result.toString();
}
default Optional> reduce(BinaryOperator> operator) {
Iterator> iterator = iterator();
if (!iterator.hasNext())
return Optional.empty();
Entry result = reduce(iterator.next(), operator, iterator);
return Optional.of(result);
}
default Optional> reduce(QuaternaryFunction> operator) {
Iterator> iterator = iterator();
if (!iterator.hasNext())
return Optional.empty();
Entry result = reduce(iterator.next(), Entries.asBinaryOperator(operator), iterator);
return Optional.of(result);
}
default Entry reduce(Entry identity, BinaryOperator> operator) {
return reduce(identity, operator, iterator());
}
default Entry reduce(K key, V value, QuaternaryFunction> operator) {
return reduce(Entries.of(key, value), Entries.asBinaryOperator(operator), iterator());
}
default Entry reduce(Entry identity,
BinaryOperator> operator,
Iterator> iterator) {
Entry result = identity;
while (iterator.hasNext())
result = operator.apply(result, iterator.next());
return result;
}
default Optional> first() {
Iterator> iterator = iterator();
if (!iterator.hasNext())
return Optional.empty();
return Optional.of(iterator.next());
}
default Optional> second() {
Iterator> iterator = iterator();
Iterators.skip(iterator);
if (!iterator.hasNext())
return Optional.empty();
return Optional.of(iterator.next());
}
default Optional> third() {
Iterator> iterator = iterator();
Iterators.skip(iterator, 2);
if (!iterator.hasNext())
return Optional.empty();
return Optional.of(iterator.next());
}
default Optional> last() {
Iterator> iterator = iterator();
if (!iterator.hasNext())
return Optional.empty();
Entry last;
do {
last = iterator.next();
} while (iterator.hasNext());
return Optional.of(last);
}
default Sequence>> partition(int window) {
return () -> new PartitioningIterator>(window).backedBy(iterator());
}
default EntrySequence step(int step) {
return () -> new SteppingIterator>(step).backedBy(iterator());
}
default EntrySequence distinct() {
return () -> new DistinctIterator>().backedBy(iterator());
}
default EntrySequence sorted() {
return () -> new SortingIterator>().backedBy(iterator());
}
default EntrySequence sorted(Comparator super Entry extends K, ? extends V>> comparator) {
return () -> new SortingIterator>(comparator).backedBy(iterator());
}
default Optional> min(Comparator super Entry extends K, ? extends V>> comparator) {
return reduce(BinaryOperator.minBy(comparator));
}
default Optional> max(Comparator super Entry extends K, ? extends V>> comparator) {
return reduce(BinaryOperator.maxBy(comparator));
}
default int count() {
int count = 0;
for (Entry ignored : this)
count++;
return count;
}
default boolean all(BiPredicate super K, ? super V> biPredicate) {
Predicate super Entry> predicate = Entries.asPredicate(biPredicate);
for (Entry each : this)
if (!predicate.test(each))
return false;
return true;
}
default boolean none(BiPredicate super K, ? super V> predicate) {
return !any(predicate);
}
default boolean any(BiPredicate super K, ? super V> biPredicate) {
Predicate super Entry> predicate = Entries.asPredicate(biPredicate);
for (Entry each : this)
if (predicate.test(each))
return true;
return false;
}
default EntrySequence peek(BiConsumer action) {
Consumer super Entry> consumer = Entries.asConsumer(action);
return () -> new PeekingIterator<>(consumer).backedBy(iterator());
}
default EntrySequence append(Iterator extends Entry> iterator) {
return append(Iterables.from(iterator));
}
default EntrySequence append(Iterable extends Entry> that) {
@SuppressWarnings("unchecked")
Iterable> chainingSequence = new ChainingIterable<>(this, that);
return chainingSequence::iterator;
}
@SuppressWarnings("unchecked")
default EntrySequence append(Entry... entries) {
return append(Iterables.from(entries));
}
@SuppressWarnings("unchecked")
default EntrySequence appendEntry(K key, V value) {
return append(Entries.of(key, value));
}
default EntrySequence append(Stream> stream) {
return append(Iterables.from(stream));
}
default Sequence> toSequence() {
return Sequence.from(this);
}
default Sequence toSequence(BiFunction super K, ? super V, ? extends T> mapper) {
return toSequence(Entries.asFunction(mapper));
}
default Sequence toSequence(Function super Entry, ? extends T> mapper) {
return () -> new MappingIterator<>(mapper).backedBy(iterator());
}
default EntrySequence repeat() {
return () -> new RepeatingIterator<>(this, -1);
}
default EntrySequence repeat(long times) {
return () -> new RepeatingIterator<>(this, times);
}
default EntrySequence reverse() {
return () -> new ReverseIterator>().backedBy(iterator());
}
default EntrySequence shuffle() {
List> list = toList();
Collections.shuffle(list);
return from(list);
}
default EntrySequence shuffle(Random md) {
List> list = toList();
Collections.shuffle(list, md);
return from(list);
}
}