functionalj.list.FuncList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of functionalj-core Show documentation
Show all versions of functionalj-core Show documentation
The module for FunctionalJ Core.
// ============================================================================
// Copyright (c) 2017-2021 Nawapunth Manusitthipol (NawaMan - http://nawaman.net).
// ----------------------------------------------------------------------------
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ============================================================================
package functionalj.list;
import static functionalj.lens.Access.$I;
import static java.util.function.Function.identity;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import functionalj.function.DoubleDoubleFunction;
import functionalj.function.DoubleObjBiFunction;
import functionalj.function.Func;
import functionalj.function.IntIntBiFunction;
import functionalj.function.IntObjBiFunction;
import functionalj.function.LongLongBiFunction;
import functionalj.function.aggregator.Aggregation;
import functionalj.function.aggregator.AggregationToBoolean;
import functionalj.function.aggregator.AggregationToDouble;
import functionalj.function.aggregator.AggregationToInt;
import functionalj.function.aggregator.AggregationToLong;
import functionalj.list.doublelist.AsDoubleFuncList;
import functionalj.list.doublelist.DoubleFuncList;
import functionalj.list.doublelist.ImmutableDoubleFuncList;
import functionalj.list.intlist.AsIntFuncList;
import functionalj.list.intlist.ImmutableIntFuncList;
import functionalj.list.intlist.IntFuncList;
import functionalj.list.longlist.AsLongFuncList;
import functionalj.list.longlist.ImmutableLongFuncList;
import functionalj.list.longlist.LongFuncList;
import functionalj.result.NoMoreResultException;
import functionalj.result.Result;
import functionalj.stream.IterablePlus;
import functionalj.stream.IteratorPlus;
import functionalj.stream.StreamPlus;
import functionalj.stream.SupplierBackedIterator;
import functionalj.stream.doublestream.DoubleStreamPlus;
import functionalj.stream.intstream.IntStreamPlus;
import functionalj.stream.longstream.LongStreamPlus;
import functionalj.stream.markers.Eager;
import functionalj.stream.markers.Terminal;
import functionalj.tuple.IntTuple2;
import functionalj.tuple.Tuple2;
import lombok.val;
import nullablej.nullable.Nullable;
public interface FuncList
extends
ReadOnlyList,
Predicate,
AsFuncList,
FuncListWithCombine,
FuncListWithFillNull,
FuncListWithFilter,
FuncListWithFlatMap,
FuncListWithLimit,
FuncListWithMap,
FuncListWithMapFirst,
FuncListWithMapGroup,
FuncListWithMapMulti,
FuncListWithMapThen,
FuncListWithMapToMap,
FuncListWithMapToTuple,
FuncListWithMapWithIndex,
FuncListWithModify,
FuncListWithPeek,
FuncListWithPipe,
FuncListWithSegment,
FuncListWithSort,
FuncListWithSplit {
public enum Mode {
lazy,
eager,
cache;
public boolean isLazy() { return this == lazy; }
public boolean isEager() { return this == eager; }
public boolean isCache() { return this == cache; }
}
/** Throw a no more element exception. This is used for generator. */
public static TARGET noMoreElement() throws NoMoreResultException {
return SupplierBackedIterator.noMoreElement();
}
/** Returns an empty functional list. */
public static ImmutableFuncList empty() {
return ImmutableFuncList.empty();
}
/** Returns an empty functional list. */
public static ImmutableFuncList emptyList() {
return ImmutableFuncList.empty();
}
/** Returns an empty FuncList. */
public static ImmutableFuncList empty(Class elementClass) {
return ImmutableFuncList.empty();
}
/** Returns an empty FuncList. */
public static ImmutableFuncList emptyList(Class elementClass) {
return ImmutableFuncList.empty();
}
/** Create a FuncList from the given data. */
@SafeVarargs
public static ImmutableFuncList of(TARGET... data) {
return ImmutableFuncList.of(data);
}
/** Create a FuncList from the given data. */
@SafeVarargs
public static ImmutableFuncList AllOf(TARGET... data) {
return ImmutableFuncList.of(data);
}
/** Create a FuncList from the given data. */
@SafeVarargs
public static ImmutableFuncList ListOf(TARGET... data) {
return ImmutableFuncList.of(data);
}
/** Create a FuncList from the given data. */
@SafeVarargs
public static ImmutableFuncList listOf(TARGET... data) {
return ImmutableFuncList.of(data);
}
/** Create a FuncList from the given array. */
public static ImmutableFuncList from(TARGET[] datas) {
return ImmutableFuncList.of(datas);
}
/** Create a FuncList from the given array. */
public static ImmutableIntFuncList from(int[] datas) {
return ImmutableIntFuncList.of(datas);
}
/** Create a FuncList from the given array. */
public static ImmutableLongFuncList from(long[] datas) {
return ImmutableLongFuncList.of(datas);
}
/** Create a FuncList from the given array. */
public static ImmutableDoubleFuncList from(double[] datas) {
return ImmutableDoubleFuncList.of(datas);
}
/** Create a FuncList from the given collection. */
public static FuncList from(Collection collection) {
if (collection instanceof FuncList) {
val funcList = (FuncList)collection;
if (funcList.mode().isEager()) {
return funcList.toImmutableList();
}
return funcList;
}
return new FuncListDerived<>(collection, identity());
}
/** Create a FuncList from the given FuncList. */
public static FuncList from(Mode mode, AsFuncList asFuncList) {
val funcList = asFuncList.asFuncList();
return funcList.toMode(mode);
}
/** Create a FuncList from the given stream. */
public static FuncList from(Stream stream) {
return new StreamBackedFuncList(stream);
}
/**
* Create a FuncList from the given supplier of stream.
*
* The provided stream should produce the same sequence of values.
**/
public static FuncList from(Supplier> supplier) {
return new FuncListDerived(()->StreamPlus.from(supplier.get()));
}
//== Create ==
/** Returns a list that contains nulls. */
public static FuncList nulls() {
return FuncList.from(()->StreamPlus.nulls());
}
/** Returns a list that contains nulls. */
public static FuncList nulls(Class dataClass) {
return FuncList.from(()->StreamPlus.nulls(dataClass));
}
/** Create a list that is the repeat of the given array of data. */
@SuppressWarnings("unchecked")
public static FuncList repeat(TARGET ... data) {
return FuncList.from(()->StreamPlus.repeat(data));
}
/** Create a list that is the repeat of the given list of data. */
public static FuncList repeat(FuncList data) {
return FuncList.from(()->StreamPlus.repeat(data));
}
/** Create a list that is the repeat of the given array of data. */
@SafeVarargs
public static FuncList cycle(TARGET ... data) {
return FuncList.from(()->StreamPlus.cycle(data));
}
/** Create a list that is the repeat of the given list of data. */
public static FuncList cycle(Collection data) {
return FuncList.from(()->StreamPlus.cycle(data));
}
/** Create a list that for an infinite loop - the value is null */
public static FuncList loop() {
return FuncList.from(()->StreamPlus.loop());
}
/** Create a list that for a loop with the number of time given - the value is the index of the loop. */
public static FuncList loop(int times) {
return FuncList.from(()->StreamPlus.loop(times));
}
/** Create a list that for an infinite loop - the value is the index of the loop. */
public static FuncList infiniteInt() {
return FuncList.from(()->StreamPlus.infiniteInt());
}
//-- Concat + Combine --
/** Concatenate all the given streams. */
@SafeVarargs
public static FuncList concat(FuncList ... list) {
return combine(list);
}
/**
* Concatenate all the given lists.
*
* This method is the alias of {@link FuncList#concat(FuncList...)}
* but allowing static import without colliding with {@link String#concat(String)}.
**/
@SafeVarargs
public static FuncList combine(FuncList ... lists) {
ImmutableFuncList> listOfList = FuncList.listOf(lists);
return listOfList.flatMap(Func.itself());
}
// TODO - Rethink ... as this will generate un-repeatable stream.
// we may want to do cache here.
/**
* Create a FuncList from the supplier of suppliers.
* The supplier will be repeatedly asked for value until NoMoreResultException is thrown.
**/
public static FuncList generate(Supplier> supplier) {
return FuncList.from(() -> {
val generator = supplier.get();
return StreamPlus.generate(generator);
});
}
/**
* Create a list from the supplier of suppliers.
* The supplier will be repeatedly asked for value until NoMoreResultException is thrown.
**/
public static FuncList generateWith(Supplier> supplier) {
return generate(supplier);
}
/**
* Create a list by apply the compounder to the seed over and over.
*
* For example: let say seed = 1 and f(x) = x*2.
* The result stream will be:
* 1 <- seed,
* 2 <- (1*2),
* 4 <- ((1*2)*2),
* 8 <- (((1*2)*2)*2),
* 16 <- ((((1*2)*2)*2)*2)
* ...
*
* Note: this is an alias of compound()
**/
public static FuncList iterate(
TARGET seed,
Function compounder) {
return FuncList.from(()->StreamPlus.iterate(seed, compounder));
}
public static FuncList iterate(
TARGET seed,
Aggregation aggregation) {
return FuncList.from(()->StreamPlus.iterate(seed, aggregation));
}
/**
* Create a list by apply the compounder to the seed over and over.
*
* For example: let say seed = 1 and f(x) = x*2.
* The result stream will be:
* 1 <- seed,
* 2 <- (1*2),
* 4 <- ((1*2)*2),
* 8 <- (((1*2)*2)*2),
* 16 <- ((((1*2)*2)*2)*2)
* ...
*
* Note: this is an alias of iterate()
**/
public static FuncList compound(
TARGET seed,
Function compounder) {
return FuncList.from(() -> StreamPlus.compound(seed, compounder));
}
public static FuncList compound(
TARGET seed,
Aggregation aggregation) {
return FuncList.from(() -> StreamPlus.compound(seed, aggregation));
}
/**
* Create a list by apply the compounder to the seeds over and over.
*
* For example: let say seed1 = 1, seed2 = 1 and f(a,b) = a+b.
* The result stream will be:
* 1 <- seed1,
* 1 <- seed2,
* 2 <- (1+1),
* 3 <- (1+2),
* 5 <- (2+3),
* 8 <- (5+8)
* ...
*
* Note: this is an alias of compound()
**/
public static FuncList iterate(
TARGET seed1,
TARGET seed2,
BiFunction compounder) {
return FuncList.from(()->StreamPlus.iterate(seed1, seed2, compounder));
}
/**
* Create a list by apply the compounder to the seeds over and over.
*
* For example: let say seed1 = 1, seed2 = 1 and f(a,b) = a+b.
* The result stream will be:
* 1 <- seed1,
* 1 <- seed2,
* 2 <- (1+1),
* 3 <- (1+2),
* 5 <- (2+3),
* 8 <- (5+8)
* ...
*
* Note: this is an alias of iterate()
**/
public static FuncList compound(
TARGET seed1,
TARGET seed2,
BiFunction compounder) {
return FuncList.from(()->StreamPlus.compound(seed1, seed2, compounder));
}
//== Zip ==
/**
* Create a FuncList by combining elements together into a FuncList of tuples.
* Only elements with pair will be combined. If this is not desirable, use FuncList1.zip(FuncList2).
*
* For example:
* list1 = [A, B, C, D, E]
* list2 = [1, 2, 3, 4]
*
* The result stream = [(A,1), (B,2), (C,3), (D,4)].
**/
public static FuncList> zipOf(
List list1,
List list2) {
return FuncList.from(() -> StreamPlus.zipOf(list1.stream(), list2.stream()));
}
/**
* Create a FuncList by combining elements together using the merger function and collected into the result stream.
* Only elements with pair will be combined. If this is not desirable, use FuncList1.zip(FuncList2).
*
* For example:
* list1 = [A, B, C, D, E]
* list2 = [1, 2, 3, 4]
* merger = a + "+" + b
*
* The result stream = ["A+1", "B+2", "C+3", "D+4"].
**/
public static FuncList zipOf(
List list1,
List list2,
BiFunction merger) {
return FuncList.from(() -> {
return StreamPlus.zipOf(list1.stream(), list2.stream(), merger);
});
}
/**
* Zip integers from two IntFuncLists and combine it into another object.
* The result stream has the size of the shortest FuncList.
*/
public static FuncList zipOf(
AsIntFuncList list1,
AsIntFuncList list2,
IntIntBiFunction merger) {
return FuncList.from(() -> {
return StreamPlus.zipOf(
list1.intStream(),
list2.intStream(),
merger);
});
}
/**
* Zip integers from an int stream and another object stream and combine it into another object.
* The result stream has the size of the shortest stream.
*/
public static FuncList zipOf(
AsIntFuncList list1,
List list2,
IntObjBiFunction merger) {
return FuncList.from(() -> {
return StreamPlus.zipOf(
list1.intStream(),
list2.stream(),
merger);
});
}
/**
* Zip integers from two IntFuncLists and combine it into another object.
* The result stream has the size of the shortest FuncList.
*/
public static FuncList zipOf(
AsLongFuncList list1,
AsLongFuncList list2,
LongLongBiFunction merger) {
return FuncList.from(() -> {
return StreamPlus.zipOf(
list1.longStream(),
list2.longStream(),
merger);
});
}
/**
* Zip integers from two IntFuncLists and combine it into another object.
* The result stream has the size of the shortest FuncList.
*/
public static FuncList zipOf(
AsDoubleFuncList list1,
AsDoubleFuncList list2,
DoubleDoubleFunction merger) {
return FuncList.from(() -> {
return StreamPlus.zipOf(
list1.doubleStream(),
list2.doubleStream(),
merger);
});
}
/**
* Zip integers from an int stream and another object stream and combine it into another object.
* The result stream has the size of the shortest stream.
*/
public static FuncList zipOf(
AsDoubleFuncList list1,
List list2,
DoubleObjBiFunction merger) {
return FuncList.from(() -> {
return StreamPlus.zipOf(
list1.doubleStream(),
list2.stream(),
merger);
});
}
//-- Builder --
/** Create a new FuncList. */
public static FuncListBuilder newListBuilder() {
return new FuncListBuilder();
}
/** Create a new list builder. */
public static FuncListBuilder newBuilder() {
return new FuncListBuilder();
}
/** Create a new FuncList. */
public static FuncListBuilder newListBuilder(Class clz) {
return new FuncListBuilder();
}
/** Create a new list builder. */
public static FuncListBuilder newBuilder(Class clz) {
return new FuncListBuilder();
}
//== Core ==
/** Return the stream of data behind this StreamPlus. */
public StreamPlus stream();
/** Return the stream of data behind this IntFuncList. */
public default StreamPlus streamPlus() {
return stream();
}
/** Return the this as a FuncList. */
@Override
public default FuncList asFuncList() {
return this;
}
//-- Derive --
/** Create a FuncList from the given FuncList. */
@SuppressWarnings({"rawtypes", "unchecked"})
public static