Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
functionalj.list.ImmutableFuncList Maven / Gradle / Ivy
// ============================================================================
// 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 java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.BooleanSupplier;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import functionalj.function.ObjectObjectToIntegerFunction;
import functionalj.result.Result;
import functionalj.stream.StreamPlus;
import functionalj.stream.markers.Sequential;
import functionalj.stream.markers.Terminal;
import lombok.val;
// TODO - Override methods in FuncListWithMapGroup to make it faster
// TODO - Override methods in FuncListWithMapWithIndex to make it faster
public final class ImmutableFuncList implements FuncList {
private static final ObjectObjectToIntegerFunction zeroForEquals = (Object i1, Object i2) -> Objects.equals(i1, i2) ? 0 : 1;
private static final Predicate toZero = (Integer i) -> i == 0;
private final static ImmutableFuncList> EMPTY = new ImmutableFuncList<>(Collections.emptyList(), 0);
/** @return an empty list */
@SuppressWarnings("unchecked")
public static final ImmutableFuncList empty() {
return (ImmutableFuncList)EMPTY;
}
/** @return the list containing the given elements */
@SafeVarargs
public static ImmutableFuncList of(T ... data) {
val list = new ArrayList(data.length);
for (val each : data)
list.add(each);
return new ImmutableFuncList<>(list, list.size());
}
/** @return the list containing the given elements */
@SafeVarargs
public static ImmutableFuncList listOf(T ... data) {
val list = new ArrayList(data.length);
for (val each : data)
list.add(each);
return new ImmutableFuncList(list, list.size());
}
/** Create a FuncList from the given array. */
public static ImmutableFuncList from(TARGET[] datas) {
return from(Mode.lazy, datas);
}
/** Create a FuncList from the given array. */
public static ImmutableFuncList from(Mode mode, TARGET[] datas) {
return ImmutableFuncList.of(datas);
}
/** @return the list containing the given elements */
public static FuncList from(Mode mode, AsFuncList funcList) {
if (funcList == null)
return ImmutableFuncList.empty();
FuncList list = funcList.asFuncList();
return new ImmutableFuncList(list, list.size(), mode);
}
/** @return the list containing the element from the given stream */
public static ImmutableFuncList from(Stream stream) {
val list = stream.collect(Collectors.toList());
return new ImmutableFuncList(list, list.size());
}
/** @return the list containing the element from the given stream */
static FuncList from(Mode mode, Stream stream) {
val list = stream.collect(Collectors.toList());
return new ImmutableFuncList(list, list.size(), mode);
}
/** @return the list containing the element from the given list. */
public static ImmutableFuncList from(ReadOnlyList readOnlyList) {
if (readOnlyList instanceof ImmutableFuncList)
return (ImmutableFuncList)readOnlyList;
if (readOnlyList == null)
return ImmutableFuncList.empty();
val list = readOnlyList.toJavaList();
return new ImmutableFuncList(list, list.size());
}
/** @return the list containing the element from the given collections. */
public static ImmutableFuncList from(Collection collection) {
if (collection instanceof ImmutableFuncList)
return (ImmutableFuncList)collection;
if (collection == null)
return ImmutableFuncList.empty();
if (collection instanceof FuncList) {
val funcList = (FuncList)collection;
return new ImmutableFuncList(funcList.toJavaList(), funcList.size(), funcList.mode());
}
if (collection instanceof List) {
val list = (List)collection;
return new ImmutableFuncList(list, list.size(), Mode.lazy);
}
val list = (List)collection.stream().collect(Collectors.toList());
return new ImmutableFuncList(list, list.size(), Mode.lazy);
}
//-- Data --
private final List data;
private final FuncList.Mode mode;
private final int size;
private volatile String toStringCache = null;
private volatile Integer hashcodeCache = null;
//-- Constructors --
ImmutableFuncList(Collection data, int size) {
this(data, size, Mode.lazy);
}
ImmutableFuncList(Collection data, int size, Mode mode) {
if (data == null) {
this.data = Collections.emptyList();
} else if (data instanceof ImmutableFuncList) {
this.data = ((ImmutableFuncList)data).data;
} else {
val list = new ArrayList();
data.forEach(list::add);
this.data = list;
}
this.size = (size != -1) ? size : this.data.size();
this.mode = mode;
}
@Override
public StreamPlus stream() {
if (size ==-1) {
return StreamPlus.from(data.stream());
} else {
return StreamPlus.from(data.stream().limit(size));
}
}
@Override
public Mode mode() {
return mode;
}
@Override
public FuncList toLazy() {
if (mode().isLazy())
return this;
// Do this to not duplicate the data
return new ImmutableFuncList(data, size, Mode.lazy);
}
@Override
public FuncList toEager() {
if (mode().isEager())
return this;
// Do this to not duplicate the data
return new ImmutableFuncList(data, size, Mode.eager);
}
@Override
public FuncList toCache() {
if (mode().isCache())
return this;
// Do this to not duplicate the data
return new ImmutableFuncList(data, size, Mode.cache);
}
@Override
public ImmutableFuncList toImmutableList() {
return this;
}
@Override
public String toString() {
if (toStringCache != null)
return toStringCache;
synchronized (this) {
if (toStringCache != null)
return toStringCache;
toStringCache = StreamPlus.from(data.stream().limit(size)).toListString();
return toStringCache;
}
}
@Override
public int hashCode() {
if (hashcodeCache != null)
return hashcodeCache;
synchronized (this) {
if (hashcodeCache != null)
return hashcodeCache;
hashcodeCache
= mapToInt(value -> (value != null) ? Objects.hash(value) : 0)
.limit(size)
.reduce(43, (hash, each) -> hash*43 + each);
return hashcodeCache;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public boolean equals(Object o) {
if (!(o instanceof FuncList))
return false;
if (hashCode() != o.hashCode())
return false;
val anotherList = (FuncList)o;
if (size() != anotherList.size())
return false;
return FuncList.zipOf(this, anotherList, (BiFunction)zeroForEquals)
.allMatch(toZero);
}
// -- Short cut --
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return (size == 0);
}
@SuppressWarnings("unchecked")
@Override
public TARGET[] toArray(TARGET[] seed) {
if (seed.length != size) {
seed = (TARGET[])Array.newInstance(seed.getClass().getComponentType(), size);
}
val seedArray = seed;
val streamPlus = streamPlus();
streamPlus
.limit (Math.min(size, seed.length - 0))
.forEachWithIndex((index, element) -> {
seedArray[index] = (TARGET)element;
});
return seed;
}
@Override
public DATA get(int index) {
if ((index < 0) || (index >= size)) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
return data.get(index);
}
@Override
public int indexOf(Object o) {
int index = data.indexOf(o);
if (index >= size) {
return -1;
}
return index;
}
@Override
public int lastIndexOf(Object o) {
// TODO - Improve this efficiency
return data.subList(0, size).lastIndexOf(o);
}
@Override
public ListIterator listIterator() {
// TODO - Improve this efficiency
return data.subList(0, size).listIterator();
}
@Override
public ListIterator listIterator(int index) {
// TODO - Improve this efficiency
return data.subList(0, size).listIterator();
}
@Sequential
@Terminal
@Override
public Result firstResult() {
return (size == 0)
? Result.ofNotExist()
: Result.ofValue(this.data.get(0));
}
@Sequential
@Terminal
@Override
public Result lastResult() {
return (size == 0)
? Result.ofNotExist()
: Result.ofValue(this.data.get(size - 1));
}
//-- Append
/**
* Add the given value to the end of the list.
* This method is for convenient. It is not really efficient if used to add a lot of data.
**/
public FuncList append(DATA value) {
if (this == EMPTY) {
List list = new ArrayList();
list.add(value);
return new ImmutableFuncList(list, 1, mode());
}
return syncIf(
() ->(data instanceof ArrayList) && (size == data.size()),
()-> {
data.add(value);
return new ImmutableFuncList<>(data, data.size(), mode());
},
() -> {
return FuncList.super.append(value);
});
}
/** Add the given values to the end of the list. */
@SuppressWarnings("unchecked")
public FuncList appendAll(DATA ... values) {
// if (this == EMPTY) {
// val list = new ArrayList(values.length);
// for (DATA value : values) {
// list.add(value);
// }
// return new ImmutableFuncList(list, list.size(), isLazy);
// }
return syncIf(
() ->(data instanceof ArrayList) && (size == data.size()),
()-> {
for (DATA value : values) {
data.add(value);
}
return new ImmutableFuncList<>(data, data.size(), mode());
},
() -> {
return FuncList.super.appendAll(values);
});
}
/** Add the given value in the collection to the end of the list. */
public FuncList appendAll(Collection extends DATA> collection) {
// if (this == EMPTY) {
// val list = new ArrayList(collection.size());
// list.addAll(collection);
// return new ImmutableFuncList(list, list.size(), isLazy);
// }
return syncIf(
() ->(data instanceof ArrayList) && (size == data.size()),
()-> {
data.addAll(collection);
return new ImmutableFuncList<>(data, data.size(), mode());
},
() -> {
return FuncList.super.appendAll(collection);
});
}
private FuncList syncIf(
BooleanSupplier condition,
Supplier> matchAction,
Supplier> elseAction) {
synchronized (this) {
if (condition.getAsBoolean()) {
return matchAction.get();
}
}
return elseAction.get();
}
}