org.reactfx.util.LL Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of richtextfx Show documentation
Show all versions of richtextfx Show documentation
FX-Text-Area for formatted text and other special effects.
package org.reactfx.util;
import java.util.Collections;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Spliterator;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* Immutable singly-linked list.
*/
public abstract class LL implements Iterable {
private static class Nil extends LL {
private static final Nil> INSTANCE = new Nil();
@SuppressWarnings("unchecked")
static Nil instance() { return (Nil) INSTANCE; }
@Override public boolean isEmpty() { return true; }
@Override public int size() { return 0; }
@Override public T head() { throw new NoSuchElementException(); }
@Override public LL tail() { throw new NoSuchElementException(); }
@Override public LL map(Function super T, ? extends U> f) { return instance(); }
@Override public Iterator iterator() { return Collections.emptyIterator(); }
@Override
public R fold(
R acc,
BiFunction super R, ? super T, ? extends R> reduction) {
return acc;
}
@Override
public Optional mapReduce(
Function super T, ? extends R> map,
BinaryOperator reduce) {
return Optional.empty();
}
}
public static final class Cons extends LL {
private final T head;
private final LL extends T> tail;
private final int size;
private Cons(T head, LL extends T> tail) {
this.head = head;
this.tail = tail;
this.size = 1 + tail.size();
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public int size() {
return size;
}
@Override
public T head() {
return head;
}
@Override
public LL extends T> tail() {
return tail;
}
@Override
public Cons map(Function super T, ? extends U> f) {
return cons(f.apply(head), tail.map(f));
}
@Override
public R fold(
R acc,
BiFunction super R, ? super T, ? extends R> reduction) {
return tail.fold(reduction.apply(acc, head), reduction);
}
@Override
public final Iterator iterator() {
return new Iterator() {
private LL extends T> l = Cons.this;
@Override
public boolean hasNext() {
return !l.isEmpty();
}
@Override
public T next() {
T res = l.head();
l = l.tail();
return res;
}
};
}
@Override
public Optional mapReduce(
Function super T, ? extends R> map,
BinaryOperator reduce) {
return Optional.of(mapReduce1(map, reduce));
}
public R mapReduce1(
Function super T, ? extends R> map,
BinaryOperator reduce) {
R acc = map.apply(head);
return tail.fold(acc, (r, t) -> reduce.apply(r, map.apply(t)));
}
}
public static LL nil() {
return Nil.instance();
}
public static Cons cons(T head, LL extends T> tail) {
return new Cons<>(head, tail);
}
@SafeVarargs
public static Cons of(T head, T... tail) {
return cons(head, of(tail, tail.length, LL.nil()));
}
private static LL of(T[] elems, int to, LL tail) {
if(to == 0) {
return tail;
} else {
return of(elems, to - 1, cons(elems[to-1], tail));
}
}
public static LL extends T> concat(LL extends T> l1, LL extends T> l2) {
if(l1.isEmpty()) {
return l2;
} else {
return cons(l1.head(), concat(l1.tail(), l2));
}
}
// private constructor to prevent subclassing
private LL() {}
public abstract boolean isEmpty();
public abstract int size();
public abstract T head();
public abstract LL extends T> tail();
public abstract LL map(Function super T, ? extends U> f);
public abstract R fold(R acc, BiFunction super R, ? super T, ? extends R> reduction);
public abstract Optional mapReduce(
Function super T, ? extends R> map,
BinaryOperator reduce);
public boolean all(Predicate cond) {
return fold(true, (b, t) -> b && cond.test(t));
}
public U mapFirst2(BiFunction super T, ? super T, ? extends U> f) {
return f.apply(head(), tail().head());
}
public U mapFirst3(TriFunction super T, ? super T, ? super T, ? extends U> f) {
return tail().mapFirst2(f.pApply(head()));
}
public U mapFirst4(TetraFunction super T, ? super T, ? super T, ? super T, ? extends U> f) {
return tail().mapFirst3(f.pApply(head()));
}
public U mapFirst5(PentaFunction super T, ? super T, ? super T, ? super T, ? super T, ? extends U> f) {
return tail().mapFirst4(f.pApply(head()));
}
public U mapFirst6(HexaFunction super T, ? super T, ? super T, ? super T, ? super T, ? super T, ? extends U> f) {
return tail().mapFirst5(f.pApply(head()));
}
@Override
public String toString() {
if(isEmpty()) {
return "[]";
} else {
StringBuilder sb = new StringBuilder();
sb.append("[");
sb.append(head());
LL extends T> tail = tail();
while(!tail.isEmpty()) {
sb.append(",").append(tail.head());
tail = tail.tail();
}
sb.append("]");
return sb.toString();
}
}
public Stream stream() {
Spliterator spliterator = new Spliterator() {
private final Iterator iterator = iterator();
@Override
public boolean tryAdvance(Consumer super T> action) {
if(iterator.hasNext()) {
action.accept(iterator.next());
return true;
} else {
return false;
}
}
@Override
public Spliterator trySplit() {
return null;
}
@Override
public long estimateSize() {
return size();
}
@Override
public int characteristics() {
return Spliterator.IMMUTABLE | Spliterator.SIZED;
}
};
return StreamSupport.stream(spliterator, false);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy