
org.osgl.util.ListBase Maven / Gradle / Ivy
The newest version!
package org.osgl.util;
/*-
* #%L
* Java Tool
* %%
* Copyright (C) 2014 - 2017 OSGL (Open Source General Library)
* %%
* 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.
* #L%
*/
import static org.osgl.util.C.Feature.SORTED;
import org.osgl.$;
import org.osgl.Lang;
import org.osgl.exception.NotAppliedException;
import java.util.*;
public abstract class ListBase extends AbstractList implements C.List {
private boolean sorted = false;
// utilities
protected final boolean isLazy() {
return is(C.Feature.LAZY);
}
protected final boolean isImmutable() {
return is(C.Feature.IMMUTABLE);
}
protected final boolean isReadOnly() {
return is(C.Feature.READONLY);
}
protected final boolean isMutable() {
return !isImmutable() && !isReadOnly();
}
protected void forEachLeft($.Visitor super T> visitor) throws $.Break {
for (T t : this) {
try {
visitor.apply(t);
} catch (NotAppliedException e) {
// ignore
}
}
}
protected void forEachLeft($.IndexedVisitor indexedVisitor) throws $.Break {
for (int i = 0, j = size(); i < j; ++i) {
try {
indexedVisitor.apply(i, get(i));
} catch (NotAppliedException e) {
// ignore
}
}
}
protected void forEachRight($.Visitor super T> visitor) throws $.Break {
Iterator itr = reverseIterator();
while (itr.hasNext()) {
try {
visitor.apply(itr.next());
} catch (NotAppliedException e) {
// ignore
}
}
}
protected void forEachRight($.IndexedVisitor indexedVisitor) throws $.Break {
for (int i = size() - 1; i >= 0; --i) {
try {
indexedVisitor.apply(i, get(i));
} catch (NotAppliedException e) {
// ignore
}
}
}
@Override
public C.List parallel() {
setFeature(C.Feature.PARALLEL);
return this;
}
@Override
public C.List sequential() {
unsetFeature(C.Feature.PARALLEL);
return this;
}
@Override
public C.List lazy() {
setFeature(C.Feature.LAZY);
return this;
}
@Override
public C.List eager() {
unsetFeature(C.Feature.LAZY);
return this;
}
@Override
public C.List snapshot() {
if (isImmutable()) {
return this;
}
return ListBuilder.toList(this);
}
@Override
public C.List readOnly() {
if (isMutable()) {
return new ReadOnlyDelegatingList(this);
}
return this;
}
@Override
public C.List copy() {
return C.newList(this);
}
@Override
public C.List sorted() {
if (size() == 0) return C.newList();
T t = get(0);
C.List l = copy();
if (!(t instanceof Comparable)) {
return l;
}
Object[] a = l.toArray();
Arrays.sort(a);
ListIterator i = l.listIterator();
for (int j=0; j sorted(Comparator super T> comparator) {
C.List l = copy();
Collections.sort(l, comparator);
((ListBase)l).setFeature(SORTED);
return l;
}
@Override
public C.List unique() {
Set set = C.newSet();
C.List retList = null;
int i = 0;
for (T t: this) {
i++;
if (set.contains(t)) {
if (null == retList) {
retList = C.newSizedList(size());
retList.addAll(subList(0, i - 1));
}
} else if (null != retList) {
retList.add(t);
}
set.add(t);
}
return null == retList ? this : retList;
}
public C.List unique(Comparator comp) {
Set set = new TreeSet(comp);
C.List retList = null;
int i = 0;
for (T t: this) {
i++;
if (set.contains(t)) {
if (null == retList) {
retList = C.newSizedList(size());
retList.addAll(subList(0, i - 1));
}
} else if (null != retList) {
retList.add(t);
}
set.add(t);
}
return null == retList ? this : retList;
}
@Override
public C.List subList(int fromIndex, int toIndex) {
if (fromIndex == toIndex) {
return Nil.list();
}
if (is(C.Feature.RANDOM_ACCESS)) {
return new RandomAccessSubList(this, fromIndex, toIndex);
} else {
return new SubList(this, fromIndex, toIndex);
}
}
@Override
public boolean add(T t) {
boolean b = super.add(t);
if (b) {
sorted = false;
}
return b;
}
@Override
public void add(int index, T element) {
super.add(index, element);
sorted = false;
unsetFeature(SORTED);
}
public boolean addAll(Iterable extends T> iterable) {
boolean modified = false;
Iterator extends T> e = iterable.iterator();
while (e.hasNext()) {
if (add(e.next())) {
modified = true;
}
}
sorted = !modified;
if (!sorted) {
unsetFeature(SORTED);
}
return modified;
}
@Override
public int hashCode() {
return 31 * super.hashCode() + $.hc(features_);
}
// --- Featured methods
volatile private EnumSet features_;
protected final EnumSet features_() {
if (null == features_) {
synchronized (this) {
if (null == features_) {
features_ = initFeatures();
assert (null != features_);
}
}
}
return features_;
}
/**
* Sub class should override this method to provide initial feature
* set for the feature based instance
*
* @return the initial feature set configuration
*/
abstract protected EnumSet initFeatures();
@Override
public final EnumSet features() {
return EnumSet.copyOf(features_());
}
@Override
public final boolean is(C.Feature feature) {
return features_().contains(feature);
}
protected ListBase setFeature(C.Feature feature) {
features_().add(feature);
return this;
}
protected ListBase unsetFeature(C.Feature feature) {
features_().remove(feature);
return this;
}
// --- eof Featured methods
// --- Traversal methods
@Override
public boolean allMatch($.Function super T, Boolean> predicate) {
return !anyMatch($.F.negate(predicate));
}
@Override
public boolean anyMatch($.Function super T, Boolean> predicate) {
return findOne(predicate).isDefined();
}
@Override
public boolean noneMatch($.Function super T, Boolean> predicate) {
return !anyMatch(predicate);
}
@Override
public $.Option findOne(final $.Function super T, Boolean> predicate) {
try {
forEach(new $.Visitor() {
@Override
public void visit(T t) throws $.Break {
if (predicate.apply(t)) {
throw new $.Break(t);
}
}
});
return $.none();
} catch ($.Break b) {
T t = b.get();
return $.some(t);
}
}
// --- eof Traversal methods
@Override
public C.List asList() {
return this;
}
@Override
public Iterator iterator() {
return listIterator();
}
public abstract ListIterator listIterator(int index);
@Override
public Iterator reverseIterator() {
final ListIterator li = listIterator(size());
return new Iterator() {
@Override
public boolean hasNext() {
return li.hasPrevious();
}
@Override
public T next() {
return li.previous();
}
@Override
public void remove() {
li.remove();
}
};
}
@Override
public final T first() throws NoSuchElementException {
return head();
}
@Override
public T head() throws NoSuchElementException {
return iterator().next();
}
@Override
public T last() throws NoSuchElementException {
return reverseIterator().next();
}
@Override
public C.List take(int n) {
boolean immutable = isImmutable();
if (n == 0) {
if (immutable) {
return Nil.list();
} else {
return C.newList();
}
} else if (n < 0) {
return drop(size() + n);
} else if (n >= size()) {
return this;
}
if (immutable) {
return subList(0, n);
}
C.List l = C.newSizedList(n);
l.addAll(subList(0, n));
return l;
}
@Override
public C.List takeWhile($.Function super T, Boolean> predicate) {
boolean immutable = isImmutable();
int sz = size();
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder lb = new ListBuilder(sz);
for (T t : this) {
if (predicate.apply(t)) {
lb.add(t);
} else {
break;
}
}
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List l = C.newSizedList(sz);
for (T t : this) {
if (predicate.apply(t)) {
l.add(t);
} else {
break;
}
}
return l;
}
}
@Override
public C.List drop(int n) throws IndexOutOfBoundsException {
int sz = size();
boolean immutable = isImmutable();
if (n < 0) {
n = -n;
if (n >= sz) {
if (immutable) return C.newList();
else return C.list();
} else {
return take(sz - n);
}
}
if (0 == n) {
return this;
}
// TODO handle lazy drop
if (immutable) {
return subList(n, size());
}
if (n >= sz) {
return C.newList();
}
C.List l = C.newSizedList(sz - n);
l.addAll(subList(n, sz));
return l;
}
@Override
public C.List dropWhile($.Function super T, Boolean> predicate) {
boolean immutable = isImmutable();
int sz = size();
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder lb = new ListBuilder(sz);
boolean found = false;
for (T t : this) {
if (!found && predicate.apply(t)) {
continue;
} else {
found = true;
lb.add(t);
}
}
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List l = C.newSizedList(sz);
boolean found = false;
for (T t : this) {
if (!found && predicate.apply(t)) {
continue;
} else {
found = true;
l.add(t);
}
}
return l;
}
}
@Override
public C.List remove($.Function super T, Boolean> predicate) {
boolean immutable = isImmutable();
int sz = size();
// TODO: handle lazy remove
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder lb = new ListBuilder(sz);
forEach($.visitor($.predicate(predicate).elseThen(C.F.addTo(lb))));
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List l = C.newSizedList(sz);
forEach($.visitor($.predicate(predicate).elseThen(C.F.addTo(l))));
return l;
}
}
@Override
public C.List map($.Function super T, ? extends R> mapper) {
boolean immutable = isImmutable();
int sz = size();
if (isLazy()) {
return MappedList.of(this, mapper);
}
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder lb = new ListBuilder(sz);
forEach($.visitor($.f1(mapper).andThen(C.F.addTo(lb))));
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List l = C.newSizedList(sz);
forEach($.visitor($.f1(mapper).andThen(C.F.addTo(l))));
return l;
}
}
@Override
public C.List flatMap($.Function super T, ? extends Iterable extends R>> mapper
) {
boolean immutable = isImmutable();
int sz = size();
// TODO: handle lazy flatmap
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder lb = new ListBuilder<>(sz * 3);
forEach($.visitor($.f1(mapper).andThen(C.F.addAllTo(lb))));
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List l = C.newSizedList(sz * 3);
forEach($.visitor($.f1(mapper).andThen(C.F.addAllTo(l))));
return l;
}
}
@Override
public C.List collect(String path) {
boolean immutable = isImmutable();
int sz = size();
if (0 == sz) {
return immutable ? Nil.list() : C.newList();
}
if (immutable) {
ListBuilder lb = new ListBuilder<>(sz);
for (T t : this) {
lb.add((R) $.getProperty(t, path));
}
return lb.toList();
} else {
C.List list = C.newSizedList(sz);
for (T t : this) {
list.add((R) $.getProperty(t, path));
}
return list;
}
}
@Override
public C.List filter($.Function super T, Boolean> predicate) {
boolean immutable = isImmutable();
int sz = size();
// TODO: handle lazy filter
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder lb = new ListBuilder(sz);
forEach($.visitor($.predicate(predicate).ifThen(C.F.addTo(lb))));
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List l = C.newSizedList(sz);
forEach($.visitor($.predicate(predicate).ifThen(C.F.addTo(l))));
return l;
}
}
@Override
public Lang.T2, C.List> split(final Lang.Function super T, Boolean> predicate) {
final C.List left = C.newList();
final C.List right = C.newList();
accept(new $.Visitor() {
@Override
public void visit(T t) throws Lang.Break {
if (predicate.apply(t)) {
left.add(t);
} else {
right.add(t);
}
}
});
if (isImmutable() || isReadOnly()) {
return $.T2(C.list(left), C.list(right));
}
return $.T2(left, right);
}
private Cursor fromLeft() {
return new ListIteratorCursor(listIterator(0));
}
private Cursor fromRight() {
return new ListIteratorCursor(listIterator(size()));
}
@Override
public Cursor locateFirst($.Function predicate) {
Cursor c = fromLeft();
while (c.hasNext()) {
T t = c.forward().get();
if (predicate.apply(t)) {
return c;
}
}
return c;
}
@Override
public Cursor locate($.Function predicate) {
return locateFirst(predicate);
}
@Override
public Cursor locateLast($.Function predicate) {
Cursor c = fromRight();
while (c.hasPrevious()) {
T t = c.backward().get();
if (predicate.apply(t)) {
return c;
}
}
return c;
}
@Override
public C.List insert(int index, T t) throws IndexOutOfBoundsException {
int sz = size();
if (sz < Math.abs(index)) {
throw new IndexOutOfBoundsException();
}
if (index < 0) {
index = sz + index;
}
if (isMutable()) {
add(index, t);
return this;
}
if (isImmutable()) {
ListBuilder lb = new ListBuilder(sz + 1);
if (index > 0) {
lb.addAll(subList(0, index));
}
lb.add(t);
if (index < sz) {
lb.addAll(subList(index, sz));
}
return lb.toList();
} else {
C.List l = C.newSizedList(sz + 1);
if (index > 0) {
l.addAll(subList(0, index));
}
l.add(t);
if (index < sz) {
l.addAll(subList(index, sz));
}
return l;
}
}
@Override
public C.List insert(int index, T... ta) throws IndexOutOfBoundsException {
if (ta.length == 0) {
return this;
}
return insert(index, C.listOf(ta));
}
@Override
public C.List insert(int index, List subList) throws IndexOutOfBoundsException {
if (subList.isEmpty()) {
return this;
}
int sz = size();
if (sz < Math.abs(index)) {
throw new IndexOutOfBoundsException();
}
if (index < 0) {
index = sz + index;
}
if (isMutable()) {
addAll(index, subList);
return this;
}
if (isImmutable()) {
int delta = subList.size();
ListBuilder lb = new ListBuilder(sz + delta);
if (index > 0) {
lb.addAll(subList(0, index));
}
lb.addAll(subList);
if (index < sz) {
lb.addAll(subList(index, sz));
}
return lb.toList();
} else {
C.List l = C.newSizedList(sz + 1);
if (index > 0) {
l.addAll(subList(0, index));
}
l.addAll(subList);
if (index < sz) {
l.addAll(subList(index, sz));
}
return l;
}
}
@Override
public C.List reverse() {
if (isLazy()) {
return ReverseList.wrap(this);
}
boolean immutable = isImmutable();
int sz = size();
if (immutable) {
if (0 == sz) {
return Nil.list();
}
ListBuilder lb = new ListBuilder(sz);
Iterator itr = reverseIterator();
while (itr.hasNext()) {
lb.add(itr.next());
}
return lb.toList();
} else {
if (0 == sz) {
return C.newList();
}
C.List l = C.newSizedList(sz);
Iterator itr = reverseIterator();
while (itr.hasNext()) {
l.add(itr.next());
}
return l;
}
}
@Override
public C.List without(Collection super T> col) {
return filter($.F.negate(C.F.containsIn(col)));
}
@Override
public C.List without(T element) {
return filter(($.F.ne().curry(element)));
}
@Override
public C.List without(T element, T... elements) {
elements = $.concat(elements, element);
C.List l = without(element);
int len = elements.length;
if (0 == len) {
return l;
}
boolean c = false;
if (8 < len) {
T t0 = elements[0];
if (t0 instanceof Comparable) {
c = true;
Arrays.sort(elements);
}
}
C.List lr = C.newSizedList(l.size());
if (c) {
for (T t : l) {
int id = Arrays.binarySearch(elements, t);
if (id == -1) continue;
lr.add(t);
}
} else {
for (T t : l) {
boolean found = false;
for (int i = 0; i < len; ++i) {
if ($.eq(elements[i], t)) {
found = true;
break;
}
}
if (!found) lr.add(t);
}
}
return lr;
}
@Override
public C.List accept($.Visitor super T> visitor) {
forEachLeft(visitor);
return this;
}
@Override
public C.List each($.Visitor super T> visitor) {
return accept(visitor);
}
@Override
public C.List forEach($.Visitor super T> visitor) {
return accept(visitor);
}
@Override
public C.List acceptLeft($.Visitor super T> visitor) {
forEachLeft(visitor);
return this;
}
@Override
public C.List acceptRight($.Visitor super T> visitor) {
forEachRight(visitor);
return this;
}
@Override
public C.List accept($.IndexedVisitor indexedVisitor) {
forEachLeft(indexedVisitor);
return this;
}
@Override
public C.List each($.IndexedVisitor indexedVisitor) {
return accept(indexedVisitor);
}
@Override
public C.List forEach($.IndexedVisitor indexedVisitor) {
return accept(indexedVisitor);
}
@Override
public C.List acceptLeft($.IndexedVisitor indexedVisitor) {
forEachLeft(indexedVisitor);
return this;
}
@Override
public C.List acceptRight($.IndexedVisitor indexedVisitor) {
forEachRight(indexedVisitor);
return this;
}
@Override
public C.List head(int n) {
return take(n);
}
@Override
public C.List tail() {
int sz = size();
if (0 == sz) {
throw new UnsupportedOperationException();
}
if (isImmutable()) {
return subList(1, sz);
}
C.List l = C.newSizedList(sz - 1);
l.addAll(subList(1, sz));
return l;
}
@Override
public C.List tail(int n) {
boolean immutable = isImmutable();
int sz = size();
if (n < 0) {
return head(-n);
} else if (n == 0) {
if (immutable) {
return Nil.list();
} else {
return C.newList();
}
} else if (n >= sz) {
return this;
}
C.List sl = subList(sz - n, sz);
if (immutable) {
return sl;
}
C.List l = C.newSizedList(n);
l.addAll(sl);
return l;
}
@SuppressWarnings("unchecked")
private C.List unLazyAppend(Iterable extends T> iterable) {
if (isMutable()) {
if (iterable instanceof Collection) {
addAll((Collection extends T>) iterable);
} else {
C.forEach(iterable, $.visitor(C.F.addTo(this)));
}
return this;
}
// immutable
if (isImmutable()) {
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(this).append(iterable);
return lb.toList();
}
// mutable but read only
C.List l = C.newSizedList(size() * 2);
l.addAll(this);
l.addAll(iterable);
return l;
}
private C.List unLazyAppend(Iterator extends T> iterator) {
if (isMutable()) {
C.forEach(iterator, $.visitor(C.F.addTo(this)));
return this;
}
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(this).append(iterator);
return lb.toList();
}
private C.List unLazyAppend(Enumeration extends T> enumeration) {
if (isMutable()) {
C.forEach(new EnumerationIterator(enumeration), $.visitor(C.F.addTo(this)));
return this;
}
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(this).append(enumeration);
return lb.toList();
}
@Override
@SuppressWarnings("unchecked")
public C.Sequence append(Iterable extends T> iterable) {
if (iterable instanceof C.List) {
return appendList((C.List) iterable);
} else if (iterable instanceof C.Sequence) {
return append((C.Sequence) iterable);
} else if (iterable instanceof Collection) {
return append((Collection extends T>) iterable);
} else if (isLazy()) {
return CompositeSeq.of(this, IterableSeq.of(iterable));
} else {
return unLazyAppend(iterable);
}
}
@Override
@SuppressWarnings("unchecked")
public C.List append(Collection extends T> collection) {
if (collection instanceof C.List) {
return appendList((C.List) collection);
} else {
return unLazyAppend(collection);
}
}
@Override
public C.Sequence append(C.Sequence extends T> seq) {
if (seq instanceof C.List) {
return appendList((C.List) seq);
}
if (isLazy()) {
return CompositeSeq.of(this, seq);
}
return unLazyAppend(seq);
}
@Override
public C.Sequence append(Iterator extends T> iterator) {
if (isLazy()) {
return CompositeSeq.of(this, C.seq(iterator));
}
return unLazyAppend(iterator);
}
@Override
public C.Sequence append(Enumeration extends T> enumeration) {
return append(new EnumerationIterator(enumeration));
}
protected C.ReversibleSequence appendReversibleSeq(C.ReversibleSequence seq) {
if (seq instanceof C.List) {
return appendList((C.List) seq);
}
// TODO support lazy append reversible sequence
return unLazyAppend(seq);
}
public C.ReversibleSequence append(C.ReversibleSequence seq) {
return appendReversibleSeq(seq);
}
protected C.List appendList(C.List list) {
if (isLazy()) {
return CompositeList.of(this, list);
}
return unLazyAppend(list);
}
@Override
public C.List append(C.List list) {
return appendList(list);
}
@Override
public C.List append(T t) {
if (isMutable()) {
add(t);
return this;
}
// Immutable
if (isImmutable()) {
ListBuilder lb = new ListBuilder(size() + 1);
lb.addAll(this);
lb.add(t);
return lb.toList();
}
// mutable but readonly
C.List l = C.newSizedList(size() + 1);
l.addAll(this);
l.add(t);
return l;
}
private C.List unLazyPrepend(Iterable extends T> iterable) {
if (isMutable()) {
int pos = 0;
for (T t : iterable) {
add(pos++, t);
}
return this;
}
// immutable
if (isImmutable()) {
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(iterable).append(this);
return lb.toList();
}
// mutable but read only
C.List l = C.newSizedList(size() * 2);
l.addAll(iterable);
l.addAll(this);
return l;
}
private C.List unLazyPrepend(Iterator extends T> iterator) {
if (isMutable()) {
int pos = 0;
while (iterator.hasNext()) {
add(pos++, iterator.next());
}
return this;
}
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(iterator).append(this);
return lb.toList();
}
private C.List unLazyPrepend(Enumeration extends T> enumeration) {
if (isMutable()) {
int pos = 0;
while (enumeration.hasMoreElements()) {
add(pos++, enumeration.nextElement());
}
return this;
}
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(enumeration).append(this);
return lb.toList();
}
@Override
@SuppressWarnings("unchecked")
public C.List prepend(Collection extends T> collection) {
if (collection instanceof C.List) {
return prependList((C.List) collection);
}
return unLazyPrepend(collection);
}
@Override
@SuppressWarnings("unchecked")
public C.Sequence prepend(Iterable extends T> iterable) {
if (iterable instanceof C.List) {
return prependList((C.List) iterable);
} else if (iterable instanceof C.Sequence) {
return prepend((C.Sequence) iterable);
} else if (iterable instanceof Collection) {
return prepend((Collection extends T>) iterable);
} else if (isLazy()) {
return CompositeSeq.of(IterableSeq.of(iterable), this);
} else {
return unLazyPrepend(iterable);
}
}
@Override
public C.Sequence prepend(Iterator extends T> iterator) {
if (!iterator.hasNext()) {
return this;
}
if (isLazy()) {
return CompositeSeq.of(C.seq(iterator), this);
}
return unLazyAppend(iterator);
}
@Override
public C.Sequence prepend(Enumeration extends T> enumeration) {
if (isLazy()) {
return CompositeSeq.of(C.seq(enumeration), this);
}
return unLazyAppend(enumeration);
}
/**
* {@inheritDoc}
* This method will NOT change the underline list
*
* @param seq the sequence to be prepended
* @return the prepended sequence
*/
@Override
public C.Sequence prepend(C.Sequence extends T> seq) {
if (seq instanceof C.List) {
return prependList((C.List) seq);
}
if (isLazy()) {
return new CompositeSeq(seq, this);
}
return unLazyPrepend(seq);
}
protected C.ReversibleSequence prependReversibleSeq(C.ReversibleSequence seq) {
if (seq instanceof C.List) {
return prependList((C.List) seq);
}
// TODO support lazy append reversible sequence
return unLazyPrepend(seq);
}
public C.ReversibleSequence prepend(C.ReversibleSequence seq) {
return prependReversibleSeq(seq);
}
protected C.List prependList(C.List list) {
if (isLazy()) {
return CompositeList.of(list, this);
}
return unLazyPrepend(list);
}
/**
* {@inheritDoc}
* This method will NOT change the underline list
*/
@Override
public C.List prepend(C.List list) {
return prependList(list);
}
/**
* {@inheritDoc}
* For mutable list, this method will insert the
* element at {@code 0} position.
*/
@Override
public C.List prepend(T t) {
if (isMutable()) {
add(0, t);
return this;
}
// immutable
if (isImmutable()) {
ListBuilder lb = new ListBuilder(size() + 1);
lb.add(t);
lb.addAll(this);
return lb.toList();
}
// readonly but mutable
C.List l = C.newSizedList(size() + 1);
l.add(t);
l.addAll(this);
return l;
}
@Override
public R reduce(R identity, $.Func2 accumulator) {
return reduceLeft(identity, accumulator);
}
@Override
public R reduceLeft(R identity, $.Func2 accumulator) {
R ret = identity;
for (T t : this) {
ret = accumulator.apply(ret, t);
}
return ret;
}
@Override
public R reduceRight(R identity, $.Func2 accumulator) {
R ret = identity;
Iterator i = reverseIterator();
while (i.hasNext()) {
ret = accumulator.apply(ret, i.next());
}
return ret;
}
@Override
public $.Option reduce($.Func2 accumulator) {
return reduceLeft(accumulator);
}
private $.Option reduceIterator(Iterator itr, $.Func2 accumulator) {
if (!itr.hasNext()) {
return $.none();
}
T ret = itr.next();
while (itr.hasNext()) {
ret = accumulator.apply(ret, itr.next());
}
return $.some(ret);
}
@Override
public $.Option reduceLeft($.Func2 accumulator) {
return reduceIterator(iterator(), accumulator);
}
@Override
public $.Option reduceRight($.Func2 accumulator) {
return reduceIterator(reverseIterator(), accumulator);
}
private $.Option findIterator(Iterator itr, $.Function super T, Boolean> predicate) {
while (itr.hasNext()) {
T t = itr.next();
if (predicate.apply(t)) {
return $.some(t);
}
}
return $.none();
}
public $.Option findFirst($.Function super T, Boolean> predicate) {
return findIterator(iterator(), predicate);
}
@Override
public $.Option findLast($.Function super T, Boolean> predicate) {
return findIterator(reverseIterator(), predicate);
}
@Override
public C.List<$.Binary> zip(List list) {
return new ZippedList<>(this, list);
}
@Override
public C.List<$.Binary> zipAll(List list, T def1, T2 def2) {
return new ZippedList<>(this, list, def1, def2);
}
@Override
public C.Sequence<$.Binary> zipWithIndex() {
return new ZippedSeq<>(this, new IndexIterable(this));
}
@Override
public C.Sequence extends $.Binary> zip(Iterable iterable) {
if (iterable instanceof List) {
return zip((List) iterable);
}
return new ZippedSeq<>(this, iterable);
}
@Override
public C.Sequence extends $.Binary> zipAll(Iterable iterable, T def1, T2 def2) {
if (iterable instanceof List) {
return zipAll((List) iterable, def1, def2);
}
return new ZippedSeq<>(this, iterable, def1, def2);
}
@Override
public C.ReversibleSequence<$.Binary> zip(C.ReversibleSequence rseq) {
if (rseq instanceof C.List) {
return zip((java.util.List) rseq);
}
return new ZippedRSeq<>(this, rseq);
}
@Override
public C.ReversibleSequence<$.Binary> zipAll(C.ReversibleSequence rseq, T def1, T2 def2) {
if (rseq instanceof C.List) {
return zipAll((java.util.List) rseq, def1, def2);
}
return new ZippedRSeq<>(this, rseq, def1, def2);
}
@Override
public int count(T t) {
if (sorted) {
int pos = indexOf(t);
if (pos < 0) {
return 0;
}
int n = 1;
for (int i = pos + 1; i < size(); ++i) {
if ($.eq(t, get(i))) {
n++;
} else {
break;
}
}
return n;
}
return SequenceBase.count(this, t);
}
@Override
public C.Map toMap(Lang.Function super T, ? extends K> keyExtractor, Lang.Function super T, ? extends V> valExtractor) {
C.Map