All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.osgl.util.C Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2013 The Java Tool project
 * Gelin Luo 
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/
package org.osgl.util;

/*-
 * #%L
 * Java Tool
 * %%
 * Copyright (C) 2014 - 2017 OSGL (Open Source General Library)
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import static org.osgl.Lang.Visitor;

import org.osgl.$;
import org.osgl.Lang;
import org.osgl.Lang.Func2;
import org.osgl.Lang.IndexedVisitor;
import org.osgl.exception.NotAppliedException;
import org.osgl.exception.ReadOnlyException;
import org.osgl.util.algo.Algorithms;

import java.io.IOException;
import java.io.Serializable;
import java.util.*;

/**
 * The namespace for OSGL collection utilities
 * Alias of {@link CollectionUtil}
 */
public class C {

    C() {
    }

    /**
     * The character enum for a data structure
     */
    public enum Feature {
        /**
         * Indicate whether a structure is immutable
         */
        IMMUTABLE,

        /**
         * Indicate the client cannot modify the structure.
         * However a readonly structure might not be immutable.
         * For example a view of a backing structure is readonly
         * while the backing structure is immutable
         */
        READONLY,

        /**
         * Indicate whether a list structure support random access
         */
        RANDOM_ACCESS,

        /**
         * Indicate whether the structure is limited
         */
        LIMITED,

        /**
         * Indicate whether the structure supports lazy evaluation
         */
        LAZY,

        /**
         * Indicate whether the structure support parallel operation
         */
        PARALLEL,

        /**
         * Indicate whether this structure is ordered. E.g. a
         * {@link List} and {@link java.util.LinkedHashSet} is ordered
         * structure, while {@link java.util.HashSet} might not be
         * ordered
         */
        ORDERED,

        /**
         * Indicate whether this structure is sorted
         */
        SORTED
    }

    /**
     * Define a type that holds a set of {@link org.osgl.util.C.Feature}
     */
    public interface Featured {
        /**
         * Get all characteristics in {@link EnumSet}
         *
         * @return an {@code EnumSet} of all characteristics hold by this object
         * @since 0.2
         */
        EnumSet features();

        /**
         * Check if this object has a certain {@link org.osgl.util.C.Feature}
         *
         * @param c the characteristic to be tested
         * @return {@code true} if this object has the characteristic, or {@code false} otherwise
         * @since 0.2
         */
        boolean is(Feature c);

        @SuppressWarnings("unused")
        class Factory {
            public static Featured identity(final EnumSet predefined) {
                return new Featured() {
                    @Override
                    public EnumSet features() {
                        return predefined;
                    }

                    @Override
                    public boolean is(Feature c) {
                        return predefined.contains(c);
                    }
                };
            }
        }
    }

    /**
     * Define a traversable structure with functional programming support,
     * including map, reduce etc.
     *
     * @param  The element type
     */
    public interface Traversable extends Iterable, Featured {

        /**
         * Returns this traversable and try to turn on
         * {@link C.Feature#PARALLEL}. If this traversable does not
         * support {@link org.osgl.util.C.Feature#PARALLEL} then
         * return this traversable directly without any state change
         *
         * @return this reference with parallel turned on if parallel
         * is supported
         */
        Traversable parallel();

        /**
         * Returns this traversable and turn off
         * {@link C.Feature#PARALLEL}
         *
         * @return this reference with parallel turned off
         */
        Traversable sequential();

        /**
         * Returns this traversable and try to turn on {@link C.Feature#LAZY}.
         * If lazy is not supported then return this traversable directly without
         * any state change
         *
         * @return this reference with lazy turned on if it is supported
         */
        Traversable lazy();

        /**
         * Returns this traversable and turn off {@link C.Feature#LAZY}
         *
         * @return this reference with lazy turned off
         */
        Traversable eager();

        /**
         * Is this traversal empty?
         *
         * @return {@code true} if the traversal is empty or {@code false} otherwise
         * @since 0.2
         */
        boolean isEmpty();

        /**
         * Return the size of this traversal
         *
         * @return the size of the structure
         * @throws UnsupportedOperationException if this structure does not support this method
         * @since 0.2
         */
        int size() throws UnsupportedOperationException;


        /**
         * Returns an new traversable with a mapper function specified. The element in the new traversal is the result of the
         * mapper function applied to this traversal element.
         * 
         *     Traversable traversable = C.list(23, _.NONE, null);
         *     assertEquals(C.list(true, false, false), traversal.map(_.F.NOT_NULL));
         *     assertEquals(C.list("23", "", ""), traversal.map(_.F.AS_STRING));
         * 
*

For Lazy Traversable, it must use lazy evaluation for this method. * Otherwise it is up to implementation to decide whether use lazy * evaluation or not

* * @param mapper the function that applied to element in this traversal and returns element in the result traversal * @param the element type of the new traversal * @return the new traversal contains results of the mapper function applied to this traversal * @since 0.2 */ Traversable map($.Function mapper); /** * Returns a traversable consisting of the results of replacing each element of this * stream with the contents of the iterable produced by applying the provided mapping * function to each element. If the result of the mapping function is {@code null}, * this is treated as if the result is an empty traversable. * * @param mapper the function produce an iterable when applied to an element * @param the element type of the the new traversable * @return the new traversable * @since 0.2 */ Traversable flatMap($.Function> mapper); Traversable collect(String path); /** * Returns an new traversable that contains all elements in the current traversable * except that does not pass the test of the filter function specified. *
         *     Traversable traversable = C.list(-1, 0, 1, -3, 7);
         *     Traversable filtered = traversable.filter(_.F.gt(0));
         *     assertTrue(filtered.contains(1));
         *     assertFalse(filtered.contains(-3));
         * 
* * @param predicate the function that test if the element in the traversable should be * kept in the resulting traversable. When applying the filter function * to the element, if the result is {@code true} then the element will * be kept in the resulting traversable. * @return the new traversable consists of elements passed the filter function test * @since 0.2 */ Traversable filter($.Function predicate); /** * Performs a reduction on the elements in this traversable, using the provided * identity and accumulating function. This might be equivalent to: *
         *      R result = identity;
         *      for (T element: this traversable) {
         *          result = accumulator.apply(result, element);
         *      }
         *      return result;
         * 
*

The above shows a typical left side reduce. However depending on the * implementation, it might choose another way to do the reduction, including * reduction in a parallel way

* * @param identity the identity value for the accumulating function * @param accumulator the function the combine two values * @param the type of identity and the return value * @return the result of reduction * @since 0.2 */ R reduce(R identity, Func2 accumulator); /** * Performs a reduction on the elements in this traversable, using provided accumulating * function. This might be equivalent to: *
         *      boolean found = false;
         *      T result = null;
         *      for (T element: this traversable) {
         *          if (found) {
         *              result = accumulator.apply(result, element);
         *          } else {
         *              found = true;
         *              result = element;
         *          }
         *      }
         *      return found ? _.some(result) : _.none();
         * 
*

The above shows a typical left side reduction. However depending on the * implementation, it might choose another way to do the reduction, including * reduction in a parallel way

* * @param accumulator the function takes previous accumulating * result and the current element being * iterated * @return an option describing the accumulating result or {@link Lang#none()} if * the structure is empty * @since 0.2 */ $.Option reduce(Func2 accumulator); /** * Check if all elements match the predicate specified * * @param predicate the function to test the element * @return {@code true} if all elements match the predicate * @since 0.2 */ boolean allMatch($.Function 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 predicate); /** * Check if no elements matches the predicate specified. This should be * equivalent to: *
         *      this.allMatch(_.F.negate(predicate));
         * 
* * @param predicate the function to test the element * @return {@code true} if none element matches the predicate * @since 0.2 */ boolean noneMatch($.Function predicate); /** * Returns an element that matches the predicate specified. The interface * does not indicate if it should be the first element matches the predicate * be returned or in case of parallel computing, whatever element matches * found first is returned. It's all up to the implementation to refine the * semantic of this method * * @param predicate the function map element to Boolean * @return an element in this traversal that matches the predicate or * {@link Lang#NONE} if no element matches * @since 0.2 */ $.Option findOne($.Function predicate); /** * Iterate this {@code Traversable} with a visitor function. This method * does not specify the approach to iterate through this structure. The * implementation might choose iterate from left to right, or vice versa. * It might even choose to split the structure into multiple parts, and * iterate through them in parallel * * @param visitor a function that apply to element in this * {@code Traversable}. The return value * of the function is ignored * @return this {@code Traversable} instance for chained call * @since 0.2 */ Traversable accept(Lang.Visitor visitor); /** * Alias of {@link #accept(Lang.Visitor)} * @param visitor the visitor to tranverse the elements * @return this {@code Traversable} instance */ Traversable each($.Visitor visitor); /** * Alias of {@link #accept(Lang.Visitor)} * @param visitor the visitor function * @return this {@code Traversable} instance */ Traversable forEach($.Visitor visitor); } public interface Sequence extends Traversable { /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is set * * @return this reference with parallel turned on */ Sequence parallel(); /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is unset * * @return this reference with parallel turned off */ Sequence sequential(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is set * * @return this reference with lazy turned on */ Sequence lazy(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is unset * * @return this reference with lazy turned off */ Sequence eager(); /** * Alias of {@link #head()} * * @return the first element in the sequence * @since 0.2 */ T first() throws NoSuchElementException; /** * Returns an {@link Lang.Option} of the first element in the * {@code Sequence} * * @return the first element from the {@code Sequence} * @throws NoSuchElementException if the {@code Sequence} is empty * @see #tail() * @see #first() * @since 0.2 */ T head() throws NoSuchElementException; /** * Alias of {@link #take(int)} * * @param n the number of elements to be taken into the return sequence * @return the first {@code n} element in the sequence * @since 0.2 */ Sequence head(int n); /** * Returns the rest part of the {@code Sequence} except the first element * * @return a {@code Sequence} without the first element * @throws UnsupportedOperationException if the {@code Sequence} is empty * @see #head() * @see ReversibleSequence#tail(int) * @since 0.2 */ Sequence tail() throws UnsupportedOperationException; /** * Returns a {@code Sequence} consisting the first {@code n} elements from this {@code Sequence} if * number {@code n} is positive and the {@code Sequence} contains more than {@code n} elements *

If this {@code Sequence} contains less than {@code n} elements, then a {@code Sequence} consisting * the whole elements of this {@code Sequence} is returned. Note it might return this {@code Sequence} * itself if the {@code Sequence} is immutable.

*

If the number {@code n} is zero, then an empty {@code Sequence} is returned in reverse * order

*

If the number {@code n} is negative, then the last {@code -n} elements from this * {@code Sequence} is returned in an new {@code Sequence}, or throw {@link UnsupportedOperationException} * if this operation is not supported

*
         *     Sequence seq = C.list(1, 2, 3, 4);
         *     assertEquals(C.list(1, 2), seq.take(2));
         *     assertEquals(C.list(1, 2, 3, 4), seq.take(100));
         *     assertEquals(C.list(), seq.take(0));
         *     assertEquals(C.list(3, 4), seq.take(-2));
         *     assertEquals(C.list(1, 2, 3, 4), seq.take(-200));
         * 
* * @param n specify the number of elements to be taken from the head of this {@code Sequence} * @return a {@code Sequence} consisting of the first {@code n} elements of this {@code Sequence} * @see #head(int) * @since 0.2 */ Sequence take(int n); /** * Returns an new {@code Sequence} that takes the head of this {@code Sequence} until the predicate * evaluate to {@code false}: *
         *     C.Sequence seq = C.list(1, 2, 3, 4, 5, 4, 3, 2, 1);
         *     assertEquals(C.list(C.list(1, 2, 3), seq.takeWhile(_.F.lt(4)));
         *     assertEquals(C.list(C.list(1, 2, 3, 3, 2, 1), seq.filter(_.F.lt(4)));
         * 
* * @param predicate specify which the elements in this {@code Sequence} will put into the new * {@code Sequence} * @return the new {@code Sequence} * @since 0.2 */ Sequence takeWhile($.Function predicate); /** * Returns a {@code Sequence} consisting of the elements from this {@code Sequence} except the first {@code n} * if number {@code n} is positive and the {@code Sequence} contains more than {@code n} elements *

If this {@code Sequence} contains less than {@code n} elements, then an empty {@code Sequence} * is returned

*

If the number {@code n} is zero, then a copy of this {@code Sequence} or this {@code Sequence} * itself is returned depending on the implementation

*

If the number {@code n} is negative, then either {@link IllegalArgumentException} should * be thrown out if this sequence is not {@link org.osgl.util.C.Feature#LIMITED} or it drop * {@code -n} element starts from the tail side

*
         *     C.Sequence seq = C.list(1, 2, 3, 4, 5);
         *     assertEquals(C.list(3, 4, 5), seq.drop(2));
         *     assertEquals(C.list(1, 2, 3, 4, 5), seq.drop(0));
         *     assertEquals(C.list(), seq.drop(100));
         * 
*

Note this method does NOT modify the current sequence, instead it returns an new sequence structure * containing the elements as required

* * @param n specify the number of elements to be taken from the head of this {@code Sequence} * must not less than 0 * @return a {@code Sequence} consisting of the elements of this {@code Sequence} except the first {@code n} ones * @since 0.2 */ Sequence drop(int n) throws IllegalArgumentException; /** * Returns a {@code Sequence} consisting of the elements from this sequence with leading elements * dropped until the predicate returns {@code true} *
         *      Sequence seq = C.list(1, 2, 3, 4, 3, 2, 1);
         *      assertTrue(C.list(), seq.dropWhile(_.F.gt(100)));
         *      assertTrue(C.list(4, 3, 2, 1), seq.dropWhile(_.F.lt(3)));
         * 
*

Note this method does NOT modify the current sequence, instead it returns an new sequence structure * containing the elements as required

* * @param predicate the function that check if drop operation should stop * @return the sequence after applying the drop operations * @since 0.2 */ Sequence dropWhile($.Function predicate); /** * Returns a sequence consists of all elements of this sequence * followed by all elements of the specified iterable. *

An {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might append specified seq to {@code this} sequence instance * directly

* * @param iterable the iterable in which elements will be append to this sequence * @return the sequence after append the iterable */ Sequence append(Iterable iterable); /** * Returns a sequence consists of all elements of this sequence * followed by all elements of the specified sequence. *

An {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might append specified seq to {@code this} sequence instance * directly

* * @param seq the sequence to be appended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence append(Sequence seq); /** * Returns a sequence consists of all elements of this sequence * followed by all elements of the specified iterator. *

An {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might append specified seq to {@code this} sequence instance * directly

* * @param iterator the iterator in which elements will be append to the returned sequence * @return a sequence consists of elements of this sequence and the elements in the iterator * @since 0.9 */ Sequence append(Iterator iterator); /** * Returns a sequence consists of all elements of this sequence * followed by all elements of the specified enumeration. *

An {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might append specified seq to {@code this} sequence instance * directly

* * @param enumeration the enumeration in which elements will be append to the returned sequence * @return a sequence consists of elements of this sequence and the elements in the iterator * @since 0.9 */ Sequence append(Enumeration enumeration); /** * Returns a sequence consists of all elements of this sequence * followed by the element specified. *

an {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might append the element to {@code this} sequence instance * directly

* * @param t the element to be appended to this sequence * @return a sequence consists of elements of this sequence * and the element {@code t} * @since 0.2 */ Sequence append(T t); /** * Returns a sequence consists of all elements of the iterable specified * followed by all elements of this sequence *

An {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might prepend specified seq to {@code this} sequence instance * directly

* * @param iterable the iterable to be prepended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence prepend(Iterable iterable); /** * Returns a sequence consists of all elements of the iterator specified * followed by all elements of this sequence *

An {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might prepend specified seq to {@code this} sequence instance * directly

* * @param iterator the iterator to be prepended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence prepend(Iterator iterator); /** * Returns a sequence consists of all elements of the enumeration specified * followed by all elements of this sequence *

An {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might prepend specified seq to {@code this} sequence instance * directly

* * @param enumeration the enumeration to be prepended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence prepend(Enumeration enumeration); /** * Returns a sequence consists of all elements of the sequence specified * followed by all elements of this sequence *

An {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might prepend specified seq to {@code this} sequence instance * directly

* * @param seq the sequence to be prepended * @return a sequence consists of elements of both sequences * @since 0.2 */ Sequence prepend(Sequence seq); /** * Returns a sequence consists of the element specified followed by * all elements of this sequence. *

an {@link C.Feature#IMMUTABLE immutable} Sequence must * return an new Sequence; while a mutable Sequence implementation * might append the element to {@code this} sequence instance * directly

* * @param t the element to be appended to this sequence * @return the sequence consists of {@code t} followed * by all elements in this sequence * @since 0.2 */ Sequence prepend(T t); /** * Returns a List contains all the elements in this sequence with the same order. * @return the list as described above */ List asList(); /** * {@inheritDoc} * * @param mapper {@inheritDoc} * @param {@inheritDoc} * @return a Sequence of {@code R} that are mapped from this sequence * @since 0.2 */ @Override Sequence map($.Function mapper); /** * {@inheritDoc} * * @param mapper {@inheritDoc} * @param {@inheritDoc} * @return a Sequence of {@code R} type element that are mapped from this sequences * @since 0.2 */ @Override Sequence flatMap($.Function> mapper); @Override Sequence collect(String path); /** * {@inheritDoc} * * @param predicate {@inheritDoc} * @return An new {@code Sequence} consists of elements that passed the predicate * @since 0.2 */ @Override Sequence filter(final $.Function predicate); /** * {@inheritDoc} * This method does not specify how to run the accumulator. It might be * {@link C.Sequence#reduceLeft(Object, Func2)} or * {@link ReversibleSequence#reduceRight(Object, Func2)}, or * even run reduction in parallel, it all depending on the implementation. *

For a guaranteed reduce from left to right, use * {@link C.Sequence#reduceLeft(Object, Func2)} instead

* * @param identity {@inheritDoc} * @param accumulator {@inheritDoc} * @param {@inheritDoc} * @return {@inheritDoc} * @since 0.2 */ @Override R reduce(R identity, Func2 accumulator); /** * Run reduction from header side. This is equivalent to: *
         *      R result = identity;
         *      for (T element: this sequence) {
         *          result = accumulator.apply(result, element);
         *      }
         *      return result;
         * 
* * @param identity the identity value for the accumulating function * @param accumulator the function to accumulate two values * @param the aggregation result type * @return the reduced result * @since 0.2 */ R reduceLeft(R identity, Func2 accumulator); /** * {@inheritDoc} * This method does not specify the approach to run reduction. * For a guaranteed reduction from head to tail, use * {@link #reduceLeft(Func2)} instead * * @param accumulator {@inheritDoc} * @return {@inheritDoc} * @since 0.2 */ @Override $.Option reduce(Func2 accumulator); /** * Run reduction from head to tail. This is equivalent to *
         *      if (isEmpty()) {
         *          return _.none();
         *      }
         *      T result = head();
         *      for (T element: this traversable.tail()) {
         *          result = accumulator.apply(result, element);
         *      }
         *      return _.some(result);
         * 
* * @param accumulator the function accumulate each element to the final result * @return an {@link Lang.Option} describing the accumulating result * @since 0.2 */ $.Option reduceLeft(Func2 accumulator); /** * Apply the predicate specified to the element of this sequence * from head to tail. Stop at the element that returns {@code true}, * and returns an {@link Lang.Option} describing the element. If none * of the element applications in the sequence returns {@code true} * then {@link Lang#none()} is returned * * @param predicate the function map the element to Boolean * @return an option describe the first element matches the * predicate or {@link Lang#none()} * @since 0.2 */ $.Option findFirst($.Function predicate); Sequence accept($.Visitor visitor); Sequence each($.Visitor visitor); Sequence forEach($.Visitor visitor); /** * Iterate through this sequence from head to tail with * the visitor function specified * * @param visitor the function to visit elements in this sequence * @return this sequence * @see Traversable#accept(Lang.Visitor) * @see ReversibleSequence#acceptRight(Lang.Visitor) * @since 0.2 */ Sequence acceptLeft($.Visitor visitor); /** * Returns a sequence formed from this sequence and another iterable * collection by combining corresponding elements in pairs. * If one of the two collections is longer than the other, * its remaining elements are ignored. * * @param iterable the part B to be zipped with this sequence * @param the type of the iterable * @return a new sequence containing pairs consisting of * corresponding elements of this sequence and that. * The length of the returned collection is the * minimum of the lengths of this sequence and that. */ Sequence> zip(Iterable iterable); /** * Returns a sequence formed from this sequence and another iterable * collection by combining corresponding elements in pairs. * If one of the two collections is longer than the other, * placeholder elements are used to extend the shorter collection * to the length of the longer. * * @param iterable the part B to be zipped with this sequence * @param the type of the iterable * @param def1 the element to be used to fill up the result if * this sequence is shorter than that iterable * @param def2 the element to be used to fill up the result if * the iterable is shorter than this sequence * @return a new sequence containing pairs consisting of * corresponding elements of this sequence and that. * The length of the returned collection is the * maximum of the lengths of this sequence and that. */ Sequence> zipAll(Iterable iterable, T def1, T2 def2); /** * Zip this sequence with its indices * * @return A new list containing pairs consisting of all * elements of this list paired with their index. * Indices start at 0. */ @SuppressWarnings("unused") Sequence> zipWithIndex(); /** * Count the element occurence in this sequence * @param t the element * @return the number of times the element be presented in this sequence */ int count(T t); } /** * A bidirectional sequence which can be iterated from tail to head * * @param the element type */ public interface ReversibleSequence extends Sequence { /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is set * * @return this reference with parallel turned on */ ReversibleSequence parallel(); /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is unset * * @return this reference with parallel turned off */ ReversibleSequence sequential(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is set * * @return this reference with lazy turned on */ ReversibleSequence lazy(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is unset * * @return this reference with lazy turned off */ ReversibleSequence eager(); /** * {@inheritDoc} * * @param n {@inheritDoc} * @return an new reversible sequence contains the first * {@code n} elements in this sequence */ @Override ReversibleSequence head(int n); /** * {@inheritDoc} * * @return an new reversible sequence contains all elements * in this sequence except the first element */ @Override ReversibleSequence tail(); /** * {@inheritDoc} * * @param n {@inheritDoc} * @return an new reversible sequence contains the first * {@code n} elements in this sequence */ @Override ReversibleSequence take(int n); /** * {@inheritDoc} * * @param predicate {@inheritDoc} * @return an new reversible sequence contains the elements * in this sequence until predicate evaluate to false */ @Override ReversibleSequence takeWhile($.Function predicate); /** * {@inheritDoc} * * @param n specify the number of elements to be taken from the head of this {@code Sequence} or * the {@code -n} number of elements to be taken from the tail of this sequence if n is * an negative number * @return a reversible sequence without the first {@code n} number of elements */ @Override ReversibleSequence drop(int n); @Override ReversibleSequence dropWhile($.Function predicate); @Override ReversibleSequence filter($.Function predicate); /** * {@inheritDoc} * * @param t {@inheritDoc} * @return a reversible sequence contains this seq's element * followed by {@code t} */ @Override ReversibleSequence append(T t); /** * Returns an new reversible sequence contains all elements * in this sequence followed by all elements in the specified * reverse sequence * * @param seq another reversible sequence * @return an new reversible sequence contains both seq's elements */ ReversibleSequence append(ReversibleSequence seq); /** * {@inheritDoc} * * @param t {@inheritDoc} * @return a reversible sequence contains by {@code t} * followed this seq's element */ @Override ReversibleSequence prepend(T t); /** * Returns an new reversible sequence contains all elements * in specified reversible sequence followed by all elements * in this sequence * * @param seq another reversible sequence * @return an new reversible sequence contains both seq's elements */ ReversibleSequence prepend(ReversibleSequence seq); /** * Returns the last element from this {@code Sequence} * * @return the last element * @throws UnsupportedOperationException if this {@code Sequence} is not limited * @throws NoSuchElementException if the {@code Sequence} is empty * @see #isEmpty() * @see org.osgl.util.C.Feature#LIMITED * @see #is(org.osgl.util.C.Feature) * @since 0.2 */ T last() throws UnsupportedOperationException, NoSuchElementException; /** * Returns a {@code Sequence} consisting the last {@code n} elements from this {@code Sequence} * if number {@code n} is positive and the {@code Sequence} contains more than {@code n} elements *

If this {@code Sequence} contains less than {@code n} elements, then a {@code Sequence} consisting * the whole elements of this {@code Sequence} is returned. Note it might return this {@code Sequence} * itself if the {@code Sequence} is immutable.

*

If the number {@code n} is zero, then an empty {@code Sequence} is returned in reverse * order

*

If the number {@code n} is negative, then the first {@code -n} elements from this * {@code Sequence} is returned in an new {@code Sequence}

*
         *     Sequence seq = C1.list(1, 2, 3, 4);
         *     assertEquals(C1.list(3, 4), seq.tail(2));
         *     assertEquals(C1.list(1, 2, 3, 4), seq.tail(100));
         *     assertEquals(C1.list(), seq.tail(0));
         *     assertEquals(C1.list(1, 2, 3), seq.tail(-3));
         *     assertEquals(C1.list(1, 2, 3, 4), seq.tail(-200));
         * 
*

This method does not mutate the underline container

* * @param n specify the number of elements to be taken from the tail of this {@code Sequence} * @return a {@code Sequence} consisting of the last {@code n} elements from this {@code Sequence} * @throws UnsupportedOperationException if the traversal is unlimited or empty * @throws IndexOutOfBoundsException if {@code n} is greater than the size of this {@code Sequence} * @see org.osgl.util.C.Feature#LIMITED * @see #is(org.osgl.util.C.Feature) * @since 0.2 */ ReversibleSequence tail(int n) throws UnsupportedOperationException, IndexOutOfBoundsException; /** * Returns an new {@code Sequence} that reverse this {@code Sequence}. * * @return a reversed {@code Sequence} * @throws UnsupportedOperationException if this {@code Sequence} is unlimited * @see org.osgl.util.C.Feature#LIMITED * @see #is(org.osgl.util.C.Feature) * @since 0.2 */ ReversibleSequence reverse() throws UnsupportedOperationException; /** * Returns an {@link Iterator} iterate the sequence from tail to head * * @return the iterator * @since 0.2 */ Iterator reverseIterator(); /** * Run reduction from tail side. This is equivalent to: *
         *      R result = identity;
         *      for (T element: this sequence.reverse()) {
         *          result = accumulator.apply(result, element);
         *      }
         *      return result;
         * 
* * @param identity the initial value * @param accumulator the function performs accumulation from {@code T} an {@code R} to anthoer {@code R} * @param the accumulation result * @return the aggregation result * @see #reduce(Object, Func2) * @since 0.2 */ R reduceRight(R identity, Func2 accumulator); /** * Run reduction from tail to head. This is equivalent to *
         *      if (isEmpty()) {
         *          return _.none();
         *      }
         *      T result = last();
         *      for (T element: this sequence.reverse.tail()) {
         *          result = accumulator.apply(result, element);
         *      }
         *      return _.some(result);
         * 
* * @param accumulator the function accumulate each element to the final result * @return an {@link Lang.Option} describing the accumulating result * @since 0.2 */ $.Option reduceRight(Func2 accumulator); /** * Apply the predicate specified to the element of this sequence * from tail to head. Stop at the element that returns {@code true}, * and returns an {@link Lang.Option} describing the element. If none * of the element applications in the sequence returns {@code true} * then {@link Lang#none()} is returned * * @param predicate the function map the element to Boolean * @return an option describe the first element matches the * predicate or {@link Lang#none()} * @since 0.2 */ $.Option findLast($.Function predicate); @Override ReversibleSequence map($.Function mapper); /** * {@inheritDoc} * * @param mapper {@inheritDoc} * @param {@inheritDoc} * @return a ReversibleSequence of {@code R} type element that are mapped from this sequences * @since 0.2 */ @Override ReversibleSequence flatMap($.Function> mapper); ReversibleSequence accept($.Visitor visitor); ReversibleSequence each($.Visitor visitor); ReversibleSequence forEach($.Visitor visitor); ReversibleSequence acceptLeft($.Visitor visitor); /** * Iterate through this sequence from tail to head with the visitor function * specified * * @param visitor the function to visit elements in this sequence * @return this sequence * @see Traversable#accept(Lang.Visitor) * @see Sequence#acceptLeft(Lang.Visitor) * @since 0.2 */ ReversibleSequence acceptRight($.Visitor visitor); C.ReversibleSequence<$.Binary> zip(C.ReversibleSequence rseq); @SuppressWarnings("unused") C.ReversibleSequence<$.Binary> zipAll(C.ReversibleSequence rseq, T def1, T2 def2); } public static class Array extends ReversibleSeqBase implements ReversibleSequence { @Override public Array lazy() { super.lazy(); return this; } @Override public Array eager() { super.eager(); return this; } @Override public Array parallel() { super.parallel(); return this; } @Override public Array sequential() { super.sequential(); return this; } T[] data; Array(T[] data) { E.NPE(data); this.data = data; } @Override public int size() throws UnsupportedOperationException { return data.length; } public boolean isEmpty() { return 0 == size(); } public boolean isNotEmpty() { return 0 < size(); } public T get(int idx) { return data[idx]; } public Array set(int idx, T val) { data[idx] = val; return this; } @Override public Iterator iterator() { final int size = size(); return new ReadOnlyIterator() { int cursor = 0; @Override public boolean hasNext() { return cursor < size; } @Override public T next() { if (cursor >= size) { throw new NoSuchElementException(); } return data[cursor++]; } }; } @Override public Iterator reverseIterator() { final int size = size(); return new ReadOnlyIterator() { int cursor = size - 1; @Override public boolean hasNext() { return cursor < 0; } @Override public T next() { if (cursor < 0) { throw new NoSuchElementException(); } return data[cursor--]; } }; } @Override @SuppressWarnings("unchecked") public ReversibleSequence reverse() throws UnsupportedOperationException { if (isLazy()) { return ReversedRSeq.of(this); } if (isMutable()) { Algorithms.arrayReverseInplace().reverse(data, 0, data.length); return this; } T[] newData = (T[]) Algorithms.ARRAY_REVERSE.apply(data, 0, data.length); return of(newData); } @Override public C.List asList() { return C.listOf(data); } public C.List asNewList() { return C.newListOf(data); } public static Array of(T[] data) { return new Array<>(data); } public static Array copyOf(T[] data) { int len = data.length; T[] newData = $.newArray(data, len); System.arraycopy(data, 0, newData, 0, len); return new Array<>(newData); } } /** * Define a Range data structure which contains a discrete sequence of elements start from {@link #from()} * until {@link #to()}. The {@code from} element should be contained in the range, while the {@code to} * element should be exclusive from the range. While the {@code from} and {@code to} defines the boundary of * an range, the {@link #step()} defines how to step from one element to another in the range. * * @param the element type */ public interface Range extends Sequence { /** * Returns the {@code from} value (inclusive) in the range * * @return {@code from} * @since 0.2 */ ELEMENT from(); /** * Returns the {@code to} value (exclusive) of the range * * @return {@code to} * @since 0.2 */ ELEMENT to(); /** * Check if an element is contained in this range * * @param element the element to be checked * @return {@code true} if the element specified is contained in the range * @since 0.2 */ boolean contains(ELEMENT element); /** * Check if this range contains all elements of another range of the same type (identified by * {@link #order()} and {@link #step()}). * * @param r2 the range to be tested * @return {@code true} if this range contains all elements of {@code r2} * @since 0.2 */ boolean containsAll(Range r2); /** * Returns a {@link Func2} function that takes two elements in the range domain and returns an integer to * determine the order of the two elements. See {@link java.util.Comparator#compare(Object, Object)} for * semantic of the function. *

If any one of the element applied is {@code null} the function should throw out * {@link NullPointerException}

* * @return a function implement the ordering logic * @since 0.2 */ Comparator order(); /** * Returns a {@link Func2} function that applied to an element in this {@code Range} and * an integer {@code n} indicate the number of steps. The result of the function is an element in * the range or the range domain after moving {@code n} steps based on the element. *

If the element apply is {@code null}, the function should throw out * {@link NullPointerException}; if the resulting element is not defined in the range * domain, the function should throw out {@link NoSuchElementException}

* * @return a function implement the stepping logic * @since 0.2 */ Func2 step(); /** * Returns an new range this range and another range {@code r2} merged together. The two ranges must have * the equal {@link #step()} and {@link #order()} operator to be merged, otherwise, * {@link org.osgl.exception.InvalidArgException} will be thrown out *

The two ranges must be either overlapped or immediately connected to each other as per * {@link #step()} definition. Otherwise an {@link org.osgl.exception.InvalidArgException} * will be throw out: *

    *
  • if one range contains another range entirely, then the larger range is returned
  • *
  • if the two ranges overlapped or immediately connected to each other, then an range * contains all elements of the two ranges will be returned
  • *
  • an {@link org.osgl.exception.InvalidArgException} will be thrown out if the two ranges does not connected * to each other
  • *
* * @param r2 the range to be merged with this range * @return an new range contains all elements in this range and r2 * @throws org.osgl.exception.InvalidArgException if the two ranges does not have * the same {@link #step()} operator or does not connect to each other * @since 0.2 */ Range merge(Range r2); ELEMENT last(); Range tail(int n); Range reverse(); Iterator reverseIterator(); @SuppressWarnings("unused") R reduceRight(R identity, Func2 accumulator); @SuppressWarnings("unused") $.Option reduceRight(Func2 accumulator); @SuppressWarnings("unused") $.Option findLast($.Function predicate); /** * {@inheritDoc} * * @param visitor {@inheritDoc} * @return this Range instance * @since 0.2 */ @Override Range accept($.Visitor visitor); @Override Range each($.Visitor visitor); @Override Range forEach($.Visitor visitor); /** * {@inheritDoc} * * @param visitor {@inheritDoc} * @return this Range instance * @since 0.2 */ @Override Range acceptLeft($.Visitor visitor); /** * iterate through the range from tail to head * * @param visitor a function to visit elements in the range * @return this Range instance * @since 0.2 */ @SuppressWarnings("unused") Range acceptRight($.Visitor visitor); } /** * The osgl List interface is a mixture of {@link java.util.List} and osgl {@link Sequence} * * @param the element type of the {@code List} * @since 0.2 */ public interface List extends java.util.List, ReversibleSequence { /** * A cursor points to an element of a {@link List}. It performs like * {@link java.util.ListIterator} but differs in the following way: *
    *
  • Add insert, append method
  • *
  • Support method chain calling style for most methods
  • *
  • A clear get() method to get the element the cursor point to
  • *
  • Unlike next/previous method, the new forward/backward method * returns a Cursor reference
  • *
* * @param */ interface Cursor { /** * Returns true if the cursor is not obsolete and points to an element * in the list * * @return true if this cursor is not obsolete and point to an element */ boolean isDefined(); /** * Returns the index of the element to which the cursor pointed * * @return the cursor index */ int index(); /** * Returns if the cursor can be moved forward to get the * next element * * @return {@code true} if there are element after the cursor in the * underline list */ boolean hasNext(); /** * Returns if the cursor can be moved backward to get the previous * element * * @return {@code true} if there are element before the cursor in the * underline list */ boolean hasPrevious(); /** * Move the cursor forward to make it point to the next element to * the current element * * @return the cursor points to the next element * @throws UnsupportedOperationException if cannot move forward anymore */ Cursor forward() throws UnsupportedOperationException; /** * Move the cursor backward to make it point to the previous element to * the current element * * @return the cursor points to the previous element * @throws UnsupportedOperationException if cannot move backward anymore */ Cursor backward() throws UnsupportedOperationException; /** * Park the cursor at the position before the first element. *

After calling this method, {@link #isDefined()} * shall return {@code false}

* * @return this cursor */ Cursor parkLeft(); /** * Park the cursor at the position after the last element *

After calling this method, {@link #isDefined()} * shall return {@code false}

* * @return this cursor */ Cursor parkRight(); /** * Returns the element this cursor points to. If the cursor isn't point * to any element, calling to this method will trigger * {@code NoSuchElementException} been thrown out. The only case * the cursor doesn't point to any element is when it is initialized * in which case the cursor index is -1 * * @return the current element * @throws NoSuchElementException if the cursor isn't point to any element */ T get() throws NoSuchElementException; /** * Replace the element this cursor points to with the new element specified. * * @param t the new element to be set to this cursor * @return the cursor itself * @throws IndexOutOfBoundsException if the cursor isn't point to any element * @throws NullPointerException if when passing null value to this method and * the underline list does not allow null value */ Cursor set(T t) throws IndexOutOfBoundsException, NullPointerException; /** * Remove the current element this cursor points to. After the element * is removed, the cursor points to the next element if there is next, * or if there isn't next element, the cursor points to the previous * element, or if there is previous element neither, then the cursor * points to {@code -1} position and the current element is not defined * * @return the cursor itself * @throws UnsupportedOperationException if the operation is not supported * by the underline container does not support removing elements * @throws NoSuchElementException if the cursor is parked either left or * right */ Cursor drop() throws NoSuchElementException, UnsupportedOperationException; /** * Add an element in front of the element this cursor points to. * After added, the cursor should still point to the current element * * @param t the element to be inserted * @return this cursor which is still pointing to the current element * @throws IndexOutOfBoundsException if the current element is undefined */ Cursor prepend(T t) throws IndexOutOfBoundsException; /** * Add an element after the element this cursor points to. * After added, the cursor should still point to the current element * * @param t the element to be added * @return this cursor which is still pointing to the current element */ Cursor append(T t); } /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is set * * @return this reference with parallel turned on */ @Override List parallel(); /** * Returns this traversable and make sure {@link C.Feature#PARALLEL} is unset * * @return this reference with parallel turned off */ @Override List sequential(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is set * * @return this reference with lazy turned on */ @Override List lazy(); /** * Returns this traversable and make sure {@link C.Feature#LAZY} is unset * * @return this reference with lazy turned off */ @Override List eager(); /** * Returns an immutable list contains all elements of the current list. * If the current list is immutable, then return the current list itself. * * @return an immutable list. * @see #readOnly() */ List snapshot(); /** * Returns a view of this list that is readonly. If the current list is * readonly or immutable then return the current list itself * * @return a readonly view of this list */ @SuppressWarnings("unused") List readOnly(); /** * Returns a mutable copy of this list * * @return a mutable list contains all elements of this list */ List copy(); /** * Returns a sorted copy of this list. *

Note if the element type T is not a {@link java.lang.Comparable} then * this method returns a {@link #copy() copy} of this list without any order * changes

* * @return a sorted copy of this list */ List sorted(); /** * Return a list that contains unique set of this list and keep the orders. If * this list doesn't have duplicated items, it could return this list directly * or choose to return an new copy of this list depends on the sub class * implementation * @return a list contains only unique elements in this list */ List unique(); /** * Return a list that contains unique set as per the comparator specified of * this list and keep the orders. If this list doesn't have duplicated items, * it could return this list directly or choose to return an new copy of this list * depends on the sub class implementation * @param comp the comparator check the duplicate elements * @return a list contains unique element as per the comparator */ List unique(Comparator comp); /** * Returns a sorted copy of this list. The order is specified by the comparator * provided * * @param comparator specify the order of elements in the result list * @return an ordered copy of this list */ List sorted(Comparator comparator); @Override List subList(int fromIndex, int toIndex); /** * Add all elements from an {@link Iterable} into this list. * Return {@code true} if the list has changed as a result of * call. *

Note if this list is immutable or readonly, {@code UnsupportedOperationException} * will be thrown out with this call

* @param iterable the iterable provides the elements to be * added into the list * @return {@code true} if this list changed as result of addd */ boolean addAll(Iterable iterable); /** * {@inheritDoc} * * @param n specify the number of elements to be included in the return list * @return A List contains first {@code n} items in this List */ @Override List head(int n); /** * {@inheritDoc} *

This method does not alter the underline list

* * @param n {@inheritDoc} * @return A list contains first {@code n} items in this list */ @Override List take(int n); /** * {@inheritDoc} * * @return A list contains all elements in this list except * the first one */ @Override List tail(); /** * {@inheritDoc} *

This method does not alter the underline list

* * @param n {@inheritDoc} * @return A list contains last {@code n} items in this list */ @Override List tail(int n); /** * {@inheritDoc} *

This method does not alter the underline list

* * @param n {@inheritDoc} * @return a List contains all elements of this list * except the first {@code n} number */ List drop(int n); /** * {@inheritDoc} *

This method does not alter the underline list

* * @param predicate the predicate function * @return {@inheritDoc} */ @Override List dropWhile($.Function predicate); /** * {@inheritDoc} *

This method does not alter the underline list

* * @param predicate {@inheritDoc} * @return {@inheritDoc} */ @Override List takeWhile($.Function predicate); /** * For mutable list, remove all element that matches the predicate * specified from this List and return this list once done. *

For immutable or readonly list, an new List contains all element from * this list that does not match the predicate specified is returned

* * @param predicate test whether an element should be removed frmo * return list * @return a list contains all element that does not match the * predicate specified */ List remove($.Function predicate); @Override C.List map($.Function mapper); /** * {@inheritDoc} * * @param mapper {@inheritDoc} * @param {@inheritDoc} * @return a List of {@code R} type element that are mapped from this sequences * @since 0.2 */ @Override List flatMap($.Function> mapper); @Override List collect(String path); @Override List filter($.Function predicate); /** * Split this list into two list based on the predicate specified. *

* The function use the predicate to test all elements in this list. If test passed * then it add the element into {@link Lang.T2#_1 left side list}, otherwise the * element will be added into {@link Lang.T2#_2 right side list}. The result * is returned as a {@link org.osgl.Lang.Tuple tuple} contains the left and * right side lift *

* @param predicate the function to test the elements in this list * @return a tuple of two lists */ $.T2, List> split($.Function predicate); /** * Find the first element in this list that matches the predicate. * Return a cursor point to the location of the element. If no * such element is found then a cursor that point to {@code -1} * is returned. * * @param predicate test the element * @return the reference to the list itself or an new List without the * first element matches the predicate if this is a readonly * list */ Cursor locateFirst($.Function predicate); /** * Locate any one element in the list that matches the predicate. * Returns the cursor point to the element found, or a cursor * that is not defined if no such element found in the list. In * a parallel locating the element been found might not be the * first element matches the predicate * * @param predicate the function that used to check the element * at the cursor * @return the reference to the list itself or an new List without * and element matches the predicate if this is a readonly * list */ Cursor locate($.Function predicate); /** * Locate the first element in this list that matches the predicate. * Return a cursor point to the location of the element. If no * such element is found then a cursor that point to {@code -1} * is returned. * * @param predicate test the element * @return the reference to the list itself or an new List without the * first element matches the predicate if this is a readonly * list */ Cursor locateLast($.Function predicate); /** * Insert an element at the position specified by {@code index}. *

If this list is readonly or immutable, then an new * list should be created with all elements in this list * and the new element inserted at the specified position. * The new list should have the same feature as this list

*

If index is less than zero then it will insert at * {@code (size() + index)}

* * @param index specify the position where the element should be inserted * @param t the element to be inserted * @return a list as specified above * @throws IndexOutOfBoundsException Math.abs(index) > size() */ List insert(int index, T t) throws IndexOutOfBoundsException; /** * Insert an array of elements at the position specified by {@code index}. *

If this list is readonly or immutable, then an new * list should be created with all elements in this list * and the new element inserted at the specified position. * The new list should have the same feature as this list

*

If index is less than zero then it will insert at * {@code (size() + index)}

* * @param index specify the position where the element should be inserted * @param ta the array of elements to be inserted * @return a list as specified above * @throws IndexOutOfBoundsException Math.abs(index) > size() */ List insert(int index, T... ta) throws IndexOutOfBoundsException; /** * Insert a sub list at the position specified by {@code index}. *

If this list is readonly or immutable, then an new * list should be created with all elements in this list * and the elements of sub list inserted at the specified position. * The new list should have the same feature as this list

*

If index is less than zero then it will insert at * {@code (size() + index)}

* * @param index specify the position where the element should be inserted * @param subList the sub list contains elements to be inserted * @return a list as specified above * @throws IndexOutOfBoundsException Math.abs(index) > size() */ List insert(int index, java.util.List subList) throws IndexOutOfBoundsException; /** * {@inheritDoc} * * @param t {@inheritDoc} * @return a list contains elements in this list followed * by {@code t} */ @Override List append(T t); /** * {@inheritDoc} * * @param iterable the iterable from which elements will be appended to this list * @return a List contains all elements of this list followed * by all elements in the iterable */ List append(Collection iterable); /** * Returns a List contains all elements in this List followed by * all elements in the specified List. *

A mutable List implementation might choose to add elements * from the specified list directly to this list and return this * list directly

*

For a read only or immutable list, it must create an new list * to avoid update this list

* * @param list the list in which elements will be appended * to this list * @return a list contains elements of both list */ List append(List list); @Override List prepend(T t); List prepend(Collection collection); List prepend(List list); @Override List reverse(); /** * Returns a List contains all elements in this List and not in * the {@code col} collection specified * * @param col the collection in which elements should * be excluded from the result List * @return a List contains elements only in this list */ List without(Collection col); /** * Returns a list contains all elements in the list except the * one specified * * @param element the element that should not be in the resulting list * @return a list without the element specified */ List without(T element); /** * Returns a list contains all elements in the list except the * ones specified * * @param element the element that should not be in the resulting list * @param elements the array contains elements that should not be in the resulting list * @return a list without the element specified */ List without(T element, T... elements); @Override List accept($.Visitor visitor); @Override List each($.Visitor visitor); @Override List forEach($.Visitor visitor); @Override List acceptLeft($.Visitor visitor); @Override List acceptRight($.Visitor visitor); /** * Loop through the list and for each element, call on the * indexedVisitor function specified * @param indexedVisitor the function to be called on each element along with the index * @return this list */ List accept(IndexedVisitor indexedVisitor); /** * Alias of {@link #accept(Visitor)} * @param indexedVisitor the function to be called on each element along with the index * @return this list */ List each(IndexedVisitor indexedVisitor); /** * Alias of {@link #accept(Visitor)} * @param indexedVisitor the function to be called on each element along with the index * @return this list */ List forEach(IndexedVisitor indexedVisitor); /** * Loop through the list from {@code 0} to {@code size - 1}. Call the indexedVisitor function * on each element along with the index * @param indexedVisitor the function to be called on each element along with the index * @return this list */ @SuppressWarnings("unused") List acceptLeft(IndexedVisitor indexedVisitor); /** * Loop through the list from {@code size() - 1} to {@code 0}. Call the indexedVisitor function * on each element along with the index * @param indexedVisitor the function to be called on each element along with the index * @return this list */ @SuppressWarnings("unused") List acceptRight(IndexedVisitor 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 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. */ List<$.Binary> zip(java.util.List 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 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. */ List<$.Binary> zipAll(java.util.List 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<$.Binary> zipWithIndex(); /** * Create a {@link Map} from this list using a key extract function and a value extract function * * The key extractor will take the element stored in this list and calculate a key, * and then store the element being used along with the key calculated into the map * to be returned. * * The value extractor will take the element stored in this list and calculate a value, * and then store the element as the key along with the outcome as the value * * @param keyExtractor the function that generate map key from the element in this list * @param valExtractor the function that generate map value from the element in this list * @param the generic type of key in the map * @param the generic type of value in the map * @return a map as described above */ Map toMap($.Function keyExtractor, $.Function valExtractor); /** * Create a {@link Map} from this list using a key extract function. * * The key extractor will take the element stored in this list and calculate a key, * and then store the element being used along with the key calculated into the map * to be returned. * * @param keyExtractor the function that generate map key from the element in this list * @param the generic type of key in the map * @return a map that indexed by key generated by the function from the element in this list */ Map toMapByVal($.Function keyExtractor); /** * Create a {@link Map} from this list using a value extract function. * * The value extractor will take the element stored in this list and calculate a value, * and then store the element as the key along with the outcome as the value * * @param valExtractor the function that generate map value from the element in this list * @param the generic type of value in the map * @return a map that stores the value calculated along with the corresponding element as the key */ Map toMapByKey($.Function valExtractor); } // /** // * The osgl Set interface is a mixture of {@link java.util.Set} and osgl {@link Traversable} // * // * @param the element type of the {@code Set} // * @since 0.2 // */ // public static interface Set extends java.util.Set, Traversable { // } // // /** // * The osgl sorted Set interface is a mixture of {@link java.util.Set} and osgl {@link Sequence} // * // * @param the element type of the {@code SortedSet} // * @since 0.2 // */ // public static interface SortedSet extends java.util.SortedSet, ReversibleSequence { // } // public static class Map implements java.util.Map, Serializable { public static class Entry extends $.T2 implements java.util.Map.Entry { 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 Entry valueOf(K k, V v) { return new Entry(k, v); } } public class _Builder { private K key; private _Builder(K key) { this.key = $.requireNotNull(key); } public Map to(V val) { Map me = Map.this; if (me.ro) { Map mapBuffer = C.newMap(me); mapBuffer.put(key, val); return C.Map(mapBuffer); } Map.this.put(key, val); return Map.this; } } private java.util.Map _m; private boolean ro; @SuppressWarnings("unchecked") protected Map(boolean readOnly, Object... args) { HashMap map = new HashMap<>(); 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 map) { E.NPE(map); boolean sorted = map instanceof SortedMap; java.util.Map m = sorted ? new TreeMap() : new HashMap(); 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) { ensureWritable(); return _m.put(key, value); } @Override public V remove(Object key) { ensureWritable(); return _m.remove(key); } @Override public void putAll(java.util.Map m) { ensureWritable(); _m.putAll(m); } @Override public void clear() { ensureWritable(); _m.clear(); } @Override public java.util.Set keySet() { return _m.keySet(); } @Override public Collection values() { return _m.values(); } @Override public Set> entrySet() { Set> 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 public _Builder map(K key) { return new _Builder(key); } @SuppressWarnings("unused") public boolean isReadOnly() { return ro; } @SuppressWarnings("unused") public Map readOnly(boolean readOnly) { if (ro ^ readOnly) { return new Map<>(readOnly, _m); } else { return this; } } public Map flipped() { Map flip = C.newMap(); for (java.util.Map.Entry entry : entrySet()) { flip.put(entry.getValue(), entry.getKey()); } return flip; } /** * 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 forEach(IndexedVisitor indexedVisitor) { for (java.util.Map.Entry entry: entrySet()) { try { indexedVisitor.apply(entry.getKey(), entry.getValue()); } catch (NotAppliedException e) { // ignore } } return this; } /** * Alias of {@link #forEach(IndexedVisitor)} * @param indexedVisitor the visitor that can be applied on Key/Value pair stored in this Map * @return this map */ public Map each(IndexedVisitor indexedVisitor) { return forEach(indexedVisitor); } /** * Alias of {@link #forEach(IndexedVisitor)} * @param indexedVisitor the visitor that can be applied on Key/Value pair stored in this Map * @return this map */ public Map accept(IndexedVisitor indexedVisitor) { return forEach(indexedVisitor); } public Map filter($.Function predicate) { java.util.Map map = new HashMap<>(); for (java.util.Map.Entry entry : entrySet()) { K k = entry.getKey(); if (predicate.apply(k)) { map.put(k, entry.getValue()); } } Map filtered = new Map<>(isReadOnly(), map); return filtered; } public Map valueFilter($.Function predicate) { java.util.Map map = new HashMap<>(); for (java.util.Map.Entry entry : entrySet()) { V v = entry.getValue(); if (predicate.apply(v)) { map.put(entry.getKey(), v); } } Map filtered = new Map<>(isReadOnly(), map); return filtered; } public Map transformValues($.Function valueTransformer) { Map newMap = C.newMap(); for (java.util.Map.Entry entry : entrySet()) { newMap.put(entry.getKey(), valueTransformer.apply(entry.getValue())); } return newMap; } public Map transformKeys($.Function keyTransformer) { Map newMap = C.newMap(); for (java.util.Map.Entry entry : entrySet()) { newMap.put(keyTransformer.apply(entry.getKey()), entry.getValue()); } return newMap; } public Map transform($.Function keyTransformer, $.Function valueTransformer) { Map newMap = C.newMap(); for (java.util.Map.Entry entry : entrySet()) { newMap.put(keyTransformer.apply(entry.getKey()), valueTransformer.apply(entry.getValue())); } return newMap; } public Set<$.Binary> zip() { C.Set<$.Binary> zipped = C.newSet(); for (java.util.Map.Entry entry : entrySet()) { zipped.add($.T2(entry.getKey(), entry.getValue())); } return zipped; } 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; } private void ensureWritable() { C.ensureWritable(ro, "map"); } } public interface Set extends java.util.Set, Traversable { @Override Set parallel(); @Override Set sequential(); @Override Set lazy(); @Override Set eager(); @Override Set filter($.Function predicate); @Override Set accept($.Visitor visitor); @Override Set each($.Visitor visitor); @Override Set forEach($.Visitor 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 onlyIn(Collection 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 withIn(Collection 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 without(Collection col); /** * Returns a set contains all elements in this set and all * elements in the {@code col} collection specified * * @param col the collection in which elements should be * included in the result set * @return a set contains elements in both this set and the collection */ Set with(Collection col); /** * Returns a set contains all elements in this set plus the element * specified * * @param element the new element that will be contained in the returning set * @return a set as described above */ Set with(T element); /** * Returns a set contains all elements in this set plus all the elements * specified in the parameter list * * @param element the first element to be added into the returning set * @param elements rest elements to be added into the returning set * @return a set as described above */ Set with(T element, T... elements); /** * 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 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 without(T element, T... elements); } public interface ListOrSet extends List, Set { @Override ListOrSet parallel(); @Override ListOrSet sequential(); @Override ListOrSet lazy(); @Override ListOrSet eager(); @Override ListOrSet accept($.Visitor visitor); @Override ListOrSet each($.Visitor visitor); @Override ListOrSet forEach($.Visitor visitor); @Override ListOrSet filter($.Function predicate); @Override ListOrSet without(Collection col); @Override ListOrSet without(T element); @Override ListOrSet without(T element, T... elements); @Override ListOrSet map($.Function mapper); @Override default Spliterator spliterator() { return Spliterators.spliterator(this, Spliterator.DISTINCT); } } /** * 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 java.util.List contains the generic type E * * @param the generic type of the list element * @return A java List instance contains elements of generic type E */ java.util.List create(); /** * Create a java.util.List pre populated with elements * of specified collection * * @param collection the collection whose elements are to be placed into this list * @param the generic type of the list element * @return The List been created * @exception NullPointerException if the specified collection is null */ java.util.List create(Collection collection) throws NullPointerException; /** * Create a java.util.List with initial capacity * * @param initialCapacity the initial capacity of the new List * @param the generic type of the list element * @return the list been created */ java.util.List create(int initialCapacity); enum Predefined { ; static final ListFactory JDK_ARRAYLIST_FACT = new ListFactory() { @Override public java.util.List create() { return new ArrayList(); } @Override public java.util.List create(Collection collection) { return new ArrayList(collection); } @Override public java.util.List create(int initialCapacity) { return new ArrayList(initialCapacity); } }; static final ListFactory JDK_LINKEDLIST_FACT = new ListFactory() { @Override public java.util.List create() { return new LinkedList(); } @Override public java.util.List create(Collection collection) { return new LinkedList(collection); } @Override public java.util.List create(int initialCapacity) { return new LinkedList(); } }; 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 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 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 Collection asCollection(Iterable 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 range(int from, int to) { return new LazyRange(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 range(byte from, byte to) { return new LazyRange(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 range(short from, short to) { return new LazyRange(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 range(long from, long to) { return new LazyRange(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 naturalNumbers() { return new LazyRange(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 evenNumbers() { return new LazyRange(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 oddNumbers() { return new LazyRange(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 Map EMPTY_MAP = Nil.EMPTY_MAP; public static final ListOrSet EMPTY = Nil.EMPTY; @SuppressWarnings("unchecked") public static ListOrSet empty() { return EMPTY; } /** * Returns an empty immutable list * * @param the type of the list element * @return the empty list */ public static List list() { return Nil.list(); } @SuppressWarnings("unused") public static List emptyListOf(Class c) { return Nil.list(); } public static List list(T t) { return $.val(t); } /** * Creates an immutable list of an array of elements. *

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

* * @param ta an array of elements * @param the element type * @return an immutable list backed by the specified array */ public static List 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 the element type * @return an immutable list contains the first element and followed by all element in the array */ public static List 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. *

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

* * @param elements an array of primary boolean * @return a Boolean typed list */ public static List 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 list(boolean[] elements) { if (null == elements || 0 == elements.length) { return Nil.list(); } Boolean[] ba = $.asObject(elements); return ImmutableList.of(ba); } /** * Create an immutable Byte list from a byte (primitive type) array. *

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

* * @param elements an array of primary byte * @return a Byte typed list */ public static List 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 list(byte[] elements) { if (null == elements || 0 == elements.length) { return Nil.list(); } Byte[] ba = $.asObject(elements); return ImmutableList.of(ba); } /** * Create an immutable Short list from a char (primitive type) array. *

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

* * @param elements an array of primary short * @return a Short typed list */ public static List 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 list(char[] elements) { if (null == elements || 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. *

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

* * @param elements an array of primary short * @return a Short typed list */ public static List 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 list(short[] elements) { if (null == elements || 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. *

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

* * @param elements an array of primary int * @return an Integer list */ public static List 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 list(int[] elements) { if (null == elements || 0 == elements.length) { return Nil.list(); } Integer[] a = $.asObject(elements); return ImmutableList.of(a); } /** * Create an immutable Long list from a long (primitive type) array. *

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

* * @param elements an array of primary long * @return an Long list */ public static List 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 list(long[] elements) { if (null == elements || 0 == elements.length) { return list(); } return ImmutableList.of($.asObject(elements)); } /** * Create an immutable Float list from a float (primitive type) array. *

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

* * @param elements an array of primary float * @return an Float list */ public static List 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 list(float[] elements) { if (null == elements || 0 == elements.length) { return list(); } return ImmutableList.of($.asObject(elements)); } /** * Create an immutable Double list from an double (primitive type) array. *

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

* * @param elements an array of primary double * @return an Double list */ public static List 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 list(double[] elements) { if (null == elements || 0 == elements.length) { return list(); } return ImmutableList.of($.asObject(elements)); } public static List list(Iterable iterable) { return null == iterable ? C.list() : ListBuilder.toList(iterable); } public static List list(Iterator iterator) { return null == iterator ? C.list() : ListBuilder.toList(iterator); } public static List list(Enumeration enumeration) { return null == enumeration ? C.list() : ListBuilder.toList(enumeration); } public static List list(Collection col) { return null == col ? C.list() : ListBuilder.toList(col); } public static List list(java.util.List javaList) { if (null == javaList) { return C.list(); } if (javaList instanceof List) { List list = $.cast(javaList); if (list.is(Feature.IMMUTABLE)) { return list; } else { return new ReadOnlyDelegatingList(list); } } return new ReadOnlyDelegatingList(javaList); } public static List singletonList(T t) { return list(t); } public static List wrap(java.util.List list) { return null == list ? C.list() : DelegatingList.wrap(list); } public static List newSizedList(int size) { return new DelegatingList(size); } public static List newList() { return newSizedList(10); } public static List newList(Iterable iterable) { return null == iterable ? C.newList() : new DelegatingList(iterable); } public static List newList(T t) { return new DelegatingList(10).append(t); } public static List newList(T t1, T t2) { return new DelegatingList(10).append(t1).append(t2); } public static List newList(T t1, T t2, T t3) { return new DelegatingList(10).append(t1).append(t2).append(t3); } public static List newList(T t1, T t2, T t3, T... ta) { int len = ta.length; List l = new DelegatingList(len + 3).append(t1).append(t2).append(t3); l.addAll(listOf(ta)); return l; } public static List newListOf(T[] ts) { return null == ts ? C.newList() : new DelegatingList<>(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 the element type * @return the sequence */ @SuppressWarnings("unchecked") public static Sequence seq(Iterable iterable) { if (null == iterable) { return C.list(); } if (iterable instanceof Sequence) { return ((Sequence) iterable); } return IterableSeq.of(iterable); } public static Sequence seq(Iterator iterator) { return null == iterator ? C.list() : IteratorSeq.of(iterator); } public static Sequence seq(Enumeration enumeration) { return null == enumeration ? C.list() : IteratorSeq.of(new EnumerationIterator(enumeration)); } /** * Alias of {@link #collect(Iterable, String)} * @param collection * @param propertyPath * @param * @return */ public static C.List extract(java.util.Collection collection, final String propertyPath) { if (null == collection || collection.isEmpty()) { return C.list(); } $.Transformer extractor = new $.Transformer() { @Override public PROPERTY transform(Object element) { return (PROPERTY)$.getProperty(element, propertyPath); } }; return C.list(collection).map(extractor); } public static Sequence lazyExtract(Iterable iterable, final String propertyPath) { $.Transformer extractor = new $.Transformer() { @Override public PROPERTY transform(Object element) { return (PROPERTY)$.getProperty(element, propertyPath); } }; return map(iterable, extractor); } public static Sequence map(Iterable seq, $.Function mapper) { if (null == seq) { return C.list(); } if (seq instanceof ReversibleSequence) { ReversibleSequence rseq = $.cast(seq); return map(rseq, mapper); } return new MappedSeq<>(seq, mapper); } public static ReversibleSequence map(ReversibleSequence seq, $.Function mapper ) { if (null == seq) { return C.list(); } return new ReversibleMappedSeq<>(seq, mapper); } public static Sequence filter(Iterable iterable, $.Function predicate) { return null == iterable ? C.list() : new FilteredSeq<>(iterable, predicate); } @SuppressWarnings("unchecked") public static Sequence prepend(T t, Sequence sequence) { if (null == sequence) { return C.list(t); } 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 the element type * @return the concatenated sequence */ public static Sequence concat(Sequence s1, Sequence s2) { if (null == s1) { return null == s2 ? C.list() : s2; } if (null == s2) { return s1; } return s1.append(s2); } /** * Concatenate two {@link ReversibleSequence} into one * @param s1 the first reversible sequence * @param s2 the second reversible sequence * @param the element type * @return the concatenated reversible sequence */ @SuppressWarnings("unused") public static ReversibleSequence concat(ReversibleSequence s1, ReversibleSequence s2) { if (null == s1) { return null == s2 ? C.list() : s2; } if (null == s2) { return s1; } return s1.append(s2); } /** * Concatenate two {@link List} into one. *

Note 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

* @param l1 list 1 * @param l2 list 2 * @param the element type * @return a list with elements of both list 1 and list 2 */ @SuppressWarnings("unused") public static List concat(List l1, List l2) { if (null == l1) { return null == l2 ? C.list() : l2; } if (null == l2) { return l1; } return l1.append(l2); } /** * This method is deprecated. Please use {@link #Set()} instead */ @Deprecated public static Set set() { return Nil.set(); } /** * Create an empty immutable set * @param the generic type * @return the empty set */ public static Set Set() { return Nil.set(); } /** * Create an immutable set of a single element * @param element the single element * @param the element type * @return the set that contains only specified element */ public static Set set(T element) { java.util.Set set = new HashSet(); 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 the element type * @return a set that contains all elements specified */ public static Set set(T t1, T... ta) { java.util.Set set = new HashSet(); 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 the element type * @return the set contains all elements in the array */ public static Set setOf(T... ta) { java.util.Set set = new HashSet(); Collections.addAll(set, ta); return ImmutableSet.of(set); } /** * This method is deprecated. Please use {@link #Set(Collection)} instead */ @Deprecated public static Set set(Collection col) { return ImmutableSet.of(col); } /** * 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 the element type * @return the set contains all elements in the collection * @see #newSet(Collection) */ public static Set Set(Collection col) { return null == col ? C.Set() : 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 the element type * @return the set contains all elements supplied by the iterable */ @SuppressWarnings("unchecked") public static Set set(Iterable itr) { if (itr instanceof Collection) { return set((Collection) itr); } java.util.Set set = new HashSet(); for (T t : itr) set.add(t); return ImmutableSet.of(set); } /** * Create an new empty set * @param the element type * @return an empty set */ public static Set newSet() { return new DelegatingSet(); } /** * Create an mutable 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 the element type * @return a set that contains all elements specified */ public static Set newSet(T t1, T... ta) { Set set = new DelegatingSet<>(); set.add(t1); Collections.addAll(set, ta); return set; } /** * 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 the element type * @return the set contains all elements in the collection * @see #set(Collection) */ public static Set newSet(Collection col) { return null == col ? C.Set() : new DelegatingSet<>(col); } public static Set unionOf(Collection col1, Collection col2) { if (null == col1) { return null == col2 ? C.Set() : Set(col2); } if (null == col2) { return C.Set(col1); } return ((Set)C.Set(col1)).with(col2); } public static Set unionOf(Collection col1, Collection col2, Collection col3, Collection ... otherCols) { Set union = C.newSet(col1); if (null != col2) { union.addAll(col2); } if (null != col3) { union.addAll(col3); } for (Collection col : otherCols) { if (null != col) { union.addAll(col); } } return C.set(union); } public static Set intercectionOf(Collection col1, Collection col2) { return ((Set) C.Set(col1)).withIn(col2); } public static Set interceptionOf(Collection col1, Collection col2, Collection col3, Collection... otherCols) { Set interception = C.newSet(col1); if (interception.isEmpty()) { return interception; } if (null == col2) { return C.Set(); } interception.retainAll(col2); if (null == col3) { return C.Set(); } interception.retainAll(col3); for (Collection col : otherCols) { if (null == col) { return C.Set(); } interception.retainAll(col); } return interception; } /** * Create a immutable {@link Map} from elements specified in an array. *

Example

*
     *     Map<String, Integer> scores = C.map("Tom", 80, "Peter", 93, ...);
     * 
*

The above code will create an immutable Map with the following entries

*
    *
  • (Tom, 80)
  • *
  • (Peter, 93)
  • *
  • ...
  • *
*

Note the array size must be an even number, otherwise {@link IndexOutOfBoundsException} * will be thrown out

* @param args the argument array specifies the entries * @param the key type * @param the value type * @return an immutable map contains of specified entries * @see #newMap(Object...) */ public static Map Map(Object... args) { if (null == args || args.length == 0) { return Nil.EMPTY_MAP; } return new Map<>(true, args); } public static Map Map(boolean readOnly, java.util.Map map) { return new Map(readOnly, map); } public static Map Map(Collection<$.Tuple> kvCol) { Map map = C.newMap(); for ($.Tuple entry : kvCol) { map.put(entry._1, entry._2); } return new Map<>(true, map); } /** * 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 the key type * @param the value type * @return an immutable map of the existing map */ public static Map Map(java.util.Map map) { if (null == map) { return Nil.EMPTY_MAP; } return new Map(true, map); } /** * Create an new {@link Map} from an array of elements. *

Example

*
     *     Map<String, Integer> scores = C.newMap("Tom", 80, "Peter", 93, ...);
     * 
*

The above code will create a Map with the following entries

*
    *
  • (Tom, 80)
  • *
  • (Peter, 93)
  • *
  • ...
  • *
*

Note the array size must be an even number, otherwise {@link IndexOutOfBoundsException} * will be thrown out

* @param args the argument array specifies the entries * @param the key type * @param the value type * @return a map contains of specified entries * @see #Map(Object...) */ @SuppressWarnings("unchecked") public static Map 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 the key type * @param the value type * @return a map that contains all entries in the existing map */ @SuppressWarnings("unchecked") public static Map newMap(java.util.Map map) { return new Map(false, map); } /** * Convert a {@link Enumeration} to an {@link Iterable} * @param e the enumeration * @param the element type * @return an iterable corresponding to the enumeration */ public static Iterable enumerable(final Enumeration e) { return new Iterable() { @Override public Iterator iterator() { return new Iterator() { @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.Lang.Break} if it need to break the loop. *

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

* @param iterable supply the element to be applied to the visitor function * @param visitor the function called on element provided by the iterable * @param the generic type of the iterable elements * @throws $.Break break the loop */ //TODO: implement forEach iteration in parallel public static void forEach(Iterable iterable, $.Visitor 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.Lang.Break} if it need to break the loop. *

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

* @param iterator iterator provides elements to be applied to the visitor function * @param visitor the function applied on the element * @param the generic type of the element */ public static void forEach(Iterator iterator, $.Visitor 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.Lang.Break} if it need to break the loop. *

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

* @param map the map in which enties will be applied to the indexedVisitor function * @param indexedVisitor the function that takes (key,value) pair * @param the generic type of Key * @param the generic type of Value * @throws $.Break the {@link org.osgl.Lang.Break} with payload throwed out by indexedVisitor function to break to loop */ public static void forEach(java.util.Map map, IndexedVisitor indexedVisitor) throws $.Break { for (java.util.Map.Entry entry : map.entrySet()) { try { indexedVisitor.apply(entry.getKey(), entry.getValue()); } catch (NotAppliedException e) { // ignore } } } public static class _CollectStage { Iterable source; public _CollectStage(Iterable source) { this.source = source; } public List by(String propertyPath) { return C.collect(source, propertyPath); } } public static class _CollectStage2 { String propertyPath; public _CollectStage2(String propertyPath) { this.propertyPath = propertyPath; } public List on(Iterable source) { return C.collect(source, propertyPath); } } public static _CollectStage collect(Iterable source) { return new _CollectStage(source); } public static _CollectStage2 collect(String propertyPath) { return new _CollectStage2(propertyPath); } public static List collect(Iterable source, String propertyPath) { if (null == source) { return C.list(); } int sz = 10; if (source instanceof Collection) { sz = ((Collection) source).size(); if (0 == sz) { return C.list(); } } List retList = newSizedList(sz); for (Object o: source) { retList.add((T) $.getProperty(o, propertyPath)); } return retList; } public static class _MapStage { Iterable source; _MapStage(Iterable source) { this.source = source; } public Sequence with($.Function mapper) { return C.map(source, mapper); } } public static class _MapStage2 { $.Function mapper; _MapStage2($.Function mapper) { this.mapper = $.requireNotNull(mapper); } public Sequence on(Iterable source) { return C.map(source, mapper); } } public static _MapStage map(Iterable source) { return new _MapStage<>(source); } public static _MapStage2 map($.Function mapper) { return new _MapStage2(mapper); } public static class _FilterStage { Iterable source; _FilterStage(Iterable source) { this.source = source; } public Sequence by($.Predicate predicate) { return filter(source, predicate); } } public static class _FilterStage2 { $.Predicate predicate; _FilterStage2($.Predicate predicate) { this.predicate = $.requireNotNull(predicate); } public Sequence on(Iterable source) { return filter(source, predicate); } } public static _FilterStage filter(Iterable source) { return new _FilterStage<>(source); } public static _FilterStage2 filter($.Predicate predicate) { return new _FilterStage2<>(predicate); } private static void ensureWritable(boolean ro, String containerName) { if (ro) { throw new ReadOnlyException(containerName + " is readonly"); } } // --- eof utility methods --- // --- Mutable collection/map constructors public enum Mutable { } /** * the namespace of function definitions relevant to Collection manipulation */ public enum F { ; public static $.Transformer, Collection> asCollection() { return new Lang.Transformer, Collection>() { @Override public Collection transform(Iterable 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 the generic type of the element of the collection * @return a predicate function * @see Collection#contains(Object) * @see #contains(Object) */ public static $.Predicate containsIn(final Collection collection) { return new $.Predicate() { @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 the type of the element * @return the function that do the check * @see Collection#contains(Object) * @see #containsIn(Collection) */ public static $.Predicate> contains(final T element) { return new $.Predicate>() { @Override public boolean test(Collection 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 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 $.Predicate> allContainsIn(final Collection collection) { return new $.Predicate>() { @Override public boolean test(Collection 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 the element type * @return the function that do the check * @see Collection#containsAll(Collection) * @see #allContainsIn(Collection) */ @SuppressWarnings("unused") public static $.Predicate> containsAll(final Collection collection) { return new $.Predicate>() { @Override public boolean test(Collection 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 the generic type of the collection elements * @return a function that do the add operation * @see Collection#add(Object) * @see #add(Object) */ public static $.Predicate addTo(final Collection destination) { return new $.Predicate() { @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 the element type * @return the function * @see Collection#add(Object) * @see #addTo(Collection) */ public static $.Predicate> add(final T element) { return new $.Predicate>() { @Override public boolean test(Collection 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 the generic type of the list * @param 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 , T> $.F1 addTo(final int index, final L destination) { return new $.F1() { @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 the list type * @param the element type * @return the function * @see java.util.List#add(int, Object) * @see #addTo(int, List) */ public static , T> $.F1 add(final int index, final T element) { return new $.F1() { @Override public L apply(L list) throws NotAppliedException, Lang.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 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 $.Predicate> addAllTo(final Collection destination) { return new $.Predicate>() { @Override public boolean test(Iterable 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 the element type * @return the function the perform the add operation * @see Collection#addAll(Collection) * @see #addAllTo(Collection) */ @SuppressWarnings({"unchecked"}) public static $.Predicate> addAll(final Collection source) { return new $.Predicate>() { @Override public boolean test(Collection 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 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 $.Predicate> addAllTo(final int index, final List destination) { if (0 > index || destination.size() < index) { throw new IndexOutOfBoundsException(); } return new $.Predicate>() { @Override public boolean test(Collection 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 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 $.Predicate> addAll(final int index, final Collection source) { return new $.Predicate>() { @Override public boolean test(List destination) { return destination.addAll(index, source); } }; } /** * Returns a function that remove the argument from a collection specified. *

The function returns {@code true} if argument removed successfully or * {@code false} otherwise

* @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 $.Predicate removeFrom(final Collection collection) { return new $.Predicate() { @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 the element type * @return the function that do removing * @see Collection#remove(Object) * @see #removeFrom(Collection) */ @SuppressWarnings("unused") public static $.Predicate> remove(final T toBeRemoved) { return new $.Predicate>() { @Override public boolean test(Collection 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 the element type * @return the function * @see Collection#removeAll(Collection) * @see #removeAll(Collection) */ @SuppressWarnings("unused") public static $.Predicate> removeAllFrom(final Collection fromCollection) { return new Lang.Predicate>() { @Override public boolean test(Collection 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 the element type * @return the function * @see Collection#removeAll(Collection) * @see #removeAllFrom(Collection) */ public static $.Predicate> removeAll(final Collection source) { return new Lang.Predicate>() { @Override public boolean test(Collection 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 the element type * @return the function as described * @see Collection#retainAll(Collection) * @see #retainAll(Collection) */ @SuppressWarnings({"unused"}) public static $.Predicate> retainAllIn(final Collection collection) { return new $.Predicate>() { @Override public boolean test(Collection 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 the element type * @return the function as described above * @see Collection#retainAll(Collection) * @see #retainAllIn(Collection) */ @SuppressWarnings({"unused"}) public static $.Predicate> retainAll(final Collection collection) { return new $.Predicate>() { @Override public boolean test(Collection 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 the element type * @return the function as described * @see Deque#addFirst(Object) * @see #dequePrepend(Object) */ @SuppressWarnings({"unused"}) public static $.F1> prependTo(final Deque deque) { return new $.F1>() { @Override public Deque 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 the element type * @return the function as described * @see Deque#addFirst(Object) * @see #prependTo(Deque) */ @SuppressWarnings("unused") public static $.Processor> dequePrepend(final T element) { return new $.Processor>() { @Override public void process(Deque deque) throws Lang.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 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 $.F1> appendTo(final Deque deque) { return new $.F1>() { @Override public Deque 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 the element type * @return the function as described * @see Deque#add(Object) * @see #appendTo(Deque) */ @SuppressWarnings("unused") public static $.Processor> dequeAppend(final T element) { return new $.Processor>() { @Override public void process(Deque deque) throws Lang.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 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 $.F1> prependTo(final Sequence sequence) { return new $.F1>() { @Override public Sequence 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 the element type * @return the function as described * @see Sequence#prepend(Object) * @see #prependTo(Sequence) */ @SuppressWarnings("unused") public static $.Processor> sequencePrepend(final T element) { return new Lang.Processor>() { @Override public void process(Sequence sequence) throws Lang.Break, NotAppliedException { sequence.prepend(element); } }; } /** * Returns a function that append the argument to a {@link Sequence} specified *

Note the function returns the sequence with the argument been removed

* @param sequence the sequence to which the argument shall be append when applying the function * @param 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 $.F1> appendTo(final Sequence sequence) { return new $.F1>() { @Override public Sequence 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 the element type * @return the function as described * @see Sequence#append(Iterable) * @see #appendTo(Sequence) */ @SuppressWarnings("unused") public static $.Processor> sequenceAppend(final T element) { return new Lang.Processor>() { @Override public void process(Sequence sequence) throws Lang.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 the element type * @return the function as described * @see C#forEach(Iterable, org.osgl.Lang.Visitor) */ @SuppressWarnings("unused") public static $.F1, Void> forEachIterable(final $.Visitor visitor) { return new $.F1, Void>() { @Override public Void apply(Iterable iterable) throws NotAppliedException, $.Break { C.forEach(iterable, visitor); return null; } }; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy