
org.osgl.util.C Maven / Gradle / Ivy
/*
* Copyright (C) 2013 The Java Tool project
* Gelin Luo
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.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.Lang.Visitor;
import org.osgl.$;
import org.osgl.Lang;
import org.osgl.Lang.Func2;
import org.osgl.Lang.IndexedVisitor;
import org.osgl.exception.NotAppliedException;
import org.osgl.exception.ReadOnlyException;
import org.osgl.util.algo.Algorithms;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
/**
* The namespace for OSGL collection utilities
* Alias of {@link CollectionUtil}
*/
public class C {
C() {
}
/**
* The character enum for a data structure
*/
public enum Feature {
/**
* Indicate whether a structure is immutable
*/
IMMUTABLE,
/**
* Indicate the client cannot modify the structure.
* However a readonly structure might not be immutable.
* For example a view of a backing structure is readonly
* while the backing structure is immutable
*/
READONLY,
/**
* Indicate whether a list structure support random access
*/
RANDOM_ACCESS,
/**
* Indicate whether the structure is limited
*/
LIMITED,
/**
* Indicate whether the structure supports lazy evaluation
*/
LAZY,
/**
* Indicate whether the structure support parallel operation
*/
PARALLEL,
/**
* Indicate whether this structure is ordered. E.g. a
* {@link List} and {@link java.util.LinkedHashSet} is ordered
* structure, while {@link java.util.HashSet} might not be
* ordered
*/
ORDERED,
/**
* Indicate whether this structure is sorted
*/
SORTED
}
/**
* Define a type that holds a set of {@link org.osgl.util.C.Feature}
*/
public interface Featured {
/**
* Get all characteristics in {@link EnumSet}
*
* @return an {@code EnumSet} of all characteristics hold by this object
* @since 0.2
*/
EnumSet features();
/**
* Check if this object has a certain {@link org.osgl.util.C.Feature}
*
* @param c the characteristic to be tested
* @return {@code true} if this object has the characteristic, or {@code false} otherwise
* @since 0.2
*/
boolean is(Feature c);
@SuppressWarnings("unused")
class Factory {
public static Featured identity(final EnumSet predefined) {
return new Featured() {
@Override
public EnumSet features() {
return predefined;
}
@Override
public boolean is(Feature c) {
return predefined.contains(c);
}
};
}
}
}
/**
* Define a traversable structure with functional programming support,
* including map, reduce etc.
*
* @param The element type
*/
public interface Traversable extends Iterable, Featured {
/**
* Returns this traversable and try to turn on
* {@link C.Feature#PARALLEL}. If this traversable does not
* support {@link org.osgl.util.C.Feature#PARALLEL} then
* return this traversable directly without any state change
*
* @return this reference with parallel turned on if parallel
* is supported
*/
Traversable parallel();
/**
* Returns this traversable and turn off
* {@link C.Feature#PARALLEL}
*
* @return this reference with parallel turned off
*/
Traversable sequential();
/**
* Returns this traversable and try to turn on {@link C.Feature#LAZY}.
* If lazy is not supported then return this traversable directly without
* any state change
*
* @return this reference with lazy turned on if it is supported
*/
Traversable lazy();
/**
* Returns this traversable and turn off {@link C.Feature#LAZY}
*
* @return this reference with lazy turned off
*/
Traversable eager();
/**
* Is this traversal empty?
*
* @return {@code true} if the traversal is empty or {@code false} otherwise
* @since 0.2
*/
boolean isEmpty();
/**
* Return the size of this traversal
*
* @return the size of the structure
* @throws UnsupportedOperationException if this structure does not support this method
* @since 0.2
*/
int size() throws UnsupportedOperationException;
/**
* Returns an new traversable with a mapper function specified. The element in the new traversal is the result of the
* mapper function applied to this traversal element.
*
* Traversable traversable = C.list(23, _.NONE, null);
* assertEquals(C.list(true, false, false), traversal.map(_.F.NOT_NULL));
* assertEquals(C.list("23", "", ""), traversal.map(_.F.AS_STRING));
*
* For Lazy Traversable, it must use lazy evaluation for this method.
* Otherwise it is up to implementation to decide whether use lazy
* evaluation or not
*
* @param mapper the function that applied to element in this traversal and returns element in the result traversal
* @param the element type of the new traversal
* @return the new traversal contains results of the mapper function applied to this traversal
* @since 0.2
*/
Traversable map($.Function super T, ? extends R> mapper);
/**
* Returns a traversable consisting of the results of replacing each element of this
* stream with the contents of the iterable produced by applying the provided mapping
* function to each element. If the result of the mapping function is {@code null},
* this is treated as if the result is an empty traversable.
*
* @param mapper the function produce an iterable when applied to an element
* @param the element type of the the new traversable
* @return the new traversable
* @since 0.2
*/
Traversable flatMap($.Function super T, ? extends Iterable extends R>> mapper);
Traversable collect(String path);
/**
* Returns an new traversable that contains all elements in the current traversable
* except that does not pass the test of the filter function specified.
*
* Traversable traversable = C.list(-1, 0, 1, -3, 7);
* Traversable filtered = traversable.filter(_.F.gt(0));
* assertTrue(filtered.contains(1));
* assertFalse(filtered.contains(-3));
*
*
* @param predicate the function that test if the element in the traversable should be
* kept in the resulting traversable. When applying the filter function
* to the element, if the result is {@code true} then the element will
* be kept in the resulting traversable.
* @return the new traversable consists of elements passed the filter function test
* @since 0.2
*/
Traversable filter($.Function super T, Boolean> predicate);
/**
* Performs a reduction on the elements in this traversable, using the provided
* identity and accumulating function. This might be equivalent to:
*
* R result = identity;
* for (T element: this traversable) {
* result = accumulator.apply(result, element);
* }
* return result;
*
* The above shows a typical left side reduce. However depending on the
* implementation, it might choose another way to do the reduction, including
* reduction in a parallel way
*
* @param identity the identity value for the accumulating function
* @param accumulator the function the combine two values
* @param the type of identity and the return value
* @return the result of reduction
* @since 0.2
*/
R reduce(R identity, Func2 accumulator);
/**
* Performs a reduction on the elements in this traversable, using provided accumulating
* function. This might be equivalent to:
*
* boolean found = false;
* T result = null;
* for (T element: this traversable) {
* if (found) {
* result = accumulator.apply(result, element);
* } else {
* found = true;
* result = element;
* }
* }
* return found ? _.some(result) : _.none();
*
* The above shows a typical left side reduction. However depending on the
* implementation, it might choose another way to do the reduction, including
* reduction in a parallel way
*
* @param accumulator the function takes previous accumulating
* result and the current element being
* iterated
* @return an option describing the accumulating result or {@link Lang#none()} if
* the structure is empty
* @since 0.2
*/
$.Option reduce(Func2 accumulator);
/**
* Check if all elements match the predicate specified
*
* @param predicate the function to test the element
* @return {@code true} if all elements match the predicate
* @since 0.2
*/
boolean allMatch($.Function super T, Boolean> predicate);
/**
* Check if any elements matches the predicate specified
*
* @param predicate the function to test the element
* @return {@code true} if any element matches the predicate
* @since 0.2
*/
boolean anyMatch($.Function super T, Boolean> predicate);
/**
* Check if no elements matches the predicate specified. This should be
* equivalent to:
*
* this.allMatch(_.F.negate(predicate));
*
*
* @param predicate the function to test the element
* @return {@code true} if none element matches the predicate
* @since 0.2
*/
boolean noneMatch($.Function super T, Boolean> predicate);
/**
* Returns an element that matches the predicate specified. The interface
* does not indicate if it should be the first element matches the predicate
* be returned or in case of parallel computing, whatever element matches
* found first is returned. It's all up to the implementation to refine the
* semantic of this method
*
* @param predicate the function map element to Boolean
* @return an element in this traversal that matches the predicate or
* {@link Lang#NONE} if no element matches
* @since 0.2
*/
$.Option findOne($.Function super T, Boolean> predicate);
/**
* Iterate this {@code Traversable} with a visitor function. This method
* does not specify the approach to iterate through this structure. The
* implementation might choose iterate from left to right, or vice versa.
* It might even choose to split the structure into multiple parts, and
* iterate through them in parallel
*
* @param visitor a function that apply to element in this
* {@code Traversable}. The return value
* of the function is ignored
* @return this {@code Traversable} instance for chained call
* @since 0.2
*/
Traversable accept(Lang.Visitor super T> visitor);
/**
* Alias of {@link #accept(Lang.Visitor)}
* @param visitor the visitor to tranverse the elements
* @return this {@code Traversable} instance
*/
Traversable each($.Visitor super T> visitor);
/**
* Alias of {@link #accept(Lang.Visitor)}
* @param visitor the visitor function
* @return this {@code Traversable} instance
*/
Traversable forEach($.Visitor super T> visitor);
}
public interface Sequence
extends Traversable {
/**
* Returns this traversable and make sure {@link C.Feature#PARALLEL} is set
*
* @return this reference with parallel turned on
*/
Sequence parallel();
/**
* Returns this traversable and make sure {@link C.Feature#PARALLEL} is unset
*
* @return this reference with parallel turned off
*/
Sequence sequential();
/**
* Returns this traversable and make sure {@link C.Feature#LAZY} is set
*
* @return this reference with lazy turned on
*/
Sequence lazy();
/**
* Returns this traversable and make sure {@link C.Feature#LAZY} is unset
*
* @return this reference with lazy turned off
*/
Sequence eager();
/**
* Alias of {@link #head()}
*
* @return the first element in the sequence
* @since 0.2
*/
T first() throws NoSuchElementException;
/**
* Returns an {@link Lang.Option} of the first element in the
* {@code Sequence}
*
* @return the first element from the {@code Sequence}
* @throws NoSuchElementException if the {@code Sequence} is empty
* @see #tail()
* @see #first()
* @since 0.2
*/
T head() throws NoSuchElementException;
/**
* Alias of {@link #take(int)}
*
* @param n the number of elements to be taken into the return sequence
* @return the first {@code n} element in the sequence
* @since 0.2
*/
Sequence head(int n);
/**
* Returns the rest part of the {@code Sequence} except the first element
*
* @return a {@code Sequence} without the first element
* @throws UnsupportedOperationException if the {@code Sequence} is empty
* @see #head()
* @see ReversibleSequence#tail(int)
* @since 0.2
*/
Sequence tail() throws UnsupportedOperationException;
/**
* Returns a {@code Sequence} consisting the first {@code n} elements from this {@code Sequence} if
* number {@code n} is positive and the {@code Sequence} contains more than {@code n} elements
* If this {@code Sequence} contains less than {@code n} elements, then a {@code Sequence} consisting
* the whole elements of this {@code Sequence} is returned. Note it might return this {@code Sequence}
* itself if the {@code Sequence} is immutable.
* If the number {@code n} is zero, then an empty {@code Sequence} is returned in reverse
* order
* If the number {@code n} is negative, then the last {@code -n} elements from this
* {@code Sequence} is returned in an new {@code Sequence}, or throw {@link UnsupportedOperationException}
* if this operation is not supported
*
* Sequence seq = C.list(1, 2, 3, 4);
* assertEquals(C.list(1, 2), seq.take(2));
* assertEquals(C.list(1, 2, 3, 4), seq.take(100));
* assertEquals(C.list(), seq.take(0));
* assertEquals(C.list(3, 4), seq.take(-2));
* assertEquals(C.list(1, 2, 3, 4), seq.take(-200));
*
*
* @param n specify the number of elements to be taken from the head of this {@code Sequence}
* @return a {@code Sequence} consisting of the first {@code n} elements of this {@code Sequence}
* @see #head(int)
* @since 0.2
*/
Sequence take(int n);
/**
* Returns an new {@code Sequence} that takes the head of this {@code Sequence} until the predicate
* evaluate to {@code false}:
*
* C.Sequence seq = C.list(1, 2, 3, 4, 5, 4, 3, 2, 1);
* assertEquals(C.list(C.list(1, 2, 3), seq.takeWhile(_.F.lt(4)));
* assertEquals(C.list(C.list(1, 2, 3, 3, 2, 1), seq.filter(_.F.lt(4)));
*
*
* @param predicate specify which the elements in this {@code Sequence} will put into the new
* {@code Sequence}
* @return the new {@code Sequence}
* @since 0.2
*/
Sequence takeWhile($.Function super T, Boolean> predicate);
/**
* Returns a {@code Sequence} consisting of the elements from this {@code Sequence} except the first {@code n}
* if number {@code n} is positive and the {@code Sequence} contains more than {@code n} elements
* If this {@code Sequence} contains less than {@code n} elements, then an empty {@code Sequence}
* is returned
* If the number {@code n} is zero, then a copy of this {@code Sequence} or this {@code Sequence}
* itself is returned depending on the implementation
* If the number {@code n} is negative, then either {@link IllegalArgumentException} should
* be thrown out if this sequence is not {@link org.osgl.util.C.Feature#LIMITED} or it drop
* {@code -n} element starts from the tail side
*
* C.Sequence seq = C.list(1, 2, 3, 4, 5);
* assertEquals(C.list(3, 4, 5), seq.drop(2));
* assertEquals(C.list(1, 2, 3, 4, 5), seq.drop(0));
* assertEquals(C.list(), seq.drop(100));
*
* Note this method does NOT modify the current sequence, instead it returns an new sequence structure
* containing the elements as required
*
* @param n specify the number of elements to be taken from the head of this {@code Sequence}
* must not less than 0
* @return a {@code Sequence} consisting of the elements of this {@code Sequence} except the first {@code n} ones
* @since 0.2
*/
Sequence drop(int n) throws IllegalArgumentException;
/**
* Returns a {@code Sequence} consisting of the elements from this sequence with leading elements
* dropped until the predicate returns {@code true}
*
* Sequence seq = C.list(1, 2, 3, 4, 3, 2, 1);
* assertTrue(C.list(), seq.dropWhile(_.F.gt(100)));
* assertTrue(C.list(4, 3, 2, 1), seq.dropWhile(_.F.lt(3)));
*
* Note this method does NOT modify the current sequence, instead it returns an new sequence structure
* containing the elements as required
*
* @param predicate the function that check if drop operation should stop
* @return the sequence after applying the drop operations
* @since 0.2
*/
Sequence dropWhile($.Function super T, Boolean> predicate);
/**
* Returns a sequence consists of all elements of this sequence
* followed by all elements of the specified iterable.
* An {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might append specified seq to {@code this} sequence instance
* directly
*
* @param iterable the iterable in which elements will be append to this sequence
* @return the sequence after append the iterable
*/
Sequence append(Iterable extends T> iterable);
/**
* Returns a sequence consists of all elements of this sequence
* followed by all elements of the specified sequence.
* An {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might append specified seq to {@code this} sequence instance
* directly
*
* @param seq the sequence to be appended
* @return a sequence consists of elements of both sequences
* @since 0.2
*/
Sequence append(Sequence extends T> seq);
/**
* Returns a sequence consists of all elements of this sequence
* followed by all elements of the specified iterator.
* An {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might append specified seq to {@code this} sequence instance
* directly
*
* @param iterator the iterator in which elements will be append to the returned sequence
* @return a sequence consists of elements of this sequence and the elements in the iterator
* @since 0.9
*/
Sequence append(Iterator extends T> iterator);
/**
* Returns a sequence consists of all elements of this sequence
* followed by all elements of the specified enumeration.
* An {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might append specified seq to {@code this} sequence instance
* directly
*
* @param enumeration the enumeration in which elements will be append to the returned sequence
* @return a sequence consists of elements of this sequence and the elements in the iterator
* @since 0.9
*/
Sequence append(Enumeration extends T> enumeration);
/**
* Returns a sequence consists of all elements of this sequence
* followed by the element specified.
* an {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might append the element to {@code this} sequence instance
* directly
*
* @param t the element to be appended to this sequence
* @return a sequence consists of elements of this sequence
* and the element {@code t}
* @since 0.2
*/
Sequence append(T t);
/**
* Returns a sequence consists of all elements of the iterable specified
* followed by all elements of this sequence
* An {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might prepend specified seq to {@code this} sequence instance
* directly
*
* @param iterable the iterable to be prepended
* @return a sequence consists of elements of both sequences
* @since 0.2
*/
Sequence prepend(Iterable extends T> iterable);
/**
* Returns a sequence consists of all elements of the iterator specified
* followed by all elements of this sequence
* An {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might prepend specified seq to {@code this} sequence instance
* directly
*
* @param iterator the iterator to be prepended
* @return a sequence consists of elements of both sequences
* @since 0.2
*/
Sequence prepend(Iterator extends T> iterator);
/**
* Returns a sequence consists of all elements of the enumeration specified
* followed by all elements of this sequence
* An {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might prepend specified seq to {@code this} sequence instance
* directly
*
* @param enumeration the enumeration to be prepended
* @return a sequence consists of elements of both sequences
* @since 0.2
*/
Sequence prepend(Enumeration extends T> enumeration);
/**
* Returns a sequence consists of all elements of the sequence specified
* followed by all elements of this sequence
* An {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might prepend specified seq to {@code this} sequence instance
* directly
*
* @param seq the sequence to be prepended
* @return a sequence consists of elements of both sequences
* @since 0.2
*/
Sequence prepend(Sequence extends T> seq);
/**
* Returns a sequence consists of the element specified followed by
* all elements of this sequence.
* an {@link C.Feature#IMMUTABLE immutable} Sequence must
* return an new Sequence; while a mutable Sequence implementation
* might append the element to {@code this} sequence instance
* directly
*
* @param t the element to be appended to this sequence
* @return the sequence consists of {@code t} followed
* by all elements in this sequence
* @since 0.2
*/
Sequence prepend(T t);
/**
* Returns a List contains all the elements in this sequence with the same order.
* @return the list as described above
*/
List asList();
/**
* {@inheritDoc}
*
* @param mapper {@inheritDoc}
* @param {@inheritDoc}
* @return a Sequence of {@code R} that are mapped from this sequence
* @since 0.2
*/
@Override
Sequence map($.Function super T, ? extends R> mapper);
/**
* {@inheritDoc}
*
* @param mapper {@inheritDoc}
* @param {@inheritDoc}
* @return a Sequence of {@code R} type element that are mapped from this sequences
* @since 0.2
*/
@Override
Sequence flatMap($.Function super T, ? extends Iterable extends R>> mapper);
@Override
Sequence collect(String path);
/**
* {@inheritDoc}
*
* @param predicate {@inheritDoc}
* @return An new {@code Sequence} consists of elements that passed the predicate
* @since 0.2
*/
@Override
Sequence filter(final $.Function super T, Boolean> predicate);
/**
* {@inheritDoc}
* This method does not specify how to run the accumulator. It might be
* {@link C.Sequence#reduceLeft(Object, Func2)} or
* {@link ReversibleSequence#reduceRight(Object, Func2)}, or
* even run reduction in parallel, it all depending on the implementation.
* For a guaranteed reduce from left to right, use
* {@link C.Sequence#reduceLeft(Object, Func2)} instead
*
* @param identity {@inheritDoc}
* @param accumulator {@inheritDoc}
* @param {@inheritDoc}
* @return {@inheritDoc}
* @since 0.2
*/
@Override
R reduce(R identity, Func2 accumulator);
/**
* Run reduction from header side. This is equivalent to:
*
* R result = identity;
* for (T element: this sequence) {
* result = accumulator.apply(result, element);
* }
* return result;
*
*
* @param identity the identity value for the accumulating function
* @param accumulator the function to accumulate two values
* @param the aggregation result type
* @return the reduced result
* @since 0.2
*/
R reduceLeft(R identity, Func2 accumulator);
/**
* {@inheritDoc}
* This method does not specify the approach to run reduction.
* For a guaranteed reduction from head to tail, use
* {@link #reduceLeft(Func2)} instead
*
* @param accumulator {@inheritDoc}
* @return {@inheritDoc}
* @since 0.2
*/
@Override
$.Option reduce(Func2 accumulator);
/**
* Run reduction from head to tail. This is equivalent to
*
* if (isEmpty()) {
* return _.none();
* }
* T result = head();
* for (T element: this traversable.tail()) {
* result = accumulator.apply(result, element);
* }
* return _.some(result);
*
*
* @param accumulator the function accumulate each element to the final result
* @return an {@link Lang.Option} describing the accumulating result
* @since 0.2
*/
$.Option reduceLeft(Func2 accumulator);
/**
* Apply the predicate specified to the element of this sequence
* from head to tail. Stop at the element that returns {@code true},
* and returns an {@link Lang.Option} describing the element. If none
* of the element applications in the sequence returns {@code true}
* then {@link Lang#none()} is returned
*
* @param predicate the function map the element to Boolean
* @return an option describe the first element matches the
* predicate or {@link Lang#none()}
* @since 0.2
*/
$.Option findFirst($.Function super T, Boolean> predicate);
Sequence accept($.Visitor super T> visitor);
Sequence each($.Visitor super T> visitor);
Sequence forEach($.Visitor super T> visitor);
/**
* Iterate through this sequence from head to tail with
* the visitor function specified
*
* @param visitor the function to visit elements in this sequence
* @return this sequence
* @see Traversable#accept(Lang.Visitor)
* @see ReversibleSequence#acceptRight(Lang.Visitor)
* @since 0.2
*/
Sequence acceptLeft($.Visitor super T> visitor);
/**
* Returns a sequence formed from this sequence and another iterable
* collection by combining corresponding elements in pairs.
* If one of the two collections is longer than the other,
* its remaining elements are ignored.
*
* @param iterable the part B to be zipped with this sequence
* @param the type of the iterable
* @return a new sequence containing pairs consisting of
* corresponding elements of this sequence and that.
* The length of the returned collection is the
* minimum of the lengths of this sequence and that.
*/
Sequence extends $.Binary> zip(Iterable iterable);
/**
* Returns a sequence formed from this sequence and another iterable
* collection by combining corresponding elements in pairs.
* If one of the two collections is longer than the other,
* placeholder elements are used to extend the shorter collection
* to the length of the longer.
*
* @param iterable the part B to be zipped with this sequence
* @param the type of the iterable
* @param def1 the element to be used to fill up the result if
* this sequence is shorter than that iterable
* @param def2 the element to be used to fill up the result if
* the iterable is shorter than this sequence
* @return a new sequence containing pairs consisting of
* corresponding elements of this sequence and that.
* The length of the returned collection is the
* maximum of the lengths of this sequence and that.
*/
Sequence extends $.Binary> zipAll(Iterable iterable, T def1, T2 def2);
/**
* Zip this sequence with its indices
*
* @return A new list containing pairs consisting of all
* elements of this list paired with their index.
* Indices start at 0.
*/
@SuppressWarnings("unused")
Sequence extends $.Binary> zipWithIndex();
/**
* Count the element occurence in this sequence
* @param t the element
* @return the number of times the element be presented in this sequence
*/
int count(T t);
}
/**
* A bidirectional sequence which can be iterated from tail to head
*
* @param the element type
*/
public interface ReversibleSequence
extends Sequence {
/**
* Returns this traversable and make sure {@link C.Feature#PARALLEL} is set
*
* @return this reference with parallel turned on
*/
ReversibleSequence parallel();
/**
* Returns this traversable and make sure {@link C.Feature#PARALLEL} is unset
*
* @return this reference with parallel turned off
*/
ReversibleSequence sequential();
/**
* Returns this traversable and make sure {@link C.Feature#LAZY} is set
*
* @return this reference with lazy turned on
*/
ReversibleSequence lazy();
/**
* Returns this traversable and make sure {@link C.Feature#LAZY} is unset
*
* @return this reference with lazy turned off
*/
ReversibleSequence eager();
/**
* {@inheritDoc}
*
* @param n {@inheritDoc}
* @return an new reversible sequence contains the first
* {@code n} elements in this sequence
*/
@Override
ReversibleSequence head(int n);
/**
* {@inheritDoc}
*
* @return an new reversible sequence contains all elements
* in this sequence except the first element
*/
@Override
ReversibleSequence tail();
/**
* {@inheritDoc}
*
* @param n {@inheritDoc}
* @return an new reversible sequence contains the first
* {@code n} elements in this sequence
*/
@Override
ReversibleSequence take(int n);
/**
* {@inheritDoc}
*
* @param predicate {@inheritDoc}
* @return an new reversible sequence contains the elements
* in this sequence until predicate evaluate to false
*/
@Override
ReversibleSequence takeWhile($.Function super T, Boolean> predicate);
/**
* {@inheritDoc}
*
* @param n specify the number of elements to be taken from the head of this {@code Sequence} or
* the {@code -n} number of elements to be taken from the tail of this sequence if n is
* an negative number
* @return a reversible sequence without the first {@code n} number of elements
*/
@Override
ReversibleSequence drop(int n);
@Override
ReversibleSequence dropWhile($.Function super T, Boolean> predicate);
@Override
ReversibleSequence filter($.Function super T, Boolean> predicate);
/**
* {@inheritDoc}
*
* @param t {@inheritDoc}
* @return a reversible sequence contains this seq's element
* followed by {@code t}
*/
@Override
ReversibleSequence append(T t);
/**
* Returns an new reversible sequence contains all elements
* in this sequence followed by all elements in the specified
* reverse sequence
*
* @param seq another reversible sequence
* @return an new reversible sequence contains both seq's elements
*/
ReversibleSequence append(ReversibleSequence seq);
/**
* {@inheritDoc}
*
* @param t {@inheritDoc}
* @return a reversible sequence contains by {@code t}
* followed this seq's element
*/
@Override
ReversibleSequence prepend(T t);
/**
* Returns an new reversible sequence contains all elements
* in specified reversible sequence followed by all elements
* in this sequence
*
* @param seq another reversible sequence
* @return an new reversible sequence contains both seq's elements
*/
ReversibleSequence prepend(ReversibleSequence seq);
/**
* Returns the last element from this {@code Sequence}
*
* @return the last element
* @throws UnsupportedOperationException if this {@code Sequence} is not limited
* @throws NoSuchElementException if the {@code Sequence} is empty
* @see #isEmpty()
* @see org.osgl.util.C.Feature#LIMITED
* @see #is(org.osgl.util.C.Feature)
* @since 0.2
*/
T last() throws UnsupportedOperationException, NoSuchElementException;
/**
* Returns a {@code Sequence} consisting the last {@code n} elements from this {@code Sequence}
* if number {@code n} is positive and the {@code Sequence} contains more than {@code n} elements
* If this {@code Sequence} contains less than {@code n} elements, then a {@code Sequence} consisting
* the whole elements of this {@code Sequence} is returned. Note it might return this {@code Sequence}
* itself if the {@code Sequence} is immutable.
* If the number {@code n} is zero, then an empty {@code Sequence} is returned in reverse
* order
* If the number {@code n} is negative, then the first {@code -n} elements from this
* {@code Sequence} is returned in an new {@code Sequence}
*
* Sequence seq = C1.list(1, 2, 3, 4);
* assertEquals(C1.list(3, 4), seq.tail(2));
* assertEquals(C1.list(1, 2, 3, 4), seq.tail(100));
* assertEquals(C1.list(), seq.tail(0));
* assertEquals(C1.list(1, 2, 3), seq.tail(-3));
* assertEquals(C1.list(1, 2, 3, 4), seq.tail(-200));
*
* This method does not mutate the underline container
*
* @param n specify the number of elements to be taken from the tail of this {@code Sequence}
* @return a {@code Sequence} consisting of the last {@code n} elements from this {@code Sequence}
* @throws UnsupportedOperationException if the traversal is unlimited or empty
* @throws IndexOutOfBoundsException if {@code n} is greater than the size of this {@code Sequence}
* @see org.osgl.util.C.Feature#LIMITED
* @see #is(org.osgl.util.C.Feature)
* @since 0.2
*/
ReversibleSequence tail(int n) throws UnsupportedOperationException, IndexOutOfBoundsException;
/**
* Returns an new {@code Sequence} that reverse this {@code Sequence}.
*
* @return a reversed {@code Sequence}
* @throws UnsupportedOperationException if this {@code Sequence} is unlimited
* @see org.osgl.util.C.Feature#LIMITED
* @see #is(org.osgl.util.C.Feature)
* @since 0.2
*/
ReversibleSequence reverse() throws UnsupportedOperationException;
/**
* Returns an {@link Iterator} iterate the sequence from tail to head
*
* @return the iterator
* @since 0.2
*/
Iterator reverseIterator();
/**
* Run reduction from tail side. This is equivalent to:
*
* R result = identity;
* for (T element: this sequence.reverse()) {
* result = accumulator.apply(result, element);
* }
* return result;
*
*
* @param identity the initial value
* @param accumulator the function performs accumulation from {@code T} an {@code R} to anthoer {@code R}
* @param the accumulation result
* @return the aggregation result
* @see #reduce(Object, Func2)
* @since 0.2
*/
R reduceRight(R identity, Func2 accumulator);
/**
* Run reduction from tail to head. This is equivalent to
*
* if (isEmpty()) {
* return _.none();
* }
* T result = last();
* for (T element: this sequence.reverse.tail()) {
* result = accumulator.apply(result, element);
* }
* return _.some(result);
*
*
* @param accumulator the function accumulate each element to the final result
* @return an {@link Lang.Option} describing the accumulating result
* @since 0.2
*/
$.Option reduceRight(Func2 accumulator);
/**
* Apply the predicate specified to the element of this sequence
* from tail to head. Stop at the element that returns {@code true},
* and returns an {@link Lang.Option} describing the element. If none
* of the element applications in the sequence returns {@code true}
* then {@link Lang#none()} is returned
*
* @param predicate the function map the element to Boolean
* @return an option describe the first element matches the
* predicate or {@link Lang#none()}
* @since 0.2
*/
$.Option findLast($.Function super T, Boolean> predicate);
@Override
ReversibleSequence map($.Function super T, ? extends R> mapper);
/**
* {@inheritDoc}
*
* @param mapper {@inheritDoc}
* @param {@inheritDoc}
* @return a ReversibleSequence of {@code R} type element that are mapped from this sequences
* @since 0.2
*/
@Override
ReversibleSequence flatMap($.Function super T, ? extends Iterable extends R>> mapper);
ReversibleSequence accept($.Visitor super T> visitor);
ReversibleSequence each($.Visitor super T> visitor);
ReversibleSequence forEach($.Visitor super T> visitor);
ReversibleSequence acceptLeft($.Visitor super T> visitor);
/**
* Iterate through this sequence from tail to head with the visitor function
* specified
*
* @param visitor the function to visit elements in this sequence
* @return this sequence
* @see Traversable#accept(Lang.Visitor)
* @see Sequence#acceptLeft(Lang.Visitor)
* @since 0.2
*/
ReversibleSequence acceptRight($.Visitor super T> visitor);
C.ReversibleSequence<$.Binary> zip(C.ReversibleSequence rseq);
@SuppressWarnings("unused")
C.ReversibleSequence<$.Binary> zipAll(C.ReversibleSequence rseq, T def1, T2 def2);
}
public static class Array extends ReversibleSeqBase implements ReversibleSequence {
@Override
public Array lazy() {
super.lazy();
return this;
}
@Override
public Array eager() {
super.eager();
return this;
}
@Override
public Array parallel() {
super.parallel();
return this;
}
@Override
public Array sequential() {
super.sequential();
return this;
}
T[] data;
Array(T[] data) {
E.NPE(data);
this.data = data;
}
@Override
public int size() throws UnsupportedOperationException {
return data.length;
}
public boolean isEmpty() {
return 0 == size();
}
public boolean isNotEmpty() {
return 0 < size();
}
public T get(int idx) {
return data[idx];
}
public Array set(int idx, T val) {
data[idx] = val;
return this;
}
@Override
public Iterator iterator() {
final int size = size();
return new ReadOnlyIterator() {
int cursor = 0;
@Override
public boolean hasNext() {
return cursor < size;
}
@Override
public T next() {
if (cursor >= size) {
throw new NoSuchElementException();
}
return data[cursor++];
}
};
}
@Override
public Iterator reverseIterator() {
final int size = size();
return new ReadOnlyIterator() {
int cursor = size - 1;
@Override
public boolean hasNext() {
return cursor < 0;
}
@Override
public T next() {
if (cursor < 0) {
throw new NoSuchElementException();
}
return data[cursor--];
}
};
}
@Override
@SuppressWarnings("unchecked")
public ReversibleSequence reverse() throws UnsupportedOperationException {
if (isLazy()) {
return ReversedRSeq.of(this);
}
if (isMutable()) {
Algorithms.arrayReverseInplace().reverse(data, 0, data.length);
return this;
}
T[] newData = (T[]) Algorithms.ARRAY_REVERSE.apply(data, 0, data.length);
return of(newData);
}
@Override
public C.List asList() {
return C.listOf(data);
}
public C.List asNewList() {
return C.newListOf(data);
}
public static Array of(T[] data) {
return new Array<>(data);
}
public static Array copyOf(T[] data) {
int len = data.length;
T[] newData = $.newArray(data, len);
System.arraycopy(data, 0, newData, 0, len);
return new Array<>(newData);
}
}
/**
* Define a Range data structure which contains a discrete sequence of elements start from {@link #from()}
* until {@link #to()}. The {@code from} element should be contained in the range, while the {@code to}
* element should be exclusive from the range. While the {@code from} and {@code to} defines the boundary of
* an range, the {@link #step()} defines how to step from one element to another in the range.
*
* @param the element type
*/
public interface Range extends Sequence {
/**
* Returns the {@code from} value (inclusive) in the range
*
* @return {@code from}
* @since 0.2
*/
ELEMENT from();
/**
* Returns the {@code to} value (exclusive) of the range
*
* @return {@code to}
* @since 0.2
*/
ELEMENT to();
/**
* Check if an element is contained in this range
*
* @param element the element to be checked
* @return {@code true} if the element specified is contained in the range
* @since 0.2
*/
boolean contains(ELEMENT element);
/**
* Check if this range contains all elements of another range of the same type (identified by
* {@link #order()} and {@link #step()}).
*
* @param r2 the range to be tested
* @return {@code true} if this range contains all elements of {@code r2}
* @since 0.2
*/
boolean containsAll(Range r2);
/**
* Returns a {@link Func2} function that takes two elements in the range domain and returns an integer to
* determine the order of the two elements. See {@link java.util.Comparator#compare(Object, Object)} for
* semantic of the function.
* If any one of the element applied is {@code null} the function should throw out
* {@link NullPointerException}
*
* @return a function implement the ordering logic
* @since 0.2
*/
Comparator order();
/**
* Returns a {@link Func2} function that applied to an element in this {@code Range} and
* an integer {@code n} indicate the number of steps. The result of the function is an element in
* the range or the range domain after moving {@code n} steps based on the element.
* If the element apply is {@code null}, the function should throw out
* {@link NullPointerException}; if the resulting element is not defined in the range
* domain, the function should throw out {@link NoSuchElementException}
*
* @return a function implement the stepping logic
* @since 0.2
*/
Func2 step();
/**
* Returns an new range this range and another range {@code r2} merged together. The two ranges must have
* the equal {@link #step()} and {@link #order()} operator to be merged, otherwise,
* {@link org.osgl.exception.InvalidArgException} will be thrown out
* The two ranges must be either overlapped or immediately connected to each other as per
* {@link #step()} definition. Otherwise an {@link org.osgl.exception.InvalidArgException}
* will be throw out:
*
* - if one range contains another range entirely, then the larger range is returned
* - if the two ranges overlapped or immediately connected to each other, then an range
* contains all elements of the two ranges will be returned
* - an {@link org.osgl.exception.InvalidArgException} will be thrown out if the two ranges does not connected
* to each other
*
*
* @param r2 the range to be merged with this range
* @return an new range contains all elements in this range and r2
* @throws org.osgl.exception.InvalidArgException if the two ranges does not have
* the same {@link #step()} operator or does not connect to each other
* @since 0.2
*/
Range merge(Range r2);
ELEMENT last();
Range tail(int n);
Range reverse();
Iterator reverseIterator();
@SuppressWarnings("unused")
R reduceRight(R identity, Func2 accumulator);
@SuppressWarnings("unused")
$.Option reduceRight(Func2 accumulator);
@SuppressWarnings("unused")
$.Option findLast($.Function super ELEMENT, Boolean> predicate);
/**
* {@inheritDoc}
*
* @param visitor {@inheritDoc}
* @return this Range instance
* @since 0.2
*/
@Override
Range accept($.Visitor super ELEMENT> visitor);
@Override
Range each($.Visitor super ELEMENT> visitor);
@Override
Range forEach($.Visitor super ELEMENT> visitor);
/**
* {@inheritDoc}
*
* @param visitor {@inheritDoc}
* @return this Range instance
* @since 0.2
*/
@Override
Range acceptLeft($.Visitor super ELEMENT> visitor);
/**
* iterate through the range from tail to head
*
* @param visitor a function to visit elements in the range
* @return this Range instance
* @since 0.2
*/
@SuppressWarnings("unused")
Range acceptRight($.Visitor super ELEMENT> visitor);
}
/**
* The osgl List interface is a mixture of {@link java.util.List} and osgl {@link Sequence}
*
* @param the element type of the {@code List}
* @since 0.2
*/
public interface List extends java.util.List, ReversibleSequence {
/**
* A cursor points to an element of a {@link List}. It performs like
* {@link java.util.ListIterator} but differs in the following way:
*
* - Add insert, append method
* - Support method chain calling style for most methods
* - A clear get() method to get the element the cursor point to
* - Unlike next/previous method, the new forward/backward method
* returns a Cursor reference
*
*
* @param
*/
interface Cursor {
/**
* Returns true if the cursor is not obsolete and points to an element
* in the list
*
* @return true if this cursor is not obsolete and point to an element
*/
boolean isDefined();
/**
* Returns the index of the element to which the cursor pointed
*
* @return the cursor index
*/
int index();
/**
* Returns if the cursor can be moved forward to get the
* next element
*
* @return {@code true} if there are element after the cursor in the
* underline list
*/
boolean hasNext();
/**
* Returns if the cursor can be moved backward to get the previous
* element
*
* @return {@code true} if there are element before the cursor in the
* underline list
*/
boolean hasPrevious();
/**
* Move the cursor forward to make it point to the next element to
* the current element
*
* @return the cursor points to the next element
* @throws UnsupportedOperationException if cannot move forward anymore
*/
Cursor forward() throws UnsupportedOperationException;
/**
* Move the cursor backward to make it point to the previous element to
* the current element
*
* @return the cursor points to the previous element
* @throws UnsupportedOperationException if cannot move backward anymore
*/
Cursor backward() throws UnsupportedOperationException;
/**
* Park the cursor at the position before the first element.
* After calling this method, {@link #isDefined()}
* shall return {@code false}
*
* @return this cursor
*/
Cursor parkLeft();
/**
* Park the cursor at the position after the last element
* After calling this method, {@link #isDefined()}
* shall return {@code false}
*
* @return this cursor
*/
Cursor parkRight();
/**
* Returns the element this cursor points to. If the cursor isn't point
* to any element, calling to this method will trigger
* {@code NoSuchElementException} been thrown out. The only case
* the cursor doesn't point to any element is when it is initialized
* in which case the cursor index is -1
*
* @return the current element
* @throws NoSuchElementException if the cursor isn't point to any element
*/
T get() throws NoSuchElementException;
/**
* Replace the element this cursor points to with the new element specified.
*
* @param t the new element to be set to this cursor
* @return the cursor itself
* @throws IndexOutOfBoundsException if the cursor isn't point to any element
* @throws NullPointerException if when passing null value to this method and
* the underline list does not allow null value
*/
Cursor set(T t) throws IndexOutOfBoundsException, NullPointerException;
/**
* Remove the current element this cursor points to. After the element
* is removed, the cursor points to the next element if there is next,
* or if there isn't next element, the cursor points to the previous
* element, or if there is previous element neither, then the cursor
* points to {@code -1} position and the current element is not defined
*
* @return the cursor itself
* @throws UnsupportedOperationException if the operation is not supported
* by the underline container does not support removing elements
* @throws NoSuchElementException if the cursor is parked either left or
* right
*/
Cursor drop() throws NoSuchElementException, UnsupportedOperationException;
/**
* Add an element in front of the element this cursor points to.
* After added, the cursor should still point to the current element
*
* @param t the element to be inserted
* @return this cursor which is still pointing to the current element
* @throws IndexOutOfBoundsException if the current element is undefined
*/
Cursor prepend(T t) throws IndexOutOfBoundsException;
/**
* Add an element after the element this cursor points to.
* After added, the cursor should still point to the current element
*
* @param t the element to be added
* @return this cursor which is still pointing to the current element
*/
Cursor append(T t);
}
/**
* Returns this traversable and make sure {@link C.Feature#PARALLEL} is set
*
* @return this reference with parallel turned on
*/
@Override
List parallel();
/**
* Returns this traversable and make sure {@link C.Feature#PARALLEL} is unset
*
* @return this reference with parallel turned off
*/
@Override
List sequential();
/**
* Returns this traversable and make sure {@link C.Feature#LAZY} is set
*
* @return this reference with lazy turned on
*/
@Override
List lazy();
/**
* Returns this traversable and make sure {@link C.Feature#LAZY} is unset
*
* @return this reference with lazy turned off
*/
@Override
List eager();
/**
* Returns an immutable list contains all elements of the current list.
* If the current list is immutable, then return the current list itself.
*
* @return an immutable list.
* @see #readOnly()
*/
List snapshot();
/**
* Returns a view of this list that is readonly. If the current list is
* readonly or immutable then return the current list itself
*
* @return a readonly view of this list
*/
@SuppressWarnings("unused")
List readOnly();
/**
* Returns a mutable copy of this list
*
* @return a mutable list contains all elements of this list
*/
List copy();
/**
* Returns a sorted copy of this list.
* Note if the element type T is not a {@link java.lang.Comparable} then
* this method returns a {@link #copy() copy} of this list without any order
* changes
*
* @return a sorted copy of this list
*/
List sorted();
/**
* Return a list that contains unique set of this list and keep the orders. If
* this list doesn't have duplicated items, it could return this list directly
* or choose to return an new copy of this list depends on the sub class
* implementation
* @return a list contains only unique elements in this list
*/
List unique();
/**
* Return a list that contains unique set as per the comparator specified of
* this list and keep the orders. If this list doesn't have duplicated items,
* it could return this list directly or choose to return an new copy of this list
* depends on the sub class implementation
* @param comp the comparator check the duplicate elements
* @return a list contains unique element as per the comparator
*/
List unique(Comparator comp);
/**
* Returns a sorted copy of this list. The order is specified by the comparator
* provided
*
* @param comparator specify the order of elements in the result list
* @return an ordered copy of this list
*/
List sorted(Comparator super T> comparator);
@Override
List subList(int fromIndex, int toIndex);
/**
* Add all elements from an {@link Iterable} into this list.
* Return {@code true} if the list has changed as a result of
* call.
* Note if this list is immutable or readonly, {@code UnsupportedOperationException}
* will be thrown out with this call
* @param iterable the iterable provides the elements to be
* added into the list
* @return {@code true} if this list changed as result of addd
*/
boolean addAll(Iterable extends T> iterable);
/**
* {@inheritDoc}
*
* @param n specify the number of elements to be included in the return list
* @return A List contains first {@code n} items in this List
*/
@Override
List head(int n);
/**
* {@inheritDoc}
* This method does not alter the underline list
*
* @param n {@inheritDoc}
* @return A list contains first {@code n} items in this list
*/
@Override
List take(int n);
/**
* {@inheritDoc}
*
* @return A list contains all elements in this list except
* the first one
*/
@Override
List tail();
/**
* {@inheritDoc}
* This method does not alter the underline list
*
* @param n {@inheritDoc}
* @return A list contains last {@code n} items in this list
*/
@Override
List tail(int n);
/**
* {@inheritDoc}
* This method does not alter the underline list
*
* @param n {@inheritDoc}
* @return a List contains all elements of this list
* except the first {@code n} number
*/
List drop(int n);
/**
* {@inheritDoc}
* This method does not alter the underline list
*
* @param predicate the predicate function
* @return {@inheritDoc}
*/
@Override
List dropWhile($.Function super T, Boolean> predicate);
/**
* {@inheritDoc}
* This method does not alter the underline list
*
* @param predicate {@inheritDoc}
* @return {@inheritDoc}
*/
@Override
List takeWhile($.Function super T, Boolean> predicate);
/**
* For mutable list, remove all element that matches the predicate
* specified from this List and return this list once done.
* For immutable or readonly list, an new List contains all element from
* this list that does not match the predicate specified is returned
*
* @param predicate test whether an element should be removed frmo
* return list
* @return a list contains all element that does not match the
* predicate specified
*/
List remove($.Function super T, Boolean> predicate);
@Override
C.List map($.Function super T, ? extends R> mapper);
/**
* {@inheritDoc}
*
* @param mapper {@inheritDoc}
* @param {@inheritDoc}
* @return a List of {@code R} type element that are mapped from this sequences
* @since 0.2
*/
@Override
List flatMap($.Function super T, ? extends Iterable extends R>> mapper);
@Override
List collect(String path);
@Override
List filter($.Function super T, Boolean> predicate);
/**
* Split this list into two list based on the predicate specified.
*
* The function use the predicate to test all elements in this list. If test passed
* then it add the element into {@link Lang.T2#_1 left side list}, otherwise the
* element will be added into {@link Lang.T2#_2 right side list}. The result
* is returned as a {@link org.osgl.Lang.Tuple tuple} contains the left and
* right side lift
*
* @param predicate the function to test the elements in this list
* @return a tuple of two lists
*/
$.T2, List> split($.Function super T, Boolean> predicate);
/**
* Find the first element in this list that matches the predicate.
* Return a cursor point to the location of the element. If no
* such element is found then a cursor that point to {@code -1}
* is returned.
*
* @param predicate test the element
* @return the reference to the list itself or an new List without the
* first element matches the predicate if this is a readonly
* list
*/
Cursor locateFirst($.Function predicate);
/**
* Locate any one element in the list that matches the predicate.
* Returns the cursor point to the element found, or a cursor
* that is not defined if no such element found in the list. In
* a parallel locating the element been found might not be the
* first element matches the predicate
*
* @param predicate the function that used to check the element
* at the cursor
* @return the reference to the list itself or an new List without
* and element matches the predicate if this is a readonly
* list
*/
Cursor locate($.Function predicate);
/**
* Locate the first element in this list that matches the predicate.
* Return a cursor point to the location of the element. If no
* such element is found then a cursor that point to {@code -1}
* is returned.
*
* @param predicate test the element
* @return the reference to the list itself or an new List without the
* first element matches the predicate if this is a readonly
* list
*/
Cursor locateLast($.Function predicate);
/**
* Insert an element at the position specified by {@code index}.
* If this list is readonly or immutable, then an new
* list should be created with all elements in this list
* and the new element inserted at the specified position.
* The new list should have the same feature as this list
* If index is less than zero then it will insert at
* {@code (size() + index)}
*
* @param index specify the position where the element should be inserted
* @param t the element to be inserted
* @return a list as specified above
* @throws IndexOutOfBoundsException Math.abs(index) > size()
*/
List insert(int index, T t) throws IndexOutOfBoundsException;
/**
* Insert an array of elements at the position specified by {@code index}.
* If this list is readonly or immutable, then an new
* list should be created with all elements in this list
* and the new element inserted at the specified position.
* The new list should have the same feature as this list
* If index is less than zero then it will insert at
* {@code (size() + index)}
*
* @param index specify the position where the element should be inserted
* @param ta the array of elements to be inserted
* @return a list as specified above
* @throws IndexOutOfBoundsException Math.abs(index) > size()
*/
List insert(int index, T... ta) throws IndexOutOfBoundsException;
/**
* Insert a sub list at the position specified by {@code index}.
* If this list is readonly or immutable, then an new
* list should be created with all elements in this list
* and the elements of sub list inserted at the specified position.
* The new list should have the same feature as this list
* If index is less than zero then it will insert at
* {@code (size() + index)}
*
* @param index specify the position where the element should be inserted
* @param subList the sub list contains elements to be inserted
* @return a list as specified above
* @throws IndexOutOfBoundsException Math.abs(index) > size()
*/
List insert(int index, java.util.List subList) throws IndexOutOfBoundsException;
/**
* {@inheritDoc}
*
* @param t {@inheritDoc}
* @return a list contains elements in this list followed
* by {@code t}
*/
@Override
List append(T t);
/**
* {@inheritDoc}
*
* @param iterable the iterable from which elements will be appended to this list
* @return a List contains all elements of this list followed
* by all elements in the iterable
*/
List append(Collection extends T> iterable);
/**
* Returns a List contains all elements in this List followed by
* all elements in the specified List.
* A mutable List implementation might choose to add elements
* from the specified list directly to this list and return this
* list directly
* For a read only or immutable list, it must create an new list
* to avoid update this list
*
* @param list the list in which elements will be appended
* to this list
* @return a list contains elements of both list
*/
List append(List list);
@Override
List prepend(T t);
List prepend(Collection extends T> collection);
List prepend(List list);
@Override
List reverse();
/**
* Returns a List contains all elements in this List and not in
* the {@code col} collection specified
*
* @param col the collection in which elements should
* be excluded from the result List
* @return a List contains elements only in this list
*/
List without(Collection super T> col);
/**
* Returns a list contains all elements in the list except the
* one specified
*
* @param element the element that should not be in the resulting list
* @return a list without the element specified
*/
List without(T element);
/**
* Returns a list contains all elements in the list except the
* ones specified
*
* @param element the element that should not be in the resulting list
* @param elements the array contains elements that should not be in the resulting list
* @return a list without the element specified
*/
List without(T element, T... elements);
@Override
List accept($.Visitor super T> visitor);
@Override
List each($.Visitor super T> visitor);
@Override
List forEach($.Visitor super T> visitor);
@Override
List acceptLeft($.Visitor super T> visitor);
@Override
List acceptRight($.Visitor super T> visitor);
/**
* Loop through the list and for each element, call on the
* indexedVisitor function specified
* @param indexedVisitor the function to be called on each element along with the index
* @return this list
*/
List accept(IndexedVisitor indexedVisitor);
/**
* Alias of {@link #accept(Visitor)}
* @param indexedVisitor the function to be called on each element along with the index
* @return this list
*/
List each(IndexedVisitor indexedVisitor);
/**
* Alias of {@link #accept(Visitor)}
* @param indexedVisitor the function to be called on each element along with the index
* @return this list
*/
List forEach(IndexedVisitor indexedVisitor);
/**
* Loop through the list from {@code 0} to {@code size - 1}. Call the indexedVisitor function
* on each element along with the index
* @param indexedVisitor the function to be called on each element along with the index
* @return this list
*/
@SuppressWarnings("unused")
List acceptLeft(IndexedVisitor indexedVisitor);
/**
* Loop through the list from {@code size() - 1} to {@code 0}. Call the indexedVisitor function
* on each element along with the index
* @param indexedVisitor the function to be called on each element along with the index
* @return this list
*/
@SuppressWarnings("unused")
List