/* * Copyright (C) 2013 The Java Tool project * Gelin Luo <greenlaw110(at)gmail.com> * * 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; import org.osgl.$; import org.osgl.Osgl; import org.osgl.exception.NotAppliedException; import org.osgl.util.algo.Algorithms; import java.io.IOException; import java.io.Serializable; import java.util.*; /** * The namespace for OSGL collection utilities */ public enum C { INSTANCE; /** * 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<Feature> 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<Feature> predefined) { return new Featured() { @Override public EnumSet<Feature> 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 <T> The element type */ public interface Traversable<T> extends Iterable<T>, 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<T> parallel(); /** * Returns this traversable and turn off * {@link C.Feature#PARALLEL} * * @return this reference with parallel turned off */ Traversable<T> 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<T> lazy(); /** * Returns this traversable and turn off {@link C.Feature#LAZY} * * @return this reference with lazy turned off */ Traversable<T> 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. * <pre> * 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)); * </pre> * <p>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</p> * * @param mapper the function that applied to element in this traversal and returns element in the result traversal * @param <R> the element type of the new traversal * @return the new traversal contains results of the mapper function applied to this traversal * @since 0.2 */ <R> Traversable<R> 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 <R> the element type of the the new traversable * @return the new traversable * @since 0.2 */ <R> Traversable<R> flatMap($.Function<? super T, ? extends Iterable<? extends R>> mapper); /** * Returns an new traversable that contains all elements in the current traversable * except that does not pass the test of the filter function specified. * <pre> * Traversable traversable = C.list(-1, 0, 1, -3, 7); * Traversable filtered = traversable.filter(_.F.gt(0)); * assertTrue(filtered.contains(1)); * assertFalse(filtered.contains(-3)); * </pre> * * @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<T> 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: * <pre> * R result = identity; * for (T element: this traversable) { * result = accumulator.apply(result, element); * } * return result; * </pre> * <p>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</p> * * @param identity the identity value for the accumulating function * @param accumulator the function the combine two values * @param <R> the type of identity and the return value * @return the result of reduction * @since 0.2 */ <R> R reduce(R identity, $.Func2<R, T, R> accumulator); /** * Performs a reduction on the elements in this traversable, using provided accumulating * function. This might be equivalent to: * <pre> * 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(); * </pre> * <p>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</p> * * @param accumulator the function takes previous accumulating * result and the current element being * iterated * @return an option describing the accumulating result or {@link $#none()} if * the structure is empty * @since 0.2 */ $.Option<T> reduce($.Func2<T, T, T> 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: * <pre> * this.allMatch(_.F.negate(predicate)); * </pre> * * @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 $#NONE} if no element matches * @since 0.2 */ $.Option<T> 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<T> accept($.Function<? super T, ?> visitor); /** * Alias of {@link #accept(Osgl.Function)} * @param visitor the visitor to tranverse the elements * @return this {@code Traversable} instance */ Traversable<T> each($.Function<? super T, ?> visitor); /** * Alias of {@link #accept(Osgl.Function)} * @param visitor the visitor function * @return this {@code Traversable} instance */ Traversable<T> forEach($.Function<? super T, ?> visitor); } public interface Sequence<T> extends Traversable<T> { /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is set * * @return this reference with parallel turned on */ Sequence<T> parallel(); /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is unset * * @return this reference with parallel turned off */ Sequence<T> sequential(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is set * * @return this reference with lazy turned on */ Sequence<T> lazy(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is unset * * @return this reference with lazy turned off */ Sequence<T> eager(); /** * Alias of {@link #head()} * * @return the first element in the sequence * @since 0.2 */ T first() throws NoSuchElementException; /** * Returns an {@link $.Option} of the first element in the * {@code Sequence} or {@link $#NONE} if the {@code Sequence} is empty * * @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<T> 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<T> 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 * <p>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.</p> * <p>If the number {@code n} is zero, then an empty {@code Sequence} is returned in reverse * order</p> * <p>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</p> * <pre> * 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)); * </pre> * * @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<T> take(int n); /** * Returns an new {@code Sequence} that takes the head of this {@code Sequence} until the predicate * evaluate to {@code false}: * <pre> * 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))); * </pre> * * @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<T> 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 * <p>If this {@code Sequence} contains less than {@code n} elements, then an empty {@code Sequence} * is returned</p> * <p>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</p> * <p>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</p> * <pre> * 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)); * </pre> * <p>Note this method does NOT modify the current sequence, instead it returns an new sequence structure * containing the elements as required</p> * * @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<T> 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} * <pre> * 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))); * </pre> * <p>Note this method does NOT modify the current sequence, instead it returns an new sequence structure * containing the elements as required</p> * * @param predicate the function that check if drop operation should stop * @return the sequence after applying the drop operations * @since 0.2 */ Sequence<T> dropWhile($.Function<? super T, Boolean> predicate); /** * Returns a sequence consists of all elements of this sequence * followed by all elements of the specified iterable. * <p>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</p> * * @param iterable the iterable in which elements will be append to this sequence * @return the sequence after append the iterable */ Sequence<T> append(Iterable<? extends T> iterable); /** * Returns a sequence consists of all elements of this sequence * followed by all elements of the specified sequence. * <p>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</p> * * @param seq the sequence to be appended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence<T> append(Sequence<? extends T> seq); /** * Returns a sequence consists of all elements of this sequence * followed by all elements of the specified iterator. * <p>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</p> * * @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<T> append(Iterator<? extends T> iterator); /** * Returns a sequence consists of all elements of this sequence * followed by all elements of the specified enumeration. * <p>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</p> * * @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<T> append(Enumeration<? extends T> enumeration); /** * Returns a sequence consists of all elements of this sequence * followed by the element specified. * <p>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</p> * * @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<T> append(T t); /** * Returns a sequence consists of all elements of the iterable specified * followed by all elements of this sequence * <p>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</p> * * @param iterable the iterable to be prepended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence<T> prepend(Iterable<? extends T> iterable); /** * Returns a sequence consists of all elements of the iterator specified * followed by all elements of this sequence * <p>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</p> * * @param iterator the iterator to be prepended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence<T> prepend(Iterator<? extends T> iterator); /** * Returns a sequence consists of all elements of the enumeration specified * followed by all elements of this sequence * <p>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</p> * * @param enumeration the enumeration to be prepended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence<T> prepend(Enumeration<? extends T> enumeration); /** * Returns a sequence consists of all elements of the sequence specified * followed by all elements of this sequence * <p>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</p> * * @param seq the sequence to be prepended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence<T> prepend(Sequence<? extends T> seq); /** * Returns a sequence consists of the element specified followed by * all elements of this sequence. * <p>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</p> * * @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<T> prepend(T t); /** * {@inheritDoc} * * @param mapper {@inheritDoc} * @param <R> {@inheritDoc} * @return a Sequence of {@code R} that are mapped from this sequence * @since 0.2 */ @Override <R> Sequence<R> map($.Function<? super T, ? extends R> mapper); /** * {@inheritDoc} * * @param mapper {@inheritDoc} * @param <R> {@inheritDoc} * @return a Sequence of {@code R} type element that are mapped from this sequences * @since 0.2 */ @Override <R> Sequence<R> flatMap($.Function<? super T, ? extends Iterable<? extends R>> mapper); /** * {@inheritDoc} * * @param predicate {@inheritDoc} * @return An new {@code Sequence} consists of elements that passed the predicate * @since 0.2 */ @Override Sequence<T> 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, Osgl.Func2)} or * {@link ReversibleSequence#reduceRight(Object, Osgl.Func2)}, or * even run reduction in parallel, it all depending on the implementation. * <p>For a guaranteed reduce from left to right, use * {@link C.Sequence#reduceLeft(Object, Osgl.Func2)} instead</p> * * @param identity {@inheritDoc} * @param accumulator {@inheritDoc} * @param <R> {@inheritDoc} * @return {@inheritDoc} * @since 0.2 */ @Override <R> R reduce(R identity, $.Func2<R, T, R> accumulator); /** * Run reduction from header side. This is equivalent to: * <pre> * R result = identity; * for (T element: this sequence) { * result = accumulator.apply(result, element); * } * return result; * </pre> * * @param identity the identity value for the accumulating function * @param accumulator the function to accumulate two values * @param <R> the aggregation result type * @return the reduced result * @since 0.2 */ <R> R reduceLeft(R identity, $.Func2<R, T, R> accumulator); /** * {@inheritDoc} * This method does not specify the approach to run reduction. * For a guaranteed reduction from head to tail, use * {@link #reduceLeft(Osgl.Func2)} instead * * @param accumulator {@inheritDoc} * @return {@inheritDoc} * @since 0.2 */ @Override $.Option<T> reduce($.Func2<T, T, T> accumulator); /** * Run reduction from head to tail. This is equivalent to * <pre> * if (isEmpty()) { * return _.none(); * } * T result = head(); * for (T element: this traversable.tail()) { * result = accumulator.apply(result, element); * } * return _.some(result); * </pre> * * @param accumulator the function accumulate each element to the final result * @return an {@link $.Option} describing the accumulating result * @since 0.2 */ $.Option<T> reduceLeft($.Func2<T, T, T> 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 $.Option} describing the element. If none * of the element applications in the sequence returns {@code true} * then {@link $#none()} is returned * * @param predicate the function map the element to Boolean * @return an option describe the first element matches the * predicate or {@link $#none()} * @since 0.2 */ $.Option<T> findFirst($.Function<? super T, Boolean> predicate); Sequence<T> accept($.Function<? super T, ?> visitor); Sequence<T> each($.Function<? super T, ?> visitor); Sequence<T> forEach($.Function<? 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(Osgl.Function) * @see ReversibleSequence#acceptRight(Osgl.Function) * @since 0.2 */ Sequence<T> acceptLeft($.Function<? 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 <T2> 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. */ <T2> Sequence<$.T2<T, T2>> zip(Iterable<T2> 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 <T2> 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. */ <T2> Sequence<$.T2<T, T2>> zipAll(Iterable<T2> 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<$.T2<T, Integer>> 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 <T> the element type */ public interface ReversibleSequence<T> extends Sequence<T> { /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is set * * @return this reference with parallel turned on */ ReversibleSequence<T> parallel(); /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is unset * * @return this reference with parallel turned off */ ReversibleSequence<T> sequential(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is set * * @return this reference with lazy turned on */ ReversibleSequence<T> lazy(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is unset * * @return this reference with lazy turned off */ ReversibleSequence<T> eager(); /** * {@inheritDoc} * * @param n {@inheritDoc} * @return an new reversible sequence contains the first * {@code n} elements in this sequence */ @Override ReversibleSequence<T> head(int n); /** * {@inheritDoc} * * @return an new reversible sequence contains all elements * in this sequence except the first element */ @Override ReversibleSequence<T> tail(); /** * {@inheritDoc} * * @param n {@inheritDoc} * @return an new reversible sequence contains the first * {@code n} elements in this sequence */ @Override ReversibleSequence<T> 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<T> 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<T> drop(int n); @Override ReversibleSequence<T> dropWhile($.Function<? super T, Boolean> predicate); @Override ReversibleSequence<T> 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<T> 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<T> append(ReversibleSequence<T> seq); /** * {@inheritDoc} * * @param t {@inheritDoc} * @return a reversible sequence contains by {@code t} * followed this seq's element */ @Override ReversibleSequence<T> 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<T> prepend(ReversibleSequence<T> 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 * <p>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.</p> * <p>If the number {@code n} is zero, then an empty {@code Sequence} is returned in reverse * order</p> * <p>If the number {@code n} is negative, then the first {@code -n} elements from this * {@code Sequence} is returned in an new {@code Sequence}</p> * <pre> * 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)); * </pre> * <p>This method does not mutate the underline container</p> * * @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<T> 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<T> reverse() throws UnsupportedOperationException; /** * Returns an {@link Iterator} iterate the sequence from tail to head * * @return the iterator * @since 0.2 */ Iterator<T> reverseIterator(); /** * Run reduction from tail side. This is equivalent to: * <pre> * R result = identity; * for (T element: this sequence.reverse()) { * result = accumulator.apply(result, element); * } * return result; * </pre> * * @param identity the initial value * @param accumulator the function performs accumulation from {@code T} an {@code R} to anthoer {@code R} * @param <R> the accumulation result * @return the aggregation result * @see #reduce(Object, Osgl.Func2) * @since 0.2 */ <R> R reduceRight(R identity, $.Func2<R, T, R> accumulator); /** * Run reduction from tail to head. This is equivalent to * <pre> * if (isEmpty()) { * return _.none(); * } * T result = last(); * for (T element: this sequence.reverse.tail()) { * result = accumulator.apply(result, element); * } * return _.some(result); * </pre> * * @param accumulator the function accumulate each element to the final result * @return an {@link $.Option} describing the accumulating result * @since 0.2 */ $.Option<T> reduceRight($.Func2<T, T, T> 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 $.Option} describing the element. If none * of the element applications in the sequence returns {@code true} * then {@link $#none()} is returned * * @param predicate the function map the element to Boolean * @return an option describe the first element matches the * predicate or {@link $#none()} * @since 0.2 */ $.Option<T> findLast($.Function<? super T, Boolean> predicate); @Override <R> ReversibleSequence<R> map($.Function<? super T, ? extends R> mapper); /** * {@inheritDoc} * * @param mapper {@inheritDoc} * @param <R> {@inheritDoc} * @return a ReversibleSequence of {@code R} type element that are mapped from this sequences * @since 0.2 */ @Override <R> ReversibleSequence<R> flatMap($.Function<? super T, ? extends Iterable<? extends R>> mapper); ReversibleSequence<T> accept($.Function<? super T, ?> visitor); ReversibleSequence<T> each($.Function<? super T, ?> visitor); ReversibleSequence<T> forEach($.Function<? super T, ?> visitor); ReversibleSequence<T> acceptLeft($.Function<? 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(Osgl.Function) * @see Sequence#acceptLeft(Osgl.Function) * @since 0.2 */ ReversibleSequence<T> acceptRight($.Function<? super T, ?> visitor); <T2> C.ReversibleSequence<$.T2<T, T2>> zip(C.ReversibleSequence<T2> rseq); @SuppressWarnings("unused") <T2> C.ReversibleSequence<$.T2<T, T2>> zipAll(C.ReversibleSequence<T2> rseq, T def1, T2 def2); } public static class Array<T> extends ReversibleSeqBase<T> implements ReversibleSequence<T> { @Override public Array<T> lazy() { super.lazy(); return this; } @Override public Array<T> eager() { super.eager(); return this; } @Override public Array<T> parallel() { super.parallel(); return this; } @Override public Array<T> 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; } @Override public Iterator<T> iterator() { final int size = size(); return new ReadOnlyIterator<T>() { 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<T> reverseIterator() { final int size = size(); return new ReadOnlyIterator<T>() { 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<T> 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); } public static <T> Array<T> of(T[] data) { return new Array<T>(data); } public static <T> Array<T> copyOf(T[] data) { int len = data.length; T[] newData = $.newArray(data, len); System.arraycopy(data, 0, newData, 0, len); return new Array<T>(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 <ELEMENT> the element type */ public interface Range<ELEMENT> extends Sequence<ELEMENT> { /** * 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<ELEMENT> 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. * <p>If any one of the element applied is {@code null} the function should throw out * {@link NullPointerException}</p> * * @return a function implement the ordering logic * @since 0.2 */ Comparator<ELEMENT> 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. * <p>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}</p> * * @return a function implement the stepping logic * @since 0.2 */ $.Func2<ELEMENT, Integer, ELEMENT> 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 * <p>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: * <ul> * <li>if one range contains another range entirely, then the larger range is returned</li> * <li>if the two ranges overlapped or immediately connected to each other, then an range * contains all elements of the two ranges will be returned</li> * <li>an {@link org.osgl.exception.InvalidArgException} will be thrown out if the two ranges does not connected * to each other</li> * </ul> * * @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<ELEMENT> merge(Range<ELEMENT> r2); ELEMENT last(); Range<ELEMENT> tail(int n); Range<ELEMENT> reverse(); Iterator<ELEMENT> reverseIterator(); @SuppressWarnings("unused") <R> R reduceRight(R identity, $.Func2<R, ELEMENT, R> accumulator); @SuppressWarnings("unused") $.Option<ELEMENT> reduceRight($.Func2<ELEMENT, ELEMENT, ELEMENT> accumulator); @SuppressWarnings("unused") $.Option<ELEMENT> findLast($.Function<? super ELEMENT, Boolean> predicate); /** * {@inheritDoc} * * @param visitor {@inheritDoc} * @return this Range instance * @since 0.2 */ @Override Range<ELEMENT> accept($.Function<? super ELEMENT, ?> visitor); @Override Range<ELEMENT> each($.Function<? super ELEMENT, ?> visitor); @Override Range<ELEMENT> forEach($.Function<? super ELEMENT, ?> visitor); /** * {@inheritDoc} * * @param visitor {@inheritDoc} * @return this Range instance * @since 0.2 */ @Override Range<ELEMENT> acceptLeft($.Function<? 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<ELEMENT> acceptRight($.Function<? super ELEMENT, ?> visitor); } /** * The osgl List interface is a mixture of {@link java.util.List} and osgl {@link Sequence} * * @param <T> the element type of the {@code List} * @since 0.2 */ public interface List<T> extends java.util.List<T>, ReversibleSequence<T> { /** * A cursor points to an element of a {@link List}. It performs like * {@link java.util.ListIterator} but differs in the following way: * <ul> * <li>Add insert, append method</li> * <li>Support method chain calling style for most methods</li> * <li>A clear get() method to get the element the cursor point to</li> * <li>Unlike next/previous method, the new forward/backward method * returns a Cursor reference</li> * </ul> * * @param <T> */ interface Cursor<T> { /** * 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<T> 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<T> backward() throws UnsupportedOperationException; /** * Park the cursor at the position before the first element. * <p>After calling this method, {@link #isDefined()} * shall return {@code false}</p> * * @return this cursor */ Cursor<T> parkLeft(); /** * Park the cursor at the position after the last element * <p>After calling this method, {@link #isDefined()} * shall return {@code false}</p> * * @return this cursor */ Cursor<T> 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<T> 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<T> 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<T> 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<T> append(T t); } /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is set * * @return this reference with parallel turned on */ @Override List<T> parallel(); /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is unset * * @return this reference with parallel turned off */ @Override List<T> sequential(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is set * * @return this reference with lazy turned on */ @Override List<T> lazy(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is unset * * @return this reference with lazy turned off */ @Override List<T> 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<T> 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<T> readOnly(); /** * Returns a mutable copy of this list * * @return a mutable list contains all elements of this list */ List<T> copy(); /** * Returns a sorted copy of this list. * <p>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</p> * * @return a sorted copy of this list */ List<T> 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<T> 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<T> unique(Comparator<T> 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<T> sorted(Comparator<? super T> comparator); @Override List<T> 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. * <p><b>Note</b> if this list is immutable or readonly, {@code UnsupportedOperationException} * will be thrown out with this call</p> * @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<T> head(int n); /** * {@inheritDoc} * <p>This method does not alter the underline list</p> * * @param n {@inheritDoc} * @return A list contains first {@code n} items in this list */ @Override List<T> take(int n); /** * {@inheritDoc} * * @return A list contains all elements in this list except * the first one */ @Override List<T> tail(); /** * {@inheritDoc} * <p>This method does not alter the underline list</p> * * @param n {@inheritDoc} * @return A list contains last {@code n} items in this list */ @Override List<T> tail(int n); /** * {@inheritDoc} * <p>This method does not alter the underline list</p> * * @param n {@inheritDoc} * @return a List contains all elements of this list * except the first {@code n} number */ List<T> drop(int n); /** * {@inheritDoc} * <p>This method does not alter the underline list</p> * * @param predicate the predicate function * @return {@inheritDoc} */ @Override List<T> dropWhile($.Function<? super T, Boolean> predicate); /** * {@inheritDoc} * <p>This method does not alter the underline list</p> * * @param predicate {@inheritDoc} * @return {@inheritDoc} */ @Override List<T> 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. * <p>For immutable or readonly list, an new List contains all element from * this list that does not match the predicate specified is returned</p> * * @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<T> remove($.Function<? super T, Boolean> predicate); @Override <R> C.List<R> map($.Function<? super T, ? extends R> mapper); /** * {@inheritDoc} * * @param mapper {@inheritDoc} * @param <R> {@inheritDoc} * @return a List of {@code R} type element that are mapped from this sequences * @since 0.2 */ @Override <R> List<R> flatMap($.Function<? super T, ? extends Iterable<? extends R>> mapper); @Override List<T> filter($.Function<? super T, Boolean> predicate); /** * Split this list into two list based on the predicate specified. * <p> * The function use the predicate to test all elements in this list. If test passed * then it add the element into {@link $.T2#_1 left side list}, otherwise the * element will be added into {@link $.T2#_2 right side list}. The result * is returned as a {@link org.osgl.Osgl.Tuple tuple} contains the left and * right side lift * </p> * @param predicate the function to test the elements in this list * @return a tuple of two lists */ $.T2<List<T>, List<T>> 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<T> locateFirst($.Function<T, Boolean> 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<T> locate($.Function<T, Boolean> 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<T> locateLast($.Function<T, Boolean> predicate); /** * Insert an element at the position specified by {@code index}. * <p>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</p> * <p>If index is less than zero then it will insert at * {@code (size() + index)}</p> * * @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<T> insert(int index, T t) throws IndexOutOfBoundsException; /** * Insert an array of elements at the position specified by {@code index}. * <p>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</p> * <p>If index is less than zero then it will insert at * {@code (size() + index)}</p> * * @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<T> insert(int index, T... ta) throws IndexOutOfBoundsException; /** * Insert a sub list at the position specified by {@code index}. * <p>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</p> * <p>If index is less than zero then it will insert at * {@code (size() + index)}</p> * * @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<T> insert(int index, java.util.List<T> subList) throws IndexOutOfBoundsException; /** * {@inheritDoc} * * @param t {@inheritDoc} * @return a list contains elements in this list followed * by {@code t} */ @Override List<T> 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<T> append(Collection<? extends T> iterable); /** * Returns a List contains all elements in this List followed by * all elements in the specified List. * <p>A mutable List implementation might choose to add elements * from the specified list directly to this list and return this * list directly</p> * <p>For a read only or immutable list, it must create an new list * to avoid update this list</p> * * @param list the list in which elements will be appended * to this list * @return a list contains elements of both list */ List<T> append(List<T> list); @Override List<T> prepend(T t); List<T> prepend(Collection<? extends T> collection); List<T> prepend(List<T> list); @Override List<T> 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<T> 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<T> 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<T> without(T element, T... elements); @Override List<T> accept($.Function<? super T, ?> visitor); @Override List<T> each($.Function<? super T, ?> visitor); @Override List<T> forEach($.Function<? super T, ?> visitor); @Override List<T> acceptLeft($.Function<? super T, ?> visitor); @Override List<T> acceptRight($.Function<? 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<T> accept($.Func2<Integer, ? super T, ?> indexedVisitor); /** * Alias of {@link #accept(Osgl.Func2)} * @param indexedVisitor the function to be called on each element along with the index * @return this list */ List<T> each($.Func2<Integer, ? super T, ?> indexedVisitor); /** * Alias of {@link #accept(Osgl.Func2)} * @param indexedVisitor the function to be called on each element along with the index * @return this list */ List<T> forEach($.Func2<Integer, ? super T, ?> 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<T> acceptLeft($.Func2<Integer, ? super T, ?> 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<T> acceptRight($.Func2<Integer, ? super T, ?> indexedVisitor); /** * Returns a list formed from this list 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 list the part B to be zipped with this list * @param <T2> the type of the iterable * @return an new list 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. */ <T2> List<$.T2<T, T2>> zip(java.util.List<T2> list); /** * Returns a list formed from this list 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 list the part B to be zipped with this list * @param <T2> 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 list containing pairs consisting of * corresponding elements of this list and that. * The length of the returned collection is the * maximum of the lengths of this list and that. */ <T2> List<$.T2<T, T2>> zipAll(java.util.List<T2> list, 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. */ Sequence<$.T2<T, Integer>> zipWithIndex(); } // /** // * The osgl Set interface is a mixture of {@link java.util.Set} and osgl {@link Traversable} // * // * @param <T> the element type of the {@code Set} // * @since 0.2 // */ // public static interface Set<T> extends java.util.Set<T>, Traversable<T> { // } // // /** // * The osgl sorted Set interface is a mixture of {@link java.util.Set} and osgl {@link Sequence} // * // * @param <T> the element type of the {@code SortedSet} // * @since 0.2 // */ // public static interface SortedSet<T> extends java.util.SortedSet<T>, ReversibleSequence<T> { // } // public static class Map<K, V> implements java.util.Map<K, V>, Serializable { public static class Entry<K, V> extends $.T2<K, V> implements java.util.Map.Entry<K, V> { public Entry(K _1, V _2) { super(_1, _2); //To change body of overridden methods use File | Settings | File Templates. } @Override public K getKey() { return _1; } @Override public V getValue() { return _2; } @Override public V setValue(V value) { throw E.unsupport(); } public static <K, V> Entry<K, V> valueOf(K k, V v) { return new Entry<K, V>(k, v); } } private java.util.Map<K, V> _m; private boolean ro; @SuppressWarnings("unchecked") protected Map(boolean readOnly, Object... args) { HashMap<K, V> map = new HashMap<K, V>(); int len = args.length; for (int i = 0; i < len; i += 2) { K k = (K) args[i]; V v = null; if (i + 1 < len) { v = (V) args[i + 1]; } map.put(k, v); } ro = readOnly; if (readOnly) { _m = Collections.unmodifiableMap(map); } else { _m = map; } } protected Map(boolean readOnly, java.util.Map<? extends K, ? extends V> map) { E.NPE(map); boolean sorted = map instanceof SortedMap; java.util.Map<K, V> m = sorted ? new TreeMap<K, V>() : new HashMap<K, V>(); for (K k : map.keySet()) { V v = map.get(k); m.put(k, v); } ro = readOnly; if (readOnly) { _m = Collections.unmodifiableMap(m); } else { _m = m; } } @Override public int size() { return _m.size(); } @Override public boolean isEmpty() { return _m.isEmpty(); } @Override public boolean containsKey(Object key) { return _m.containsKey(key); } @Override public boolean containsValue(Object value) { return _m.containsValue(value); } @Override public V get(Object key) { return _m.get(key); } @Override public V put(K key, V value) { return _m.put(key, value); } @Override public V remove(Object key) { return _m.remove(key); } @Override public void putAll(java.util.Map<? extends K, ? extends V> m) { _m.putAll(m); } @Override public void clear() { _m.clear(); } @Override public java.util.Set<K> keySet() { return _m.keySet(); } @Override public Collection<V> values() { return _m.values(); } @Override public Set<java.util.Map.Entry<K, V>> entrySet() { Set<java.util.Map.Entry<K, V>> set = C.newSet(); for (K k : _m.keySet()) { V v = _m.get(k); set.add(Entry.valueOf(k, v)); } return set; } @Override public int hashCode() { return _m.hashCode(); } @Override public String toString() { StringBuilder sb = S.builder(_m.toString()); if (ro) { sb.append("[ro]"); } return sb.toString(); } @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof java.util.Map)) { return false; } if (o instanceof Map) { return o.equals(_m) && ((Map)o).ro == ro; } return o.equals(_m); } // --- extensions @SuppressWarnings("unused") public boolean readOnly() { return ro; } @SuppressWarnings("unused") public Map<K, V> readOnly(boolean readOnly) { if (ro ^ readOnly) { return new Map<K, V>(readOnly, _m); } else { return this; } } /** * Loop through this map on each key/value pair, apply them to the function specified * @param indexedVisitor the function that takes argument of (key, value) pair * @return this map */ public Map<K, V> forEach($.Func2<? super K, ? super V, ?> indexedVisitor) { for (java.util.Map.Entry<K, V> entry: entrySet()) { try { indexedVisitor.apply(entry.getKey(), entry.getValue()); } catch (NotAppliedException e) { // ignore } } return this; } /** * Alias of {@link #forEach(Osgl.Func2)} * @param indexedVisitor the visitor that can be applied on Key/Value pair stored in this Map * @return this map */ public Map<K, V> each($.Func2<? super K, ? super V, ?> indexedVisitor) { return forEach(indexedVisitor); } /** * Alias of {@link #forEach(Osgl.Func2)} * @param indexedVisitor the visitor that can be applied on Key/Value pair stored in this Map * @return this map */ public Map<K, V> accept($.Func2<? super K, ? super V, ?> indexedVisitor) { return forEach(indexedVisitor); } private void writeObject(java.io.ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeObject(_m); if (ro) s.writeInt(1); else s.writeInt(0); } private static final long serialVersionUID = 262498820763181265L; @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); _m = (java.util.Map)s.readObject(); int i = s.readInt(); ro = i != 0; } } public interface Set<T> extends java.util.Set<T>, Traversable<T> { @Override Set<T> parallel(); @Override Set<T> sequential(); @Override Set<T> lazy(); @Override Set<T> eager(); @Override Set<T> filter($.Function<? super T, Boolean> predicate); @Override Set<T> accept($.Function<? super T, ?> visitor); @Override Set<T> each($.Function<? super T, ?> visitor); @Override Set<T> forEach($.Function<? super T, ?> visitor); /** * Returns a set contains all elements in the {@code col} * collection specified but not in this set * * @param col the collection in which elements should * be included from the result set * @return a set contains elements only in the col */ @SuppressWarnings("unused") Set<T> onlyIn(Collection<? extends T> col); /** * Returns a set contains only elements in both {@code col} * collection specified and this set * * @param col the collection in which elements should * be included from the result set * @return a set contains elements in both col and this set */ Set<T> withIn(Collection<T> col); /** * Returns a set contains all elements in this set and not in * the {@code col} collection specified * * @param col the collection in which elements should * be excluded from the result set * @return a set contains elements only in this set */ Set<T> without(Collection<? super T> col); /** * Returns a set contains all elements in the set except the * one specified * * @param element the element that should not be in the resulting set * @return a set without the element specified */ Set<T> without(T element); /** * Returns a set contains all elements in the set except the * ones specified * * @param element the element that should not be in the resulting set * @param elements the array contains elements that should not be in the resulting set * @return a set without the element specified */ Set<T> without(T element, T... elements); } public interface ListOrSet<T> extends List<T>, Set<T> { @Override ListOrSet<T> parallel(); @Override ListOrSet<T> sequential(); @Override ListOrSet<T> lazy(); @Override ListOrSet<T> eager(); @Override ListOrSet<T> accept($.Function<? super T, ?> visitor); @Override ListOrSet<T> each($.Function<? super T, ?> visitor); @Override ListOrSet<T> forEach($.Function<? super T, ?> visitor); @Override ListOrSet<T> filter($.Function<? super T, Boolean> predicate); @Override ListOrSet<T> without(Collection<? super T> col); @Override ListOrSet<T> without(T element); @Override ListOrSet<T> without(T element, T... elements); @Override <R> ListOrSet<R> map($.Function<? super T, ? extends R> mapper); } /** * Defines a factory to create {@link java.util.List java List} instance * used by {@link DelegatingList} to create it's backing data structure * * @since 0.2 */ public interface ListFactory { /** * Create an empty <code>java.util.List</code> contains the generic type E * * @param <ET> the generic type of the list element * @return A java List instance contains elements of generic type E */ <ET> java.util.List<ET> create(); /** * Create a <code>java.util.List</code> pre populated with elements * of specified collection * * @param collection the collection whose elements are to be placed into this list * @param <ET> the generic type of the list element * @return The List been created * @exception NullPointerException if the specified collection is null */ <ET> java.util.List<ET> create(Collection<? extends ET> collection) throws NullPointerException; /** * Create a <code>java.util.List</code> with initial capacity * * @param initialCapacity the initial capacity of the new List * @param <ET> the generic type of the list element * @return the list been created */ <ET> java.util.List<ET> create(int initialCapacity); enum Predefined { ; static final ListFactory JDK_ARRAYLIST_FACT = new ListFactory() { @Override public <ET> java.util.List<ET> create() { return new ArrayList<ET>(); } @Override public <ET> java.util.List<ET> create(Collection<? extends ET> collection) { return new ArrayList<ET>(collection); } @Override public <ET> java.util.List<ET> create(int initialCapacity) { return new ArrayList<ET>(initialCapacity); } }; static final ListFactory JDK_LINKEDLIST_FACT = new ListFactory() { @Override public <ET> java.util.List<ET> create() { return new LinkedList<ET>(); } @Override public <ET> java.util.List<ET> create(Collection<? extends ET> collection) { return new LinkedList<ET>(collection); } @Override public <ET> java.util.List<ET> create(int initialCapacity) { return new LinkedList<ET>(); } }; static ListFactory defLinked() { return JDK_LINKEDLIST_FACT; } static ListFactory defRandomAccess() { return JDK_ARRAYLIST_FACT; } } } /** * "osgl.list.factory", the property key to configure user defined * {@link ListFactory list factory}. * Upon loaded, osgl tried to get a class name string from system * properties use this configuration key. If osgl find the String * returned is not empty then it will initialize the list factory * use the class name configured. If any exception raised during the * initialization, then it might cause the JVM failed to boot up * * @since 0.2 */ public static final String CONF_LINKED_LIST_FACTORY = "osgl.linked_list.factory"; /** * "osgl.random_access_list.factory", the property key to configure user defined {@link ListFactory * random access list factory}. See {@link #CONF_LINKED_LIST_FACTORY} for how osgl use this configuration * * @since 0.2 */ public static final String CONF_RANDOM_ACCESS_LIST_FACTORY = "osgl.random_access_list.factory"; static ListFactory linkedListFact; static { String factCls = System.getProperty(CONF_LINKED_LIST_FACTORY); if (null == factCls) { linkedListFact = ListFactory.Predefined.defLinked(); } else { $.Option<ListFactory> fact = $.safeNewInstance(factCls); if (fact.isDefined()) { linkedListFact = fact.get(); } else { linkedListFact = ListFactory.Predefined.defLinked(); } } } static ListFactory randomAccessListFact; static { String factCls = System.getProperty(CONF_RANDOM_ACCESS_LIST_FACTORY); if (null == factCls) { randomAccessListFact = ListFactory.Predefined.defRandomAccess(); } else { $.Option<ListFactory> fact = $.safeNewInstance(factCls); if (fact.isDefined()) { randomAccessListFact = fact.get(); } else { randomAccessListFact = ListFactory.Predefined.defRandomAccess(); } } } public static boolean empty(Collection<?> col) { return null == col || col.isEmpty(); } @SuppressWarnings("unused") public static boolean notEmpty(Collection<?> col) { return !empty(col); } public static boolean isEmpty(Collection<?> col) { return empty(col); } public static boolean empty(java.util.Map map) { return null == map || map.isEmpty(); } public static boolean notEmpty(java.util.Map map) { return !empty(map); } public static boolean isEmpty(java.util.Map map) { return empty(map); } // --- conversion methods --- public static <T> Collection<T> asCollection(Iterable<T> iterable) { if (iterable instanceof Collection) { return $.cast(iterable); } return C.list(iterable); } // --- eof conversion methods --- // --- factory methods --- /** * Returns a {@link Range} of integer specified by {@code from} and {@code to}. {@code from} * can be less or larger than {@code to}. * * @param from specify the left side of the range (inclusive) * @param to specify the right hand side of the range (exclusive) * @return a range of integer @{code [from .. to)} */ public static Range<Integer> range(int from, int to) { return new LazyRange<Integer>(from, to, N.F.INT_RANGE_STEP); } /** * Returns a {@link Range} of byte specified by {@code from} and {@code to}. {@code from} * can be less or larger than {@code to}. * * @param from specify the left side of the range (inclusive) * @param to specify the right hand side of the range (exclusive) * @return a range of byte @{code [from .. to)} */ public static Range<Byte> range(byte from, byte to) { return new LazyRange<Byte>(from, to, N.F.BYTE_RANGE_STEP); } /** * Returns a {@link Range} of short specified by {@code from} and {@code to}. {@code from} * can be less or larger than {@code to}. * * @param from specify the left side of the range (inclusive) * @param to specify the right hand side of the range (exclusive) * @return a range of short @{code [from .. to)} */ public static Range<Short> range(short from, short to) { return new LazyRange<Short>(from, to, N.F.SHORT_RANGE_STEP); } /** * Returns a {@link Range} of long specified by {@code from} and {@code to}. {@code from} * can be less or larger than {@code to}. * * @param from specify the left side of the range (inclusive) * @param to specify the right hand side of the range (exclusive) * @return a range of long @{code [from .. to)} */ public static Range<Long> range(long from, long to) { return new LazyRange<Long>(from, to, N.F.LONG_RANGE_STEP); } /** * Returns a {@link Range} of non-negative integers start from {@code 0} to {@code Integer.MAX_VALUE}. Note * unlike traditional definition of natural number, zero is included in the range returned * * @return a range of non negative integers */ @SuppressWarnings("unused") public static Range<Integer> naturalNumbers() { return new LazyRange<Integer>(1, Integer.MAX_VALUE, N.F.INT_RANGE_STEP); } /** * Returns a {@link Range} of non-negative even numbers starts from {@code 0} to * {@code Integer.MAX_VALUE}. * * @return a range of non-negative even numbers */ @SuppressWarnings("unused") public static Range<Integer> evenNumbers() { return new LazyRange<Integer>(0, Integer.MAX_VALUE, N.F.intRangeStep(2)); } /** * Returns a {@link Range} of positive odd numbers starts from {@code 1} to * {@code Integer.MAX_VALUE}. * * @return a range of positive odd numbers */ @SuppressWarnings("unused") public static Range<Integer> oddNumbers() { return new LazyRange<Integer>(1, Integer.MAX_VALUE, N.F.intRangeStep(2)); } @SuppressWarnings("unused") public static final List EMPTY_LIST = Nil.list(); @SuppressWarnings("unused") public static final Set EMPTY_SET = Nil.set(); @SuppressWarnings("unused") public static final java.util.Map EMPTY_MAP = Collections.EMPTY_MAP; public static final ListOrSet EMPTY = Nil.EMPTY; @SuppressWarnings("unchecked") public static <T> ListOrSet<T> empty() { return EMPTY; } /** * Returns an empty immutable list * * @param <T> the type of the list element * @return the empty list */ public static <T> List<T> list() { return Nil.list(); } @SuppressWarnings("unused") public static <T> List<T> emptyListOf(Class<T> c) { return Nil.list(); } public static <T> List<T> list(T t) { return $.val(t); } /** * Creates an immutable list of an array of elements. * <p>Note the array will not be copied, instead it will * be used directly as the backing data for the list. * To create an list with a copy of the array specified. * Use the {@link #newListOf(Object[])} method</p> * * @param ta an array of elements * @param <T> the element type * @return an immutable list backed by the specified array */ public static <T> List<T> listOf(T... ta) { return ImmutableList.of(ta); } /** * Creates an immutable list from an element plus an array of elements * * @param t the first element * @param ta the array * @param <T> the element type * @return an immutable list contains the first element and followed by all element in the array */ public static <T> List<T> list(T t, T... ta) { int len = ta.length; T[] a = $.newArray(ta, len + 1); a[0] = t; System.arraycopy(ta, 0, a, 1, len); return ImmutableList.of(a); } /** * Create an immutable Boolean list from a boolean (primitive type) array. * <p>At the moment the implementation will convert the boolean (primary) * array to Boolean (wraper) array, thus a copy of the array * will actually take place. However it should assume the * array will directly be used as backing data in user application * to cater to the future optimized implementation</p> * * @param elements an array of primary boolean * @return a Boolean typed list */ public static List<Boolean> listOf(boolean[] elements) { return list(elements); } /** * Create an immutable Boolean list of a byte (primitive type) array. * The elements of the array is copied into the returned list * * @param elements an array of bytes * @return an immutable list contains specified elements */ public static List<Boolean> list(boolean[] elements) { if (elements.length == 0) { return Nil.list(); } Boolean[] ba = $.asObject(elements); return ImmutableList.of(ba); } /** * Create an immutable Byte list from a byte (primitive type) array. * <p>At the moment the implementation will convert the byte (primary) * array to Byte (reference) array, thus a copy of the array * will actually take place. However it should assume the * array will directly be used as backing data in user application * to cater to the future optimized implementation</p> * * @param elements an array of primary byte * @return a Byte typed list */ public static List<Byte> listOf(byte[] elements) { return list(elements); } /** * Create an immutable Byte list of a byte (primitive type) array. * The elements of the array is copied into the returned list * * @param elements an array of bytes * @return an immutable list contains specified elements */ public static List<Byte> list(byte[] elements) { if (elements.length == 0) { return Nil.list(); } Byte[] ba = $.asObject(elements); return ImmutableList.of(ba); } /** * Create an immutable Short list from a char (primitive type) array. * <p>At the moment the implementation will convert the char (primary) * array to Character (reference) array, thus a copy of the array * will actually take place. However it should assume the * array will directly be used as backing data in user application * to cater to the future optimized implementation</p> * * @param elements an array of primary short * @return a Short typed list */ public static List<Character> listOf(char[] elements) { return list(elements); } /** * Create an immutable Character list of a char array. * The elements of the array is copied into the returned list * * @param elements an array of shorts * @return an immutable list contains specified elements */ public static List<Character> list(char[] elements) { if (0 == elements.length) { return Nil.list(); } Character[] a = $.asObject(elements); return ImmutableList.of(a); } /** * Create an immutable Short list from a short (primitive type) array. * <p>At the moment the implementation will convert the short (primary) * array to Short (reference) array, thus a copy of the array * will actually take place. However it should assume the * array will directly be used as backing data in user application * to cater to the future optimized implementation</p> * * @param elements an array of primary short * @return a Short typed list */ public static List<Short> listOf(short[] elements) { return list(elements); } /** * Create an immutable Short list of a short array. * The elements of the array is copied into the returned list * * @param elements an array of shorts * @return an immutable list contains specified elements */ public static List<Short> list(short[] elements) { if (0 == elements.length) { return Nil.list(); } Short[] a = $.asObject(elements); return ImmutableList.of(a); } /** * Create an immutable Integer list from an int (primitive type) array. * <p>At the moment the implementation will convert the int (primary) * array to Integer (reference) array, thus a copy of the array * will actually take place. However it should assume the * array will directly be used as backing data in user application * to cater to the future optimized implementation</p> * * @param elements an array of primary int * @return an Integer list */ public static List<Integer> listOf(int[] elements) { return list(elements); } /** * Create an immutable integer list of a int array. If an empty array specified, * the nan empty immutable list is returned * * @param elements an array of int * @return an immutable list contains specified elements */ public static List<Integer> list(int[] elements) { if (elements.length == 0) { return Nil.list(); } Integer[] a = $.asObject(elements); return ImmutableList.of(a); } /** * Create an immutable Long list from a long (primitive type) array. * <p>At the moment the implementation will convert the long (primary) * array to Long (reference) array, thus a copy of the array * will actually take place. However it should assume the * array will directly be used as backing data in user application * to cater to the future optimized implementation</p> * * @param elements an array of primary long * @return an Long list */ public static List<Long> listOf(long[] elements) { return list(elements); } /** * Create an immutable Long list of a long array. If an empty array specified, * the nan empty immutable list is returned * * @param elements an array of long * @return an immutable list contains specified elements */ public static List<Long> list(long[] elements) { if (0 == elements.length) { return list(); } return ImmutableList.of($.asObject(elements)); } /** * Create an immutable Float list from a float (primitive type) array. * <p>At the moment the implementation will convert the float (primary) * array to Float (reference) array, thus a copy of the array * will actually take place. However it should assume the * array will directly be used as backing data in user application * to cater to the future optimized implementation</p> * * @param elements an array of primary float * @return an Float list */ public static List<Float> listOf(float[] elements) { return list(elements); } /** * Create an immutable byte list of a float array. If an empty array specified, * the nan empty immutable list is returned * * @param elements an array of floats * @return an immutable list contains specified elements */ public static List<Float> list(float[] elements) { if (0 == elements.length) { return list(); } return ImmutableList.of($.asObject(elements)); } /** * Create an immutable Double list from an double (primitive type) array. * <p>At the moment the implementation will convert the double (primary) * array to Double (reference) array, thus a copy of the array * will actually take place. However it should assume the * array will directly be used as backing data in user application * to cater to the future optimized implementation</p> * * @param elements an array of primary double * @return an Double list */ public static List<Double> listOf(double[] elements) { return list(elements); } /** * Create an immutable Byte list of a double array. If an empty array specified, * the nan empty immutable list is returned * * @param elements an array of double * @return an immutable list contains specified elements */ public static List<Double> list(double[] elements) { if (0 == elements.length) { return list(); } return ImmutableList.of($.asObject(elements)); } public static <T> List<T> list(Iterable<? extends T> iterable) { return ListBuilder.toList(iterable); } public static <T> List<T> list(Iterator<? extends T> iterator) { return ListBuilder.toList(iterator); } public static <T> List<T> list(Enumeration<? extends T> enumeration) { return ListBuilder.toList(enumeration); } public static <T> List<T> list(Collection<? extends T> col) { return ListBuilder.toList(col); } public static <T> List<T> list(java.util.List<? extends T> javaList) { if (javaList instanceof List) { List<T> list = $.cast(javaList); if (list.is(Feature.IMMUTABLE)) { return list; } else { return new ReadOnlyDelegatingList<T>(list); } } return new ReadOnlyDelegatingList<T>(javaList); } public static <T> List<T> singletonList(T t) { return list(t); } public static <T> List<T> wrap(java.util.List<T> list) { return DelegatingList.wrap(list); } public static <T> List<T> newSizedList(int size) { return new DelegatingList<T>(size); } public static <T> List<T> newList() { return newSizedList(10); } public static <T> List<T> newList(Iterable<? extends T> iterable) { return new DelegatingList<T>(iterable); } public static <T> List<T> newList(T t) { return new DelegatingList<T>(10).append(t); } public static <T> List<T> newList(T t1, T t2) { return new DelegatingList<T>(10).append(t1).append(t2); } public static <T> List<T> newList(T t1, T t2, T t3) { return new DelegatingList<T>(10).append(t1).append(t2).append(t3); } public static <T> List<T> newList(T t1, T t2, T t3, T... ta) { int len = ta.length; List<T> l = new DelegatingList<T>(len + 3).append(t1).append(t2).append(t3); l.addAll(listOf(ta)); return l; } public static <T> List<T> newListOf(T[] ts) { return new DelegatingList<T>(C.listOf(ts)); } /** * Return a {@link Sequence} consists of all elements in the * iterable specified * @param iterable the iterable in which elements will be used to fill into the sequence * @param <T> the element type * @return the sequence */ @SuppressWarnings("unchecked") public static <T> Sequence<T> seq(Iterable<? extends T> iterable) { if (iterable instanceof Sequence) { return ((Sequence<T>) iterable); } return IterableSeq.of(iterable); } public static <T> Sequence<T> seq(Iterator<? extends T> iterator) { return IteratorSeq.of(iterator); } public static <T> Sequence<T> seq(Enumeration<? extends T> enumeration) { return IteratorSeq.of(new EnumerationIterator<T>(enumeration)); } public static <T, R> Sequence<R> map(Sequence<T> seq, $.Function<? super T, ? extends R> mapper) { if (seq instanceof ReversibleSequence) { return map((ReversibleSequence<T>) seq, mapper); } return new MappedSeq<T, R>(seq, mapper); } public static <T, R> ReversibleSequence<R> map(ReversibleSequence<T> seq, $.Function<? super T, ? extends R> mapper ) { return new ReversibleMappedSeq<T, R>(seq, mapper); } public static <T> Sequence<T> filter(Sequence<T> seq, $.Function<? super T, Boolean> predicate) { return new FilteredSeq<T>(seq, predicate); } @SuppressWarnings("unchecked") public static <T> Sequence<T> prepend(T t, Sequence<T> sequence) { if (sequence instanceof ReversibleSequence) { return prepend(t, (ReversibleSequence) sequence); } else { return concat(C.list(t), sequence); } } /** * Concatenate two {@link Sequence} into one * @param s1 the first sequence * @param s2 the second sequence * @param <T> the element type * @return the concatenated sequence */ public static <T> Sequence<T> concat(Sequence<T> s1, Sequence<T> s2) { return s1.append(s2); } /** * Concatenate two {@link ReversibleSequence} into one * @param s1 the first reversible sequence * @param s2 the second reversible sequence * @param <T> the element type * @return the concatenated reversible sequence */ @SuppressWarnings("unused") public static <T> ReversibleSequence<T> concat(ReversibleSequence<T> s1, ReversibleSequence<T> s2) { return s1.append(s2); } /** * Concatenate two {@link List} into one. * <p><b>Note</b> if the first list is readonly or immutable an new list instance * will be created with elements in both list 1 and list 2 filled in. Otherwise * all elemnets from list 2 will be appended to list 1 and return list 1 instance</p> * @param l1 list 1 * @param l2 list 2 * @param <T> the element type * @return a list with elements of both list 1 and list 2 */ @SuppressWarnings("unused") public static <T> List<T> concat(List<T> l1, List<T> l2) { return l1.append(l2); } /** * Create an empty immutable set * @param <T> the generic type * @return the empty set */ public static <T> Set<T> set() { return Nil.set(); } /** * Create an immutable set of a single element * @param element the single element * @param <T> the element type * @return the set that contains only specified element */ public static <T> Set<T> set(T element) { java.util.Set<T> set = new HashSet<T>(); set.add(element); return ImmutableSet.of(set); } /** * Create an immutable set contains specified elements * @param t1 one element to be added into the result set * @param ta an array from which all elements will be added into the result set * @param <T> the element type * @return a set that contains all elements specified */ public static <T> Set<T> set(T t1, T... ta) { java.util.Set<T> set = new HashSet<T>(); set.add(t1); Collections.addAll(set, ta); return ImmutableSet.of(set); } /** * Create an immutable set of an array of elements * @param ta the array from which all elements will be added into * the result set * @param <T> the element type * @return the set contains all elements in the array */ public static <T> Set<T> setOf(T... ta) { java.util.Set<T> set = new HashSet<T>(); Collections.addAll(set, ta); return ImmutableSet.of(set); } /** * Create an immutable set of all elements contained in the collection specified * @param col the collection from which elements will be added into the * result set * @param <T> the element type * @return the set contains all elements in the collection * @see #newSet(Collection) */ public static <T> Set<T> set(Collection<? extends T> col) { return ImmutableSet.of(col); } /** * Create an immutable set of all elements supplied by the iterable specified * @param itr the iterable from where elements will be added into the result set * @param <T> the element type * @return the set contains all elements supplied by the iterable */ @SuppressWarnings("unchecked") public static <T> Set<T> set(Iterable<? extends T> itr) { if (itr instanceof Collection) { return set((Collection<T>) itr); } java.util.Set<T> set = new HashSet<T>(); for (T t : itr) set.add(t); return ImmutableSet.of(set); } /** * Create an new empty set * @param <T> the element type * @return an empty set */ public static <T> Set<T> newSet() { return new DelegatingSet<T>(); } /** * Create an new set with all elements contained in the collection * specified * @param col the collection from which all elements will be added into * the result set * @param <T> the element type * @return the set contains all elements in the collection * @see #set(Collection) */ public static <T> Set<T> newSet(Collection<? extends T> col) { return new DelegatingSet<T>(col); } /** * Create a immutable {@link java.util.Map} from elements specified in an array. * <p>Example</p> * <pre> * Map<String, Integer> scores = C.map("Tom", 80, "Peter", 93, ...); * </pre> * <p>The above code will create an immutable Map with the following entries</p> * <ul> * <li>(Tom, 80)</li> * <li>(Peter, 93)</li> * <li>...</li> * </ul> * <p><b>Note</b> the array size must be an even number, otherwise {@link IndexOutOfBoundsException} * will be thrown out</p> * @param args the argument array specifies the entries * @param <K> the key type * @param <V> the value type * @return an immutable map contains of specified entries * @see #newMap(Object...) */ @SuppressWarnings("unchecked") public static <K, V> java.util.Map<K, V> map(Object... args) { if (null == args || args.length == 0) { return Collections.EMPTY_MAP; } return new Map(true, args); } /** * Create an immutable {@link java.util.Map} from existing {@link java.util.Map} * @param map the map from which entries will be put into the new immutable map * @param <K> the key type * @param <V> the value type * @return an immutable map of the existing map */ public static <K, V> java.util.Map<K, V> map(java.util.Map<? extends K, ? extends V> map) { if (null == map) { return Collections.emptyMap(); } return Collections.unmodifiableMap(map); } /** * Create an immutable {@link java.util.Map} from existing {@link Map} * @param map the map from which entries will be put into the new immutable map * @param <K> the key type * @param <V> the value type * @return an immutable map of the existing map */ public static <K, V> java.util.Map<K, V> map(Map<? extends K, ? extends V> map) { if (null == map) { return Collections.emptyMap(); } return Collections.unmodifiableMap(map); } /** * Create an new {@link Map} from an array of elements. * <p>Example</p> * <pre> * Map<String, Integer> scores = C.newMap("Tom", 80, "Peter", 93, ...); * </pre> * <p>The above code will create a Map with the following entries</p> * <ul> * <li>(Tom, 80)</li> * <li>(Peter, 93)</li> * <li>...</li> * </ul> * <p><b>Note</b> the array size must be an even number, otherwise {@link IndexOutOfBoundsException} * will be thrown out</p> * @param args the argument array specifies the entries * @param <K> the key type * @param <V> the value type * @return a map contains of specified entries * @see #map(Object...) */ @SuppressWarnings("unchecked") public static <K, V> Map<K, V> newMap(Object... args) { return new Map(false, args); } /** * Create an new {@link Map} from existing {@link java.util.Map} * @param map the map that contains elements to be put into the new map * @param <K> the key type * @param <V> the value type * @return a map that contains all entries in the existing map */ @SuppressWarnings("unchecked") public static <K, V> Map<K, V> newMap(java.util.Map<? extends K, ? extends V> map) { return new Map(false, map); } /** * Convert a {@link Enumeration} to an {@link Iterable} * @param e the enumeration * @param <T> the element type * @return an iterable corresponding to the enumeration */ public static <T> Iterable<T> enumerable(final Enumeration<T> e) { return new Iterable<T>() { @Override public Iterator<T> iterator() { return new Iterator<T>() { @Override public boolean hasNext() { return e.hasMoreElements(); } @Override public T next() { return e.nextElement(); } @Override public void remove() { throw E.unsupport(); } }; } }; } // --- eof factory methods --- // --- utility methods --- /** * Check if a {@link Traversable} structure is read only. A * Traversable is considered to be read only structure when * {@code is(Feature.READONLY) || is(Feature.IMMUTABLE} * evaluate to {@code true} * * @param t the structure to be checked * @return {@code true} if the structure is read only * or immutable */ @SuppressWarnings("unused") public static boolean isReadOnly(Traversable<?> t) { return t.is(Feature.READONLY) || t.is(Feature.IMMUTABLE); } /** * Check if a {@link Traversable} structure is immutable. * * @param t the traversable strucure to be checked * @return {@code true} if the traversable is immutable */ @SuppressWarnings("unused") public static boolean isImmutable(Traversable<?> t) { return t.is(Feature.IMMUTABLE); } /** * Run visitor function on each element supplied by the iterable. The visitor function can throw out * {@link org.osgl.Osgl.Break} if it need to break the loop. * <p>Note if {@link NotAppliedException} thrown out by visitor function, it will be ignored * and keep looping through the Map entry set. It is kind of {@code continue} mechanism in a funcitonal * way</p> * @param iterable supply the element to be applied to the visitor function * @param visitor the function called on element provided by the iterable * @param <T> the generic type of the iterable elements * @throws $.Break break the loop */ //TODO: implement forEach iteration in parallel public static <T> void forEach(Iterable<? extends T> iterable, $.Function<? super T, ?> visitor) throws $.Break { for (T t : iterable) { try { visitor.apply(t); } catch (NotAppliedException e) { // ignore } } } /** * Run visitor function on each element supplied by the iterator. The visitor function can throw out * {@link org.osgl.Osgl.Break} if it need to break the loop. * <p>Note if {@link NotAppliedException} thrown out by visitor function, it will be ignored * and keep looping through the Map entry set. It is kind of {@code continue} mechanism in a funcitonal * way</p> * @param iterator iterator provides elements to be applied to the visitor function * @param visitor the function applied on the element * @param <T> the generic type of the element */ public static <T> void forEach(Iterator<? extends T> iterator, $.Function<? super T, ?> visitor) { while (iterator.hasNext()) { T t = iterator.next(); visitor.apply(t); } } /** * Run indexedVisitor function on all key/value pair in a given map. The indexedVisitor function can * throw out {@link org.osgl.Osgl.Break} if it need to break the loop. * <p>Note if {@link NotAppliedException} thrown out by indexedVisitor function, it will be ignored * and keep looping through the Map entry set. It is kind of {@code continue} mechanism in a funcitonal * way</p> * @param map the map in which enties will be applied to the indexedVisitor function * @param indexedVisitor the function that takes (key,value) pair * @param <K> the generic type of Key * @param <V> the generic type of Value * @throws $.Break the {@link org.osgl.Osgl.Break} with payload throwed out by indexedVisitor function to break to loop */ public static <K, V> void forEach(java.util.Map<K, V> map, $.Func2<? super K, ? super V, ?> indexedVisitor) throws $.Break { for (java.util.Map.Entry<K, V> entry : map.entrySet()) { try { indexedVisitor.apply(entry.getKey(), entry.getValue()); } catch (NotAppliedException e) { // ignore } } } // --- eof utility methods --- /** * the namespace of function definitions relevant to Collection manipulation */ public enum F { ; public static <T> $.Transformer<Iterable<T>, Collection<T>> asCollection() { return new Osgl.Transformer<Iterable<T>, Collection<T>>() { @Override public Collection<T> transform(Iterable<T> iterable) { return C.asCollection(iterable); } }; } /** * Returns a predicate function that check if the argument is contained in * the collection specified * * @param collection the collection to be checked on against the argument when applying the prediate * @param <T> the generic type of the element of the collection * @return a predicate function * @see Collection#contains(Object) * @see #contains(Object) */ public static <T> $.Predicate<T> containsIn(final Collection<? super T> collection) { return new $.Predicate<T>() { @Override public boolean test(T t) throws NotAppliedException, $.Break { return collection.contains(t); } }; } /** * Returns a predicate function that check if the argument (collection) contains the * element specified * * @param element the element to be checked * @param <T> the type of the element * @return the function that do the check * @see Collection#contains(Object) * @see #containsIn(Collection) */ public static <T> $.Predicate<Collection<? super T>> contains(final T element) { return new $.Predicate<Collection<? super T>>() { @Override public boolean test(Collection<? super T> collection) { return collection.contains(element); } }; } /** * Returns a predicate function that check if all element in the argument (a collection) contained * in the collection specified * @param collection the collection to be checked on against all elements in the argument when * applying the function * @param <T> the generic type of the element of the collection or argument * @return the function that do the check * @see Collection#containsAll(Collection) * @see #containsAll(Collection) */ @SuppressWarnings("unused") public static <T> $.Predicate<Collection<? extends T>> allContainsIn(final Collection<? super T> collection) { return new $.Predicate<Collection<? extends T>>() { @Override public boolean test(Collection<? extends T> theCollection) { return collection.containsAll(theCollection); } }; } /** * Returns a predicate function that check if all element in the collection specified are contained in * the argument collection * @param collection the collection in which all elements will be checked if contained in the argument * collection when applying the function * @param <T> the element type * @return the function that do the check * @see Collection#containsAll(Collection) * @see #allContainsIn(Collection) */ @SuppressWarnings("unused") public static <T> $.Predicate<Collection<? super T>> containsAll(final Collection<? extends T> collection) { return new $.Predicate<Collection<? super T>>() { @Override public boolean test(Collection<? super T> theCollection) { return theCollection.contains(collection); } }; } /** * Returns a function that add the argument to a collection specified and returns * {@code true} if added successfully or {@code false} otherwise * @param destination the collection into which the argument to be added * @param <T> the generic type of the collection elements * @return a function that do the add operation * @see Collection#add(Object) * @see #add(Object) */ public static <T> $.Predicate<T> addTo(final Collection<? super T> destination) { return new $.Predicate<T>() { @Override public boolean test(T t) throws NotAppliedException, $.Break { return destination.add(t); } }; } /** * Returns a function that add the specified element into the argument collection and * return {@code true} if add successfully or {@code false} otherwise * @param element the element to be added when applying the function * @param <T> the element type * @return the function * @see Collection#add(Object) * @see #addTo(Collection) */ public static <T> $.Predicate<Collection<? super T>> add(final T element) { return new $.Predicate<Collection<? super T>>() { @Override public boolean test(Collection<? super T> collection) { return collection.add(element); } }; } /** * Returns a function that add the argument into the specified list at specified position. * the function returns {@code true} if added successfully or {@code false} otherwise * @param destination a list into which the argument to be added * @param index specify the position where the argument can be added * @param <L> the generic type of the list * @param <T> the generic type of the list element * @return the function that do the add operation * @see java.util.List#add(int, Object) * @see #add(int, Object) */ @SuppressWarnings("unused") public static <L extends List<? super T>, T> $.F1<T, L> addTo(final int index, final L destination) { return new $.F1<T, L>() { @Override public L apply(T t) throws NotAppliedException, $.Break { destination.add(index, t); return destination; } }; } /** * Returns a function that add specified element into the argument list at specified position. The * function returns the argument list after element added * @param index the location at where the element should be added to * @param element the element the be added to the argument list * @param <L> the list type * @param <T> the element type * @return the function * @see java.util.List#add(int, Object) * @see #addTo(int, List) */ public static <L extends List<? super T>, T> $.F1<L, L> add(final int index, final T element) { return new $.F1<L, L>() { @Override public L apply(L list) throws NotAppliedException, Osgl.Break { list.add(index, element); return list; } }; } /** * Returns a function that takes argument of type {@link Collection} and add all elements inside * into the specified collection. The function returns {@code true} if the collection specified * has been changed as a result of adding elements * @param destination the collection into which all elements in the argument collection will be added * when applying the function * @param <T> the generic type of the collection element and the argument collection element * @return the function that add all elements from iterable argument into the collection specified * @see Collection#addAll(Collection) * @see #addAll(Collection) */ @SuppressWarnings({"unchecked"}) public static <T> $.Predicate<Iterable<? extends T>> addAllTo(final Collection<? super T> destination) { return new $.Predicate<Iterable<? extends T>>() { @Override public boolean test(Iterable<? extends T> source) throws NotAppliedException, $.Break { if (source instanceof Collection) { return destination.addAll((Collection)(source)); } return destination.addAll(C.list(source)); } }; } /** * Returns a function that add all elements in the source collection specified into the destination * collection as argument. The function returns {@code true} if the argument collection has been * changes as a result of call. * @param source the collection from which the elements will be added into the argument collection * when applying the function * @param <T> the element type * @return the function the perform the add operation * @see Collection#addAll(Collection) * @see #addAllTo(Collection) */ @SuppressWarnings({"unchecked"}) public static <T> $.Predicate<Collection<? super T>> addAll(final Collection<? extends T> source) { return new $.Predicate<Collection<? super T>>() { @Override public boolean test(Collection<? super T> destination) { return destination.addAll(source); } }; } /** * Returns a function that add all elements from the argument collection into the destination list specified * at the position specified * @param index the position at where the element shall be inserted into the destination list * @param destination the list into which the elements will be added * @param <T> the element type * @return the function that do the add operation * @see java.util.List#addAll(int, Collection) * @see #addAll(int, Collection) */ @SuppressWarnings({"unused"}) public static <T> $.Predicate<Collection<? extends T>> addAllTo(final int index, final List<? super T> destination) { if (0 > index || destination.size() < index) { throw new IndexOutOfBoundsException(); } return new $.Predicate<Collection<? extends T>>() { @Override public boolean test(Collection<? extends T> collection) throws NotAppliedException, $.Break { return destination.addAll(index, collection); } }; } /** * Returns a function that add all elements from the source collection specified into the argument list at * the position specified * @param index the position where the element should be insert in the argument list * @param source the collection from which the elements to be get to added into the argument list * @param <T> the element type * @return the function that do the add operation * @see java.util.List#addAll(int, Collection) * @see #addAllTo(int, List) */ @SuppressWarnings({"unused"}) public static <T> $.Predicate<List<? super T>> addAll(final int index, final Collection<? extends T> source) { return new $.Predicate<List<? super T>>() { @Override public boolean test(List<? super T> destination) { return destination.addAll(index, source); } }; } /** * Returns a function that remove the argument from a collection specified. * <p>The function returns {@code true} if argument removed successfully or * {@code false} otherwise</p> * @param collection the collection from which the argument to be removed * when applying the function returned * @return the function that remove element from the collection * @see Collection#remove(Object) * @see #remove(Object) */ @SuppressWarnings("unused") public static <T> $.Predicate<T> removeFrom(final Collection<? super T> collection) { return new $.Predicate<T>() { @Override public boolean test(T t) throws NotAppliedException, $.Break { return collection.remove(t); } }; } /** * Returns a function that remove the element specified from the argument collection. The * function returns {@code true} if the argument collection changed as a result of the call. * @param toBeRemoved the element to be removed from the argument when applying the function * @param <T> the element type * @return the function that do removing * @see Collection#remove(Object) * @see #removeFrom(Collection) */ @SuppressWarnings("unused") public static <T> $.Predicate<Collection<? super T>> remove(final T toBeRemoved) { return new $.Predicate<Collection<? super T>>() { @Override public boolean test(Collection<? super T> collection) { return collection.remove(toBeRemoved); } }; } /** * Returns a function that remove all elements in the argument collection from * the {@code fromCollection} specified. The function returns {@code true} if * the fromCollection changed as a result of call * @param fromCollection the collection from which elements will be removed * @param <T> the element type * @return the function * @see Collection#removeAll(Collection) * @see #removeAll(Collection) */ @SuppressWarnings("unused") public static <T> $.Predicate<Collection<? extends T>> removeAllFrom(final Collection<? super T> fromCollection) { return new Osgl.Predicate<Collection<? extends T>>() { @Override public boolean test(Collection<? extends T> theCollection) { return fromCollection.removeAll(theCollection); } }; } /** * Returns a function that remove all elements in the {@code source} collection from the * argument collection. The function returns {@code true} if the argument collection changed * as a result of call * @param source the collection in which elements will be used to remove from argument collection * @param <T> the element type * @return the function * @see Collection#removeAll(Collection) * @see #removeAllFrom(Collection) */ public static <T> $.Predicate<Collection<? super T>> removeAll(final Collection<? extends T> source) { return new Osgl.Predicate<Collection<? super T>>() { @Override public boolean test(Collection<? super T> collection) { return collection.removeAll(source); } }; } /** * Returns a function that retains only elements contained in the argument collection in the * collection specified. The function returns {@code true} if the collection specified * changed as a result of call * @param collection the collection in which elements will be retained/removed * @param <T> the element type * @return the function as described * @see Collection#retainAll(Collection) * @see #retainAll(Collection) */ @SuppressWarnings({"unused"}) public static <T> $.Predicate<Collection<? extends T>> retainAllIn(final Collection<? super T> collection) { return new $.Predicate<Collection<? extends T>>() { @Override public boolean test(Collection<? extends T> theCollection) { return collection.retainAll(theCollection); } }; } /** * Returns a function that retains only elements contained in the specified collection in * the argument collection. The function returns {@code true} if argument collection changes * as a result of the call * @param collection the collection in which elements will be used to check if argument collection * element shall be retained or not * @param <T> the element type * @return the function as described above * @see Collection#retainAll(Collection) * @see #retainAllIn(Collection) */ @SuppressWarnings({"unused"}) public static <T> $.Predicate<Collection<? super T>> retainAll(final Collection<? extends T> collection) { return new $.Predicate<Collection<? super T>>() { @Override public boolean test(Collection<? super T> theCollection) { return theCollection.retainAll(collection); } }; } /** * Returns a function that prepend an element to a deque specified and return the * deque instance * @param deque the deque to which the element argument will be prepend to * @param <T> the element type * @return the function as described * @see Deque#addFirst(Object) * @see #dequePrepend(Object) */ @SuppressWarnings({"unused"}) public static <T> $.F1<T, Deque<? super T>> prependTo(final Deque<? super T> deque) { return new $.F1<T, Deque<? super T>>() { @Override public Deque<? super T> apply(T t) throws NotAppliedException, $.Break { deque.addFirst(t); return deque; } }; } /** * Returns a function that prepend specified element to argument deque * @param element the element to be added to the head of the argument (deque type) * @param <T> the element type * @return the function as described * @see Deque#addFirst(Object) * @see #prependTo(Deque) */ @SuppressWarnings("unused") public static <T> $.Processor<Deque<? super T>> dequePrepend(final T element) { return new $.Processor<Deque<? super T>>() { @Override public void process(Deque<? super T> deque) throws Osgl.Break, NotAppliedException { deque.addFirst(element); } }; } /** * Returns a function that append the argument to a {@link Deque} specified * @param deque the deque to which the argument shall be append when applying the function returned * @param <T> the generic type of the argument/deque element * @return the function that do the append operation * @see Deque#add(Object) * @see #dequeAppend(Object) */ @SuppressWarnings("unused") public static <T> $.F1<T, Deque<? super T>> appendTo(final Deque<? super T> deque) { return new $.F1<T, Deque<? super T>>() { @Override public Deque<? super T> apply(T t) throws NotAppliedException, $.Break { deque.addLast(t); return deque; } }; } /** * Returns a function that append specified element to argument deque * @param element the element to be added to the tail of the argument (deque type) * @param <T> the element type * @return the function as described * @see Deque#add(Object) * @see #appendTo(Deque) */ @SuppressWarnings("unused") public static <T> $.Processor<Deque<? super T>> dequeAppend(final T element) { return new $.Processor<Deque<? super T>>() { @Override public void process(Deque<? super T> deque) throws Osgl.Break, NotAppliedException { deque.add(element); } }; } /** * Returns a function that prepend the argument to a {@link Sequence} specified * @param sequence the sequence to which the argument shall be prepend whene applying the function * @param <T> the generic type of the argument/sequence element * @return the function that do the prepend operation * @see Sequence#prepend(Object) * @see #sequencePrepend(Object) */ @SuppressWarnings("unused") public static <T> $.F1<T, Sequence<? super T>> prependTo(final Sequence<? super T> sequence) { return new $.F1<T, Sequence<? super T>>() { @Override public Sequence<? super T> apply(T t) throws NotAppliedException, $.Break { sequence.prepend(t); return sequence; } }; } /** * Returns a function that preppend specified element to argument sequence * @param element the element to be added to the head of the argument (sequence type) * @param <T> the element type * @return the function as described * @see Sequence#prepend(Object) * @see #prependTo(Sequence) */ @SuppressWarnings("unused") public static <T> $.Processor<Sequence<? super T>> sequencePrepend(final T element) { return new Osgl.Processor<Sequence<? super T>>() { @Override public void process(Sequence<? super T> sequence) throws Osgl.Break, NotAppliedException { sequence.prepend(element); } }; } /** * Returns a function that append the argument to a {@link Sequence} specified * <p><b>Note</b> the function returns the sequence with the argument been removed</p> * @param sequence the sequence to which the argument shall be append when applying the function * @param <T> the generic type of the argument/sequence element * @return the function that do the append operation * @see Sequence#append(Iterable) * @see #sequenceAppend(Object) */ @SuppressWarnings("unused") public static <T> $.F1<T, Sequence<? super T>> appendTo(final Sequence<? super T> sequence) { return new $.F1<T, Sequence<? super T>>() { @Override public Sequence<? super T> apply(T t) throws NotAppliedException, $.Break { sequence.append(t); return sequence; } }; } /** * Returns a function that append specified element to argument sequence * @param element the element to be added to the tail of the argument (sequence type) * @param <T> the element type * @return the function as described * @see Sequence#append(Iterable) * @see #appendTo(Sequence) */ @SuppressWarnings("unused") public static <T> $.Processor<Sequence<? super T>> sequenceAppend(final T element) { return new Osgl.Processor<Sequence<? super T>>() { @Override public void process(Sequence<? super T> sequence) throws Osgl.Break, NotAppliedException { sequence.append(element); } }; } /** * Returns a function that apply the visitor function specified on the argument (iterable) * @param visitor the function to be used to loop through the argument * @param <T> the element type * @return the function as described * @see C#forEach(Iterable, Osgl.Function) */ @SuppressWarnings("unused") public static <T> $.F1<Iterable<? extends T>, Void> forEachIterable(final $.Function<? super T, ?> visitor) { return new $.F1<Iterable<? extends T>, Void>() { @Override public Void apply(Iterable<? extends T> iterable) throws NotAppliedException, $.Break { C.forEach(iterable, visitor); return null; } }; } } }