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:
Speiger 2022-11-20 08:56:23 +01:00
parent 5118ae8b1f
commit 99e9afe7b1
13 changed files with 197 additions and 10 deletions

View File

@ -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

View File

@ -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
/**

View File

@ -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.

View File

@ -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 {

View File

@ -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];
}

View File

@ -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];
}

View File

@ -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];
}

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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) {

View File

@ -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();
}
}
}