
com.github.tonivade.purefun.data.Sequence Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of purefun-core Show documentation
Show all versions of purefun-core Show documentation
Functional Programming Library for Java
The newest version!
/*
* Copyright (c) 2018-2024, Antonio Gabriel Muñoz Conejo
* Distributed under the terms of the MIT License
*/
package com.github.tonivade.purefun.data;
import static com.github.tonivade.purefun.core.Precondition.checkNonNull;
import static java.util.Spliterators.spliteratorUnknownSize;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.joining;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.SequencedCollection;
import java.util.Spliterator;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import com.github.tonivade.purefun.HigherKind;
import com.github.tonivade.purefun.Kind;
import com.github.tonivade.purefun.core.Bindable;
import com.github.tonivade.purefun.core.Function1;
import com.github.tonivade.purefun.core.Function2;
import com.github.tonivade.purefun.core.Matcher1;
import com.github.tonivade.purefun.core.Operator2;
import com.github.tonivade.purefun.core.PartialFunction1;
import com.github.tonivade.purefun.core.Tuple;
import com.github.tonivade.purefun.core.Tuple2;
import com.github.tonivade.purefun.type.Option;
@HigherKind
public non-sealed interface Sequence extends SequenceOf, Iterable, Bindable, E> {
int size();
boolean contains(Object element);
default boolean containsAll(Iterable> elements) {
for (var e : elements) {
if (!contains(e)) {
return false;
}
}
return true;
}
Sequence append(E element);
Sequence remove(E element);
Sequence appendAll(Sequence extends E> other);
Sequence removeAll(Sequence extends E> other);
Sequence reverse();
@Override
Sequence map(Function1 super E, ? extends R> mapper);
@Override
Sequence flatMap(Function1 super E, ? extends Kind, ? extends R>> mapper);
Sequence filter(Matcher1 super E> matcher);
Sequence filterNot(Matcher1 super E> matcher);
default Collection toCollection() {
return toSequencedCollection();
}
default SequencedCollection toSequencedCollection() {
return new SequenceCollection<>(this);
}
default Option reduce(Operator2 operator) {
return Option.from(stream().reduce(operator::apply));
}
default E fold(E initial, Operator2 operator) {
return stream().reduce(initial, operator::apply);
}
default U foldLeft(U initial, Function2 super U, ? super E, ? extends U> combinator) {
U accumulator = initial;
for (E element : this) {
accumulator = combinator.apply(accumulator, element);
}
return accumulator;
}
default U foldRight(U initial, Function2 super E, ? super U, ? extends U> combinator) {
return reverse().foldLeft(initial, (acc, e) -> combinator.apply(e, acc));
}
default String join() {
return join("");
}
default String join(String separator) {
return stream().map(Object::toString).collect(joining(separator));
}
default String join(String separator, String prefix, String suffix) {
return stream().map(Object::toString).collect(joining(separator, prefix, suffix));
}
default Sequence collect(PartialFunction1 super E, ? extends R> function) {
return filter(function::isDefinedAt).map(function::apply);
}
@SuppressWarnings("unchecked")
default ImmutableMap> groupBy(Function1 super E, ? extends G> selector) {
return (ImmutableMap>)
ImmutableMap.from(stream().collect(groupingBy(selector::apply))).mapValues(ImmutableList::from);
}
default ImmutableList asList() {
return ImmutableList.from(stream());
}
default ImmutableArray asArray() {
return ImmutableArray.from(stream());
}
default ImmutableSet asSet() {
return ImmutableSet.from(stream());
}
default ImmutableTree asTree() {
return ImmutableTree.from(stream());
}
default ImmutableTree asTree(Comparator super E> comparator) {
return ImmutableTree.from(comparator, stream());
}
default Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
default boolean isEmpty() {
return size() == 0;
}
default Stream> zipWithIndex() {
return zip(Range.of(0, size()).stream(), stream());
}
default E[] toArray(Function1 supplier) {
E[] array = supplier.apply(size());
int i = 0;
for (E element: this) {
array[i++] = element;
}
return array;
}
static ImmutableArray emptyArray() {
return ImmutableArray.empty();
}
static ImmutableList emptyList() {
return ImmutableList.empty();
}
static ImmutableSet emptySet() {
return ImmutableSet.empty();
}
static ImmutableTree emptyTree() {
return ImmutableTree.empty();
}
@SafeVarargs
static ImmutableArray arrayOf(E... elements) {
return ImmutableArray.of(elements);
}
@SafeVarargs
static ImmutableList listOf(E... elements) {
return ImmutableList.of(elements);
}
@SafeVarargs
static ImmutableSet setOf(E... elements) {
return ImmutableSet.of(elements);
}
@SafeVarargs
static > ImmutableTree treeOf(E... elements) {
return ImmutableTree.of(elements);
}
static Stream> zip(Iterator first, Iterator second) {
return asStream(new PairIterator<>(first, second));
}
static Stream> zip(Stream first, Stream second) {
return zip(first.iterator(), second.iterator());
}
static Stream> zip(Sequence first, Sequence second) {
return zip(first.stream(), second.stream());
}
static Stream interleave(Iterator first, Iterator second) {
return zip(first, second)
.flatMap(tuple -> Stream.of(tuple.get1(), tuple.get2()))
.filter(Objects::nonNull);
}
static Stream interleave(Stream first, Stream second) {
return interleave(first.iterator(), second.iterator());
}
static Stream interleave(Sequence first, Sequence second) {
return interleave(first.stream(), second.stream());
}
static Stream asStream(Iterator iterator) {
return StreamSupport.stream(spliteratorUnknownSize(iterator, Spliterator.ORDERED), false);
}
}
final class PairIterator implements Iterator> {
private final Iterator first;
private final Iterator second;
PairIterator(Iterator first, Iterator second) {
this.first = checkNonNull(first);
this.second = checkNonNull(second);
}
@Override
public boolean hasNext() {
return first.hasNext() && second.hasNext();
}
@Override
public Tuple2 next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return Tuple.of(nextItem(first), nextItem(second));
}
private static Z nextItem(Iterator it) {
return it.next();
}
}
final class SequenceCollection implements SequencedCollection {
private final Sequence sequence;
SequenceCollection(Sequence sequence) {
this.sequence = checkNonNull(sequence);
}
@Override
public int size() {
return sequence.size();
}
@Override
public boolean isEmpty() {
return sequence.isEmpty();
}
@Override
public boolean contains(Object o) {
return sequence.contains(o);
}
@Override
public Iterator iterator() {
return sequence.iterator();
}
@Override
public Object[] toArray() {
Object[] array = new Object[sequence.size()];
int i = 0;
for (E element: sequence) {
array[i++] = element;
}
return array;
}
@SuppressWarnings("unchecked")
@Override
public T[] toArray(T[] array) {
if (array.length < sequence.size()) {
return (T[]) Arrays.copyOf(toArray(), sequence.size(), array.getClass());
}
System.arraycopy(toArray(), 0, array, 0, sequence.size());
if (array.length > sequence.size()) {
array[sequence.size()] = null;
}
return array;
}
@Override
public SequencedCollection reversed() {
return new SequenceCollection<>(sequence.reverse());
}
@Override
public boolean containsAll(Collection> c) {
return sequence.containsAll(c);
}
@Override
public boolean add(E e) {
throw new UnsupportedOperationException();
}
@Override
public void addFirst(E e) {
throw new UnsupportedOperationException();
}
@Override
public void addLast(E e) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public E removeFirst() {
throw new UnsupportedOperationException();
}
@Override
public E removeLast() {
throw new UnsupportedOperationException();
}
@Override
public boolean removeIf(Predicate super E> filter) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection extends E> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection> c) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy