forked from Speiger/Primitive-Collections
Started working on the next patch.
- Added: ISizeProvider interface (Optimization Helper) - Added: ISizeProvider into most Iterable implementations (Distinct/Filter/FlatMap/ArrayFlatMap don't support it, for obvious reasons) - Added: ToArray function into Iterable which uses ISizeProvider to reduce overhead of duplicating arrays. - Fixed: putIfAbsent now replaces defaultValues
This commit is contained in:
parent
5118ae8b1f
commit
99e9afe7b1
|
@ -1,5 +1,11 @@
|
|||
# Changelog of versions
|
||||
|
||||
### Version 0.7.1 (Unreleased)
|
||||
- Added: ISizeProvider interface (Optimization Helper)
|
||||
- Added: ISizeProvider into most Iterable implementations (Distinct/Filter/FlatMap/ArrayFlatMap don't support it, for obvious reasons)
|
||||
- Added: ToArray function into Iterable which uses ISizeProvider to reduce overhead of duplicating arrays.
|
||||
- Fixed: putIfAbsent now replaces defaultValues
|
||||
|
||||
### Version 0.7.0
|
||||
- Added: Over 11 Million Unit Tests to this library to ensure quality.
|
||||
- Added: ArrayList size constructor now throws IllegalStateException if the size parameter is negative
|
||||
|
|
|
@ -16,13 +16,14 @@ import speiger.src.collections.PACKAGE.functions.CONSUMER;
|
|||
#endif
|
||||
import speiger.src.collections.PACKAGE.utils.SPLIT_ITERATORS;
|
||||
import speiger.src.collections.PACKAGE.utils.COLLECTIONS;
|
||||
import speiger.src.collections.utils.ISizeProvider;
|
||||
import speiger.src.collections.utils.SanityChecks;
|
||||
|
||||
/**
|
||||
* A Type-Specific {@link Collection} that reduces (un)boxing
|
||||
* @Type(T)
|
||||
*/
|
||||
public interface COLLECTION KEY_GENERIC_TYPE extends Collection<CLASS_TYPE>, ITERABLE KEY_GENERIC_TYPE
|
||||
public interface COLLECTION KEY_GENERIC_TYPE extends Collection<CLASS_TYPE>, ITERABLE KEY_GENERIC_TYPE, ISizeProvider
|
||||
{
|
||||
#if !TYPE_OBJECT
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,7 @@ import speiger.src.collections.objects.collections.ObjectIterable;
|
|||
#else
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.Comparator;
|
||||
import speiger.src.collections.ints.functions.function.Int2ObjectFunction;
|
||||
|
||||
#endif
|
||||
import speiger.src.collections.PACKAGE.functions.function.TO_OBJECT_FUNCTION;
|
||||
|
@ -26,6 +27,7 @@ import speiger.src.collections.PACKAGE.utils.ASYNC_BUILDER;
|
|||
import speiger.src.collections.PACKAGE.utils.SPLIT_ITERATORS;
|
||||
import speiger.src.collections.PACKAGE.utils.ITERABLES;
|
||||
import speiger.src.collections.PACKAGE.utils.ITERATORS;
|
||||
import speiger.src.collections.utils.ISizeProvider;
|
||||
|
||||
/**
|
||||
* A Type-Specific {@link Iterable} that reduces (un)boxing
|
||||
|
@ -117,6 +119,7 @@ public interface ITERABLE KEY_GENERIC_TYPE extends Iterable<CLASS_TYPE>
|
|||
* @param <V> The return type supplier.
|
||||
* @param <E> The return type.
|
||||
* @return a new Iterable that returns the desired result
|
||||
* @note does not support TO_ARRAY optimizations.
|
||||
*/
|
||||
default <E, V extends Iterable<E>> ObjectIterable<E> flatMap(TO_OBJECT_FUNCTION KKS_GENERIC_TYPE<V> mapper) {
|
||||
return ITERABLES.flatMap(this, mapper);
|
||||
|
@ -127,6 +130,7 @@ public interface ITERABLE KEY_GENERIC_TYPE extends Iterable<CLASS_TYPE>
|
|||
* @param mapper the flatMapping function
|
||||
* @param <E> The return type.
|
||||
* @return a new Iterable that returns the desired result
|
||||
* @note does not support TO_ARRAY optimizations.
|
||||
*/
|
||||
default <E> ObjectIterable<E> arrayflatMap(TO_OBJECT_FUNCTION KKS_GENERIC_TYPE<E[]> mapper) {
|
||||
return ITERABLES.arrayFlatMap(this, mapper);
|
||||
|
@ -136,6 +140,7 @@ public interface ITERABLE KEY_GENERIC_TYPE extends Iterable<CLASS_TYPE>
|
|||
* A Helper function to reduce the usage of Streams and allows to filter out unwanted elements
|
||||
* @param filter the elements that should be kept.
|
||||
* @return a Iterable that filtered out all unwanted elements
|
||||
* @note does not support TO_ARRAY optimizations.
|
||||
*/
|
||||
default ITERABLE KEY_GENERIC_TYPE filter(PREDICATE KEY_GENERIC_TYPE filter) {
|
||||
return ITERABLES.filter(this, filter);
|
||||
|
@ -144,6 +149,7 @@ public interface ITERABLE KEY_GENERIC_TYPE extends Iterable<CLASS_TYPE>
|
|||
/**
|
||||
* A Helper function to reduce the usage of Streams and allows to filter out duplicated elements
|
||||
* @return a Iterable that filtered out all duplicated elements
|
||||
* @note does not support TO_ARRAY optimizations.
|
||||
*/
|
||||
default ITERABLE KEY_GENERIC_TYPE distinct() {
|
||||
return ITERABLES.distinct(this);
|
||||
|
@ -213,6 +219,44 @@ public interface ITERABLE KEY_GENERIC_TYPE extends Iterable<CLASS_TYPE>
|
|||
return pour(new LINKED_HASH_SETBRACES());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if TYPE_OBJECT
|
||||
/**
|
||||
* A Helper function that reduces the usage of streams and allows to collect all elements as a Array
|
||||
* @param action is the creator function of said Array to ensure type is kept.
|
||||
* @return a new Array of all elements
|
||||
*/
|
||||
default KEY_TYPE[] TO_ARRAY(Int2ObjectFunction<KEY_TYPE[]> action) {
|
||||
ISizeProvider prov = ISizeProvider.of(this);
|
||||
if(prov != null) {
|
||||
int size = prov.size();
|
||||
if(size >= 0) {
|
||||
KEY_TYPE[] array = action.get(size);
|
||||
ITERATORS.unwrap(array, iterator());
|
||||
return array;
|
||||
}
|
||||
}
|
||||
return ITERATORS.pour(iterator()).TO_ARRAY(action);
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* A Helper function that reduces the usage of streams and allows to collect all elements as a Array
|
||||
* @return a new Array of all elements
|
||||
*/
|
||||
default KEY_TYPE[] TO_ARRAY() {
|
||||
ISizeProvider prov = ISizeProvider.of(this);
|
||||
if(prov != null) {
|
||||
int size = prov.size();
|
||||
if(size >= 0) {
|
||||
KEY_TYPE[] array = NEW_KEY_ARRAY(size);
|
||||
ITERATORS.unwrap(array, iterator());
|
||||
return array;
|
||||
}
|
||||
}
|
||||
return ITERATORS.pour(iterator()).TO_ARRAY();
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Helper function to reduce stream usage that allows to filter for any matches.
|
||||
|
|
|
@ -1812,6 +1812,11 @@ public class CONCURRENT_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY
|
|||
insert(-slot-1, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
else if(VALUE_EQUALS(values[slot], getDefaultReturnValue())) {
|
||||
VALUE_TYPE oldValue = values[slot];
|
||||
values[slot] = value;
|
||||
return oldValue;
|
||||
}
|
||||
return values[slot];
|
||||
}
|
||||
finally {
|
||||
|
|
|
@ -270,6 +270,11 @@ public class CUSTOM_HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VAL
|
|||
insert(-slot-1, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
else if(VALUE_EQUALS(values[slot], getDefaultReturnValue())) {
|
||||
VALUE_TYPE oldValue = values[slot];
|
||||
values[slot] = value;
|
||||
return oldValue;
|
||||
}
|
||||
return values[slot];
|
||||
}
|
||||
|
||||
|
|
|
@ -245,6 +245,11 @@ public class HASH_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GENE
|
|||
insert(-slot-1, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
else if(VALUE_EQUALS(values[slot], getDefaultReturnValue())) {
|
||||
VALUE_TYPE oldValue = values[slot];
|
||||
values[slot] = value;
|
||||
return oldValue;
|
||||
}
|
||||
return values[slot];
|
||||
}
|
||||
|
||||
|
|
|
@ -202,6 +202,11 @@ public class ARRAY_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_GEN
|
|||
insertIndex(size++, key, value);
|
||||
return getDefaultReturnValue();
|
||||
}
|
||||
else if(VALUE_EQUALS(values[index], getDefaultReturnValue())) {
|
||||
VALUE_TYPE oldValue = values[index];
|
||||
values[index] = value;
|
||||
return oldValue;
|
||||
}
|
||||
return values[index];
|
||||
}
|
||||
|
||||
|
|
|
@ -161,7 +161,14 @@ public class ENUM_MAP KEY_ENUM_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE
|
|||
@Override
|
||||
public VALUE_TYPE putIfAbsent(T key, VALUE_TYPE value) {
|
||||
int index = key.ordinal();
|
||||
if(isSet(index)) return values[index];
|
||||
if(isSet(index)) {
|
||||
if(VALUE_EQUALS(values[index], getDefaultReturnValue())) {
|
||||
VALUE_TYPE oldValue = values[index];
|
||||
values[index] = value;
|
||||
return oldValue;
|
||||
}
|
||||
return values[index];
|
||||
}
|
||||
set(index);
|
||||
values[index] = value;
|
||||
return getDefaultReturnValue();
|
||||
|
|
|
@ -280,7 +280,10 @@ public class AVL_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_
|
|||
int compare = 0;
|
||||
Node KEY_VALUE_GENERIC_TYPE parent = tree;
|
||||
while(true) {
|
||||
if((compare = compare(key, parent.key)) == 0) return parent.value;
|
||||
if((compare = compare(key, parent.key)) == 0) {
|
||||
if(VALUE_EQUALS(parent.value, getDefaultReturnValue())) return parent.setValue(value);
|
||||
return parent.value;
|
||||
}
|
||||
if(compare < 0) {
|
||||
if(parent.left == null) break;
|
||||
parent = parent.left;
|
||||
|
|
|
@ -280,7 +280,10 @@ public class RB_TREE_MAP KEY_VALUE_GENERIC_TYPE extends ABSTRACT_MAP KEY_VALUE_G
|
|||
int compare = 0;
|
||||
Node KEY_VALUE_GENERIC_TYPE parent = tree;
|
||||
while(true) {
|
||||
if((compare = compare(key, parent.key)) == 0) return parent.value;
|
||||
if((compare = compare(key, parent.key)) == 0) {
|
||||
if(VALUE_EQUALS(parent.value, getDefaultReturnValue())) return parent.setValue(value);
|
||||
return parent.value;
|
||||
}
|
||||
if(compare < 0) {
|
||||
if(parent.left == null) break;
|
||||
parent = parent.left;
|
||||
|
|
|
@ -102,6 +102,26 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
|
|||
*/
|
||||
public VALUE_TYPE put(KEY_TYPE key, VALUE_TYPE value);
|
||||
|
||||
/**
|
||||
* A Helper method that allows to put int a MAP.Entry into a map.
|
||||
* @param entry then Entry that should be inserted.
|
||||
* @return the last present value or default return value.
|
||||
*/
|
||||
public default VALUE_TYPE put(Entry KEY_VALUE_GENERIC_TYPE entry) {
|
||||
return put(entry.ENTRY_KEY(), entry.ENTRY_VALUE());
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT || !VALUE_OBJECT
|
||||
/**
|
||||
* A Helper method that allows to put int a Map.Entry into a map.
|
||||
* @param entry then Entry that should be inserted.
|
||||
* @return the last present value or default return value.
|
||||
*/
|
||||
public default CLASS_VALUE_TYPE put(Map.Entry<CLASS_TYPE, CLASS_VALUE_TYPE> entry) {
|
||||
return put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Type Specific array method to bulk add elements into a map without creating a wrapper and increasing performances
|
||||
* @param keys the keys that should be added
|
||||
|
|
|
@ -25,6 +25,7 @@ import speiger.src.collections.PACKAGE.functions.function.PREDICATE;
|
|||
import speiger.src.collections.PACKAGE.sets.HASH_SET;
|
||||
import speiger.src.collections.PACKAGE.sets.SET;
|
||||
#endif
|
||||
import speiger.src.collections.utils.ISizeProvider;
|
||||
|
||||
/**
|
||||
* A Helper class for Iterables
|
||||
|
@ -247,7 +248,7 @@ public class ITERABLES
|
|||
return new WrappedIterableBRACES(iterable);
|
||||
}
|
||||
|
||||
private static class WrappedIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE
|
||||
private static class WrappedIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE, ISizeProvider
|
||||
{
|
||||
Iterable<? extends CLASS_TYPE> iterable;
|
||||
|
||||
|
@ -259,6 +260,12 @@ public class ITERABLES
|
|||
return ITERATORS.wrap(iterable.iterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
ISizeProvider prov = ISizeProvider.of(iterable);
|
||||
return prov == null ? -1 : prov.size();
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(CONSUMER action) {
|
||||
|
@ -273,7 +280,7 @@ public class ITERABLES
|
|||
#endif
|
||||
}
|
||||
|
||||
private static class MappedIterable KSS_GENERIC_TYPE<E, T> implements ObjectIterable<T>
|
||||
private static class MappedIterable KSS_GENERIC_TYPE<E, T> implements ObjectIterable<T>, ISizeProvider
|
||||
{
|
||||
ITERABLE KEY_SPECIAL_GENERIC_TYPE<E> iterable;
|
||||
TO_OBJECT_FUNCTION KSS_GENERIC_TYPE<E, T> mapper;
|
||||
|
@ -287,6 +294,12 @@ public class ITERABLES
|
|||
return ITERATORS.map(iterable.iterator(), mapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
ISizeProvider prov = ISizeProvider.of(this);
|
||||
return prov == null ? -1 : prov.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super T> action) {
|
||||
Objects.requireNonNull(action);
|
||||
|
@ -342,7 +355,7 @@ public class ITERABLES
|
|||
}
|
||||
}
|
||||
|
||||
private static class RepeatingIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE
|
||||
private static class RepeatingIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE, ISizeProvider
|
||||
{
|
||||
ITERABLE KEY_GENERIC_TYPE iterable;
|
||||
int repeats;
|
||||
|
@ -357,6 +370,12 @@ public class ITERABLES
|
|||
return ITERATORS.repeat(iterable.iterator(), repeats);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
ISizeProvider prov = ISizeProvider.of(iterable);
|
||||
return prov == null ? -1 : prov.size() * (repeats+1);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(CONSUMER action) {
|
||||
|
@ -407,7 +426,7 @@ public class ITERABLES
|
|||
#endif
|
||||
}
|
||||
|
||||
private static class LimitedIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE
|
||||
private static class LimitedIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE, ISizeProvider
|
||||
{
|
||||
ITERABLE KEY_GENERIC_TYPE iterable;
|
||||
long limit;
|
||||
|
@ -422,6 +441,12 @@ public class ITERABLES
|
|||
return ITERATORS.limit(iterable.iterator(), limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
ISizeProvider prov = ISizeProvider.of(iterable);
|
||||
return prov == null ? -1 : (int)Math.min(prov.size(), limit);
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(CONSUMER action) {
|
||||
|
@ -446,7 +471,7 @@ public class ITERABLES
|
|||
#endif
|
||||
}
|
||||
|
||||
private static class SortedIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE
|
||||
private static class SortedIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE, ISizeProvider
|
||||
{
|
||||
ITERABLE KEY_GENERIC_TYPE iterable;
|
||||
COMPARATOR KEY_GENERIC_TYPE sorter;
|
||||
|
@ -461,6 +486,12 @@ public class ITERABLES
|
|||
return ITERATORS.sorted(iterable.iterator(), sorter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
ISizeProvider prov = ISizeProvider.of(iterable);
|
||||
return prov == null ? -1 : prov.size();
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(CONSUMER action) {
|
||||
|
@ -520,7 +551,7 @@ public class ITERABLES
|
|||
#endif
|
||||
}
|
||||
|
||||
private static class PeekIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE
|
||||
private static class PeekIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE, ISizeProvider
|
||||
{
|
||||
ITERABLE KEY_GENERIC_TYPE iterable;
|
||||
CONSUMER KEY_GENERIC_TYPE action;
|
||||
|
@ -535,6 +566,12 @@ public class ITERABLES
|
|||
return ITERATORS.peek(iterable.iterator(), action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
ISizeProvider prov = ISizeProvider.of(iterable);
|
||||
return prov == null ? -1 : prov.size();
|
||||
}
|
||||
|
||||
#if !TYPE_OBJECT
|
||||
@Override
|
||||
public void forEach(CONSUMER action) {
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package speiger.src.collections.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Speiger
|
||||
*
|
||||
* This Interface is a Helper class to allow transfer the information through Iterators, without forcing a Implementation of a size method through it.
|
||||
* This is mainly used to optimize the toArray function.
|
||||
*
|
||||
*/
|
||||
public interface ISizeProvider
|
||||
{
|
||||
/** @return the size of the implementing Collection */
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* Gets a SizeProvider given the Iterable. May return null if it isn't a Collection or a SizeProvider.
|
||||
* @param iter the Iterable that you want the size of.
|
||||
* @return a SizeProvider if it is one or if it is a JavaCollection
|
||||
*/
|
||||
public static ISizeProvider of(Iterable<?> iter) {
|
||||
if(iter instanceof ISizeProvider) return (ISizeProvider)iter;
|
||||
if(iter instanceof Collection) return new CollectionSize((Collection<?>)iter);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collection implementation of the SizeProvider
|
||||
*/
|
||||
static class CollectionSize implements ISizeProvider
|
||||
{
|
||||
Collection<?> collection;
|
||||
|
||||
public CollectionSize(Collection<?> collection)
|
||||
{
|
||||
this.collection = collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return collection.size();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue