
org.osgl.util.ImmutableList 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 org.osgl.$;
import org.osgl.exception.NotAppliedException;
import org.osgl.util.algo.Algorithms;
import java.io.Serializable;
import java.util.*;
/**
* An immutable list implementation. This class is guaranteed to be NOT empty
*/
class ImmutableList extends ListBase
implements C.List, RandomAccess, Serializable {
private final T[] data_;
/**
* Construct the ImmutableList with an array. The array will be used
* directly as the backing data of this list. No data copy happen
*
* @param data an array of element backing this list
*/
protected ImmutableList(T[] data) {
E.NPE(data);
data_ = data;
}
@Override
protected EnumSet initFeatures() {
return EnumSet.of(C.Feature.READONLY, C.Feature.LIMITED, C.Feature.ORDERED, C.Feature.IMMUTABLE, C.Feature.LAZY, C.Feature.PARALLEL, C.Feature.RANDOM_ACCESS);
}
@Override
public int size() throws UnsupportedOperationException {
return data_.length;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(Object o) {
return indexOf(o) > -1;
}
@Override
public Object[] toArray() {
T[] da = data_;
int sz = da.length;
Object[] ret = new Object[sz];
System.arraycopy(da, 0, ret, 0, sz);
return ret;
}
@Override
@SuppressWarnings("unchecked")
public T1[] toArray(T1[] a) {
int sza = a.length;
T[] da = data_;
int sz = da.length;
if (sza < sz) {
return (T1[]) Arrays.copyOf(da, sz, a.getClass());
}
System.arraycopy(da, 0, a, 0, sz);
if (sza > sz) {
a[sz] = null;
}
return a;
}
@Override
public boolean add(T t) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean containsAll(Collection> c) {
for (Object o : c) {
if (!contains(c)) {
return false;
}
}
return true;
}
@Override
public boolean addAll(Collection extends T> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(int index, Collection extends T> 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();
}
@Override
public T get(int index) {
return data_[index];
}
@Override
public T set(int index, T element) {
throw new UnsupportedOperationException();
}
@Override
public void add(int index, T element) {
throw new UnsupportedOperationException();
}
@Override
public T remove(int index) {
throw new UnsupportedOperationException();
}
@Override
public int indexOf(Object o) {
T[] da = data_;
int sz = da.length;
if (o == null) {
for (int i = 0; i < sz; i++)
if (da[i] == null)
return i;
} else {
for (int i = 0; i < sz; i++)
if (o.equals(da[i]))
return i;
}
return -1;
}
@Override
public int lastIndexOf(Object o) {
T[] da = data_;
int sz = da.length;
if (o == null) {
for (int i = sz - 1; i >= 0; i--)
if (da[i] == null)
return i;
} else {
for (int i = sz - 1; i >= 0; i--)
if (o.equals(da[i]))
return i;
}
return -1;
}
private class Itr implements Iterator {
protected int cursor = 0;
@Override
public boolean hasNext() {
return cursor != data_.length;
}
@Override
public T next() {
T[] da = data_;
if (cursor >= da.length) {
throw new NoSuchElementException();
}
int i = cursor++;
return da[i];
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
@Override
public Iterator iterator() {
return new Itr();
}
private class LstItr extends Itr implements ListIterator {
LstItr() {this(0);}
LstItr(int index) {
if (index < 0 || index > data_.length) {
throw new IndexOutOfBoundsException();
}
cursor = index;
}
@Override
public boolean hasPrevious() {
return cursor != 0;
}
@Override
public T previous() {
if (cursor < 0) {
throw new NoSuchElementException();
}
cursor--;
return data_[cursor];
}
@Override
public int nextIndex() {
return cursor;
}
@Override
public int previousIndex() {
return cursor - 1;
}
@Override
public void set(T t) {
throw new UnsupportedOperationException();
}
@Override
public void add(T t) {
throw new UnsupportedOperationException();
}
}
@Override
public ListIterator listIterator() {
return new LstItr();
}
@Override
public ListIterator listIterator(int index) {
return new LstItr(index);
}
@Override
public C.List map($.Function super T, ? extends R> mapper) {
if (isLazy()) {
return MappedList.of(this, mapper);
}
int sz = size();
ListBuilder lb = new ListBuilder(sz);
forEach($.visitor($.f1(mapper).andThen(C.F.addTo(lb))));
return lb.toList();
}
@Override
public C.List flatMap($.Function super T, ? extends Iterable extends R>> mapper
) {
// TODO: handle lazy operation
int sz = size();
ListBuilder lb = new ListBuilder(sz * 3);
forEach($.visitor($.f1(mapper).andThen(C.F.addAllTo(lb))));
return lb.toList();
}
@Override
public C.Sequence append(Iterable extends T> iterable) {
return super.append(iterable);
}
private C.List unLazyAppend(Collection extends T> collection) {
int szB = collection.size();
if (szB == 0) {
return this;
}
int szA = size();
T[] dataA = data_;
Object[] dataB = collection.toArray();
T[] data = $.newArray(dataA, szA + szB);
System.arraycopy(dataA, 0, data, 0, szA);
System.arraycopy(dataB, 0, data, szA, szB);
return of(data);
}
@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.ReversibleSequence append(C.ReversibleSequence seq) {
if (seq instanceof C.List) {
return appendList((C.List) seq);
}
return super.appendReversibleSeq(seq);
}
@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);
}
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(this).append(seq);
return lb.toList();
}
@Override
public C.Sequence append(Iterator extends T> iterator) {
if (isLazy()) {
return CompositeSeq.of(this, C.seq(iterator));
}
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(this).append(iterator);
return lb.toList();
}
@Override
public C.Sequence append(Enumeration extends T> enumeration) {
if (isLazy()) {
return CompositeSeq.of(this, C.seq(enumeration));
}
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(this).append(enumeration);
return lb.toList();
}
protected C.List appendList(C.List l) {
if (isLazy()) {
return CompositeList.of(this, l);
}
if (l instanceof ImmutableList) {
return appendImmutableList((ImmutableList) l);
}
return unLazyAppend(l);
}
public C.List append(C.List l) {
return appendList(l);
}
private C.List appendImmutableList(ImmutableList l) {
int szA = size();
int szB = l.size();
T[] dataA = data_;
T[] data = $.newArray(dataA, szA + szB);
System.arraycopy(dataA, 0, data, 0, szA);
System.arraycopy(l.data_, 0, data, szA, szB);
return of(data);
}
public C.List append(ImmutableList l) {
return appendImmutableList(l);
}
private C.List unLazyPrepend(Collection extends T> collection) {
int szB = collection.size();
if (szB == 0) {
return this;
}
int szA = size();
T[] dataA = data_;
Object[] dataB = collection.toArray();
T[] data = $.newArray(dataA, szA + szB);
System.arraycopy(dataB, 0, data, 0, szB);
System.arraycopy(dataA, 0, data, szB, szA);
return of(data);
}
@Override
@SuppressWarnings("unchecked")
public C.List prepend(Collection extends T> collection) {
if (collection instanceof C.List) {
return prependList((C.List) collection);
} else {
return unLazyPrepend(collection);
}
}
@Override
public C.ReversibleSequence prepend(C.ReversibleSequence seq) {
return super.prependReversibleSeq(seq);
}
@Override
public C.Sequence prepend(C.Sequence extends T> seq) {
if (seq instanceof C.List) {
return prependList((C.List) seq);
}
if (isLazy()) {
return CompositeSeq.of(seq, this);
}
ListBuilder lb = new ListBuilder(size() * 2);
lb.append(seq).append(this);
return lb.toList();
}
public C.List prepend(C.List l) {
if (isLazy()) {
return CompositeList.of(l, this);
}
if (l instanceof ImmutableList) {
return prependList((ImmutableList) l);
}
return unLazyPrepend(l);
}
public C.List prepend(ImmutableList l) {
if (isLazy()) {
return CompositeList.of(l, this);
}
int szA = size();
int szB = l.size();
T[] myData = data_;
T[] data = $.newArray(myData, szA + szB);
System.arraycopy(l.data_, 0, data, 0, szB);
System.arraycopy(myData, 0, data, szB, szA);
return of(data);
}
private class ReverseItr implements Iterator {
private LstItr itr;
ReverseItr() {
itr = new LstItr(size());
}
@Override
public boolean hasNext() {
return itr.hasPrevious();
}
@Override
public T next() {
return itr.previous();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
@Override
public Iterator reverseIterator() {
return new ReverseItr();
}
@Override
public $.Option findLast($.Function super T, Boolean> predicate) {
T[] ta = data_;
for (int i = ta.length - 1; i >= 0; --i) {
T t = ta[i];
if (predicate.apply(t)) {
return $.some(t);
}
}
return $.none();
}
@Override
public C.List takeWhile($.Function super T, Boolean> predicate) {
int sz = size();
ListBuilder lb = new ListBuilder(sz);
for (T t : this) {
if (predicate.apply(t)) {
lb.add(t);
} else {
break;
}
}
return lb.toList();
}
@Override
public C.List without(Collection super T> col) {
int sz = size();
T[] data = data_;
ListBuilder lb = new ListBuilder(sz);
for (int i = 0; i < sz; ++i) {
T t = data[i];
if (!col.contains(t)) {
lb.add(t);
}
}
return lb.toList();
}
@Override
public C.List without(T element) {
int sz = size();
T[] data = data_;
ListBuilder lb = new ListBuilder(sz);
for (int i = 0; i < sz; ++i) {
T t = data[i];
if ($.ne(t, element)) {
lb.add(t);
}
}
return lb.toList();
}
@Override
public C.List without(T element, T... elements) {
int len = elements.length;
if (len == 0) return without(element);
int sz = size();
T[] data = data_;
ListBuilder lb = new ListBuilder(sz);
T t0 = elements[0];
boolean c = false;
if (len < 8 && t0 instanceof Comparable) {
Arrays.sort(elements);
c = true;
}
if (c) {
for (int i = 0; i < sz; ++i) {
T t = data[i];
if ($.eq(t, element)) {
continue;
}
int id = Arrays.binarySearch(elements, t);
if (id > -1) continue;
lb.add(t);
}
} else {
for (int i = 0; i < sz; ++i) {
T t = data[i];
if ($.eq(t, element)) {
continue;
}
boolean found = false;
for (int j = 0; j < len; ++j) {
if ($.eq(elements[j], t)) {
found = true;
break;
};
}
if (!found) {
lb.add(t);
}
}
}
return lb.toList();
}
@Override
@SuppressWarnings("unchecked")
public C.List reverse() {
if (isLazy()) {
return ReverseList.wrap(this);
}
T[] data = (T[]) Algorithms.ARRAY_REVERSE.apply(data_, 0, data_.length);
return of(data);
}
@Override
public C.List prepend(T t) {
int sz = size();
T[] myData = data_;
T[] data = $.newArray(myData, sz + 1);
data[0] = t;
System.arraycopy(myData, 0, data, 1, sz);
return of(data);
}
@Override
public C.List append(T t) {
int sz = size();
T[] myData = data_;
T[] data = $.newArray(myData, sz + 1);
data[sz] = t;
System.arraycopy(myData, 0, data, 0, sz);
return of(data);
}
@Override
public C.List insert(int index, T t) throws IndexOutOfBoundsException {
T[] myData = data_;
int sz = data_.length;
if (sz < Math.abs(index)) {
throw new IndexOutOfBoundsException();
}
if (index < 0) {
index = sz + index;
}
T[] data = $.newArray(myData, sz + 1);
System.arraycopy(myData, 0, data, 0, index);
data[index] = t;
System.arraycopy(myData, index, data, index + 1, sz - index);
return of(data);
}
@Override
public C.List insert(int index, T... ta) throws IndexOutOfBoundsException {
if (ta.length == 0) {
return this;
}
T[] myData = data_;
int sz = data_.length;
if (sz < Math.abs(index)) {
throw new IndexOutOfBoundsException();
}
if (index < 0) {
index = sz + index;
}
int delta = ta.length;
T[] data = $.newArray(myData, sz + delta);
if (index > 0) {
System.arraycopy(myData, 0, data, 0, index);
}
System.arraycopy(ta, 0, data, index, delta);
if (index < sz) {
System.arraycopy(myData, index, data, index + delta, sz - index);
}
return of(data);
}
@Override
public C.List insert(int index, List subList) throws IndexOutOfBoundsException {
if (subList.isEmpty()) {
return this;
}
T[] myData = data_;
int sz = data_.length;
if (sz < Math.abs(index)) {
throw new IndexOutOfBoundsException();
}
if (index < 0) {
index = sz + index;
}
int delta = subList.size();
T[] data = $.newArray(myData, sz + delta);
if (index > 0) {
System.arraycopy(myData, 0, data, 0, index);
}
for (int i = 0; i < delta; ++i) {
data[index + i] = subList.get(i);
}
if (index < sz) {
System.arraycopy(myData, index, data, index + delta, sz - index);
}
return of(data);
}
private class Csr implements Cursor {
private int id_;
Csr() {this(-1);}
Csr(int index) {
if (index < -1) {
index = -1;
} else if (index > size()) {
index = size();
}
id_ = index;
}
@Override
public boolean isDefined() {
int id = id_;
return id > -1 && id < size();
}
@Override
public int index() {
return id_;
}
@Override
public T get() throws NoSuchElementException {
if (!isDefined()) {
throw new NoSuchElementException();
}
return data_[id_];
}
@Override
public boolean hasNext() {
return id_ < size() - 1;
}
@Override
public boolean hasPrevious() {
return id_ > 0;
}
@Override
public Cursor parkLeft() {
id_ = -1;
return this;
}
@Override
public Cursor parkRight() {
id_ = size();
return this;
}
@Override
public Cursor forward() {
if (id_ >= size()) {
id_ = size();
throw new UnsupportedOperationException();
}
id_++;
return this;
}
@Override
public Cursor backward() throws UnsupportedOperationException {
if (id_ <= -1) {
id_ = -1;
throw new UnsupportedOperationException();
}
id_--;
return this;
}
@Override
public Cursor set(T t) throws IndexOutOfBoundsException, NullPointerException {
throw new UnsupportedOperationException();
}
@Override
public Cursor drop() throws NoSuchElementException {
throw new UnsupportedOperationException();
}
@Override
public Cursor prepend(T t) throws IndexOutOfBoundsException {
throw new UnsupportedOperationException();
}
@Override
public Cursor append(T t) {
throw new UnsupportedOperationException();
}
}
@Override
public Cursor locateLast($.Function predicate) {
int sz = size();
T[] data = data_;
for (int i = sz - 1; i >= 0; --i) {
T t = data[i];
if (predicate.apply(t)) {
return new Csr(i);
}
}
return new Csr(-1);
}
@Override
public Cursor locate($.Function predicate) {
return locateFirst(predicate);
}
@Override
public Cursor locateFirst($.Function predicate) {
int sz = size();
T[] data = data_;
for (int i = 0; i < sz; ++i) {
T t = data[i];
if (predicate.apply(t)) {
return new Csr(i);
}
}
return new Csr(sz);
}
@Override
public C.List filter($.Function super T, Boolean> predicate) {
// TODO: handle lazy operation
int sz = size();
if (0 == sz) {
return Nil.list();
}
T[] data = $.newArray(data_);
int cursor = 0;
for (int i = 0; i < sz; ++i) {
T t = data_[i];
if (predicate.apply(t)) {
data[cursor++] = t;
}
}
if (0 == cursor) {
return Nil.list();
}
data = Arrays.copyOf(data, cursor);
return of(data);
}
@Override
public C.List dropWhile($.Function super T, Boolean> predicate) {
//TODO: handle lazy operation
int sz = size();
$.Function f = $.F.negate(predicate);
Cursor cursor = locateFirst(f);
if (!cursor.isDefined()) {
return Nil.list();
}
int id = cursor.index();
return subList(id, size());
}
@Override
public C.List drop(int n) throws IndexOutOfBoundsException {
int size = size();
if (n < 0) {
n = -n;
if (n >= size) return C.list();
return take(size - n);
}
if (0 == n) {
return this;
}
if (n >= size) {
return Nil.list();
}
return subList(n, size());
}
@Override
public C.List tail(int n) {
if (n < 0) {
return head(-n);
}
int sz = size();
if (n >= sz) {
return this;
}
return subList(sz - n, sz);
}
@Override
public C.List tail() {
int sz = size();
if (sz == 0) {
throw new UnsupportedOperationException();
}
return subList(1, sz);
}
@Override
public C.List take(int n) {
if (n < 0) {
return tail(-n);
}
int sz = size();
if (n >= sz) {
return this;
}
return subList(0, n);
}
@Override
protected void forEachLeft($.Visitor super T> visitor) throws $.Break {
int sz = size();
T[] data = data_;
for (int i = 0; i < sz; ++i) {
T t = data[i];
try {
visitor.apply(t);
} catch (NotAppliedException e) {
// ignore
}
}
}
@Override
protected void forEachRight($.Visitor super T> visitor) throws $.Break {
int sz = size();
T[] data = data_;
for (int i = sz - 1; i >= 0; --i) {
T t = data[i];
try {
visitor.apply(t);
} catch (NotAppliedException e) {
// ignore
}
}
}
@Override
public $.Option findOne($.Function super T, Boolean> predicate) {
//todo parallel finding
int sz = size();
T[] data = data_;
for (int i = 0; i < sz; ++i) {
T t = data[i];
if (predicate.apply(t)) {
return $.some(t);
}
}
return $.none();
}
@Override
public T head() throws NoSuchElementException {
return data_[0];
}
@Override
public T last() throws NoSuchElementException {
return data_[size() - 1];
}
@Override
public R reduce(R identity, $.Func2 accumulator) {
// TODO: parallel
return reduceLeft(identity, accumulator);
}
@Override
public R reduceLeft(R identity, $.Func2 accumulator) {
int sz = size();
R ret = identity;
T[] data = data_;
for (int i = 0; i < sz; ++i) {
ret = accumulator.apply(ret, data[i]);
}
return ret;
}
@Override
public R reduceRight(R identity, $.Func2 accumulator) {
int sz = size();
R ret = identity;
T[] data = data_;
for (int i = sz - 1; i >= 0; --i) {
ret = accumulator.apply(ret, data[i]);
}
return ret;
}
@Override
public $.Option reduce($.Func2 accumulator) {
// TODO parallel
return reduceLeft(accumulator);
}
@Override
public $.Option reduceLeft($.Func2 accumulator) {
int sz = size();
T[] data = data_;
T ret = data[0];
for (int i = 1; i < sz; ++i) {
ret = accumulator.apply(ret, data[i]);
}
return $.some(ret);
}
@Override
public $.Option reduceRight($.Func2 accumulator) {
int sz = size();
T[] data = data_;
T ret = data[sz - 1];
for (int i = sz - 2; i >= 0; --i) {
ret = accumulator.apply(ret, data[i]);
}
return $.some(ret);
}
@Override
int modCount() {
return 0;
}
@Override
void removeRange2(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
static C.List of(T[] data) {
E.NPE(data);
int len = data.length;
if (len == 0) {
return Nil.list();
} else if (len == 1) {
return $.val(data[0]);
} else {
return new ImmutableList<>(data);
}
}
static C.List copyOf(T[] data) {
int sz = data.length;
if (sz == 0) {
return Nil.list();
}
T[] a = Arrays.copyOf(data, sz);
return new ImmutableList(a);
}
}
class ImmutableSubList extends RandomAccessSubList {
ImmutableSubList(ListBase list, int fromIndex, int toIndex) {
super(list, fromIndex, toIndex);
}
@Override
public C.List subList(int fromIndex, int toIndex) {
return new ImmutableSubList(this, fromIndex, toIndex);
}
@Override
protected void checkForComodification() {
return;
}
@Override
public T set(int index, T element) {
throw new UnsupportedOperationException();
}
@Override
public void add(int index, T element) {
throw new UnsupportedOperationException();
}
@Override
public T remove(int index) {
throw new UnsupportedOperationException();
}
@Override
protected void removeRange(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection extends T> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(int index, Collection extends T> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Iterable extends T> iterable) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean add(T t) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection> c) {
throw new UnsupportedOperationException();
}
}
class ImmutableStringList extends ImmutableList implements S.List {
public ImmutableStringList(String[] data) {
super(data);
}
static S.List of(String[] data) {
E.NPE(data);
int len = data.length;
if (len == 0) {
return new Nil.EmptyStringList();
} else if (len == 1) {
return S.val(data[0]);
} else {
return new ImmutableStringList(data);
}
}
static S.List of(java.util.Collection strings) {
return of(strings.toArray(new String[strings.size()]));
}
static S.List of(Iterable strings) {
if (strings instanceof S.List) {
return $.cast(strings);
}
if (strings instanceof Collection) {
return of((Collection) strings);
}
return of(C.list(strings));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy