New Compute function and better toArray implementations

This commit is contained in:
Speiger 2023-06-05 23:40:48 +02:00
parent 0f9751bf70
commit 63ef68fb95
10 changed files with 4130 additions and 3749 deletions

View File

@ -1,5 +1,13 @@
# Changelog of versions # Changelog of versions
### Version 0.8.1
- Added: getFirst/getLast/removeFirst/removeLast to List.class.
- Added: Dedicated Set toArray implementations.
- Added: ToArray/pushTop functions to Stack.class.
- Added: ComputeNonDefault functions which will contain the current behavior of the Compute function, while the Compute will be changed to be more java compliant!
- Fixed: SetValue wasn't working on forEach implementations.
### Version 0.8.0 ### Version 0.8.0
- Added: getFirst/getLast/removeFirst/removeLast to Lists - Added: getFirst/getLast/removeFirst/removeLast to Lists
- Added: Dedicated implementations for toArray into TreeSets - Added: Dedicated implementations for toArray into TreeSets

View File

@ -1,5 +1,7 @@
package speiger.src.collections.PACKAGE.collections; package speiger.src.collections.PACKAGE.collections;
import java.util.NoSuchElementException;
import speiger.src.collections.utils.Stack; import speiger.src.collections.utils.Stack;
/** /**
@ -14,6 +16,14 @@ public interface STACK
*/ */
public void push(KEY_TYPE e); public void push(KEY_TYPE e);
/**
* Helper function that pushes the top element on top of the stack again.
* @throws NoSuchElementException if the stack is empty
*/
public default void pushTop() {
push(top());
}
/** /**
* Removes the Object on top of the stack. * Removes the Object on top of the stack.
* @return the element that is on top of the stack * @return the element that is on top of the stack
@ -59,4 +69,19 @@ public interface STACK
public default boolean isEmpty() { public default boolean isEmpty() {
return size() == 0; return size() == 0;
} }
/**
* A method to drop the contents of the Stack without clearing the stack
* @Type(E)
* @return the contents of the stack into a seperate array.
*/
public default GENERIC_SPECIAL_KEY_BRACES<E> KEY_SPECIAL_TYPE[] TO_ARRAY() { return TO_ARRAY(NEW_SPECIAL_KEY_ARRAY(size())); }
/**
* A method to drop the contents of the Stack without clearing the stack
* @param input where the elements should be inserted to. If it does not fit then it creates a new appropiatly created array
* @Type(E)
* @return the contents of the stack into a seperate array.
* @note if the Type is generic then a Object Array is created instead of a Type Array
*/
public GENERIC_SPECIAL_KEY_BRACES<E> KEY_SPECIAL_TYPE[] TO_ARRAY(KEY_SPECIAL_TYPE[] input);
} }

View File

@ -201,6 +201,26 @@ public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap<CL
@Override @Override
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) { public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction); Objects.requireNonNull(mappingFunction);
#if !VALUE_OBJECT
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, GET_VALUE(key));
#else
VALUE_TYPE value = GET_VALUE(key);
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, value);
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
if(VALUE_EQUALS_NOT(value, getDefaultReturnValue()) || containsKey(key)) {
remove(key);
return getDefaultReturnValue();
}
return getDefaultReturnValue();
}
#endif
put(key, newValue);
return newValue;
}
@Override
public VALUE_TYPE COMPUTENonDefault(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
VALUE_TYPE value = GET_VALUE(key); VALUE_TYPE value = GET_VALUE(key);
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, value); VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, value);
if(VALUE_EQUALS(newValue, getDefaultReturnValue())) { if(VALUE_EQUALS(newValue, getDefaultReturnValue())) {
@ -217,6 +237,29 @@ public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap<CL
@Override @Override
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) { public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction); Objects.requireNonNull(mappingFunction);
#if VALUE_OBJECT
VALUE_TYPE value;
if((value = GET_VALUE(key)) == getDefaultReturnValue() || !containsKey(key)) {
VALUE_TYPE newValue = mappingFunction.APPLY(key);
if(VALUE_EQUALS_NOT(newValue, getDefaultReturnValue())) {
put(key, newValue);
return newValue;
}
}
return value;
#else
if(!containsKey(key)) {
VALUE_TYPE newValue = mappingFunction.APPLY(key);
put(key, newValue);
return newValue;
}
return get(key);
#endif
}
@Override
public VALUE_TYPE COMPUTE_IF_ABSENTNonDefault(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
VALUE_TYPE value; VALUE_TYPE value;
if((value = GET_VALUE(key)) == getDefaultReturnValue() || !containsKey(key)) { if((value = GET_VALUE(key)) == getDefaultReturnValue() || !containsKey(key)) {
VALUE_TYPE newValue = mappingFunction.APPLY(key); VALUE_TYPE newValue = mappingFunction.APPLY(key);
@ -231,6 +274,29 @@ public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap<CL
@Override @Override
public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) { public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
Objects.requireNonNull(valueProvider); Objects.requireNonNull(valueProvider);
#if VALUE_OBJECT
VALUE_TYPE value;
if((value = GET_VALUE(key)) == getDefaultReturnValue() || !containsKey(key)) {
VALUE_TYPE newValue = valueProvider.VALUE_SUPPLY_GET();
if(VALUE_EQUALS_NOT(newValue, getDefaultReturnValue())) {
put(key, newValue);
return newValue;
}
}
return value;
#else
if(!containsKey(key)) {
VALUE_TYPE newValue = valueProvider.VALUE_SUPPLY_GET();
put(key, newValue);
return newValue;
}
return get(key);
#endif
}
@Override
public VALUE_TYPE SUPPLY_IF_ABSENTNonDefault(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider) {
Objects.requireNonNull(valueProvider);
VALUE_TYPE value; VALUE_TYPE value;
if((value = GET_VALUE(key)) == getDefaultReturnValue() || !containsKey(key)) { if((value = GET_VALUE(key)) == getDefaultReturnValue() || !containsKey(key)) {
VALUE_TYPE newValue = valueProvider.VALUE_SUPPLY_GET(); VALUE_TYPE newValue = valueProvider.VALUE_SUPPLY_GET();
@ -245,6 +311,29 @@ public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap<CL
@Override @Override
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) { public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction); Objects.requireNonNull(mappingFunction);
#if VALUE_OBJECT
VALUE_TYPE value;
if(VALUE_EQUALS_NOT((value = GET_VALUE(key)), getDefaultReturnValue()) || containsKey(key)) {
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, value);
if(VALUE_EQUALS_NOT(newValue, getDefaultReturnValue())) {
put(key, newValue);
return newValue;
}
remove(key);
}
#else
if(containsKey(key)) {
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, GET_VALUE(key));
put(key, newValue);
return newValue;
}
#endif
return getDefaultReturnValue();
}
@Override
public VALUE_TYPE COMPUTE_IF_PRESENTNonDefault(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction);
VALUE_TYPE value; VALUE_TYPE value;
if(VALUE_EQUALS_NOT((value = GET_VALUE(key)), getDefaultReturnValue()) || containsKey(key)) { if(VALUE_EQUALS_NOT((value = GET_VALUE(key)), getDefaultReturnValue()) || containsKey(key)) {
VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, value); VALUE_TYPE newValue = mappingFunction.APPLY_VALUE(key, value);
@ -256,7 +345,7 @@ public abstract class ABSTRACT_MAP KEY_VALUE_GENERIC_TYPE extends AbstractMap<CL
} }
return getDefaultReturnValue(); return getDefaultReturnValue();
} }
@Override @Override
public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) { public VALUE_TYPE MERGE(KEY_TYPE key, VALUE_TYPE value, VALUE_UNARY_OPERATOR VALUE_VALUE_GENERIC_TYPE mappingFunction) {
Objects.requireNonNull(mappingFunction); Objects.requireNonNull(mappingFunction);

View File

@ -389,6 +389,15 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
* @return the result of the computation * @return the result of the computation
*/ */
public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction); public VALUE_TYPE COMPUTE(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction);
/**
* A Type Specific compute method to reduce boxing/unboxing
* If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null".
* A "Null Value" will be treated as "Do not insert/remove" based on how the Java has specified it.
* @param key the key that should be computed
* @param mappingFunction the operator that should generate the value
* @return the result of the computation
*/
public VALUE_TYPE COMPUTENonDefault(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction);
/** /**
* A Type Specific computeIfAbsent method to reduce boxing/unboxing * A Type Specific computeIfAbsent method to reduce boxing/unboxing
* If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null". * If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null".
@ -398,7 +407,15 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
* @return the result of the computed value or present value * @return the result of the computed value or present value
*/ */
public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction); public VALUE_TYPE COMPUTE_IF_ABSENT(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction);
/**
* A Type Specific computeIfAbsent method to reduce boxing/unboxing
* If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null".
* A "Null Value" will be treated as "Do not insert/remove" based on how the Java has specified it.
* @param key the key that should be computed
* @param mappingFunction the operator that should generate the value if not present
* @return the result of the computed value or present value
*/
public VALUE_TYPE COMPUTE_IF_ABSENTNonDefault(KEY_TYPE key, FUNCTION KEY_VALUE_GENERIC_TYPE mappingFunction);
/** /**
* A Supplier based computeIfAbsent function to fill the most used usecase of this function * A Supplier based computeIfAbsent function to fill the most used usecase of this function
* If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null". * If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null".
@ -408,6 +425,15 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
* @return the result of the computed value or present value * @return the result of the computed value or present value
*/ */
public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider); public VALUE_TYPE SUPPLY_IF_ABSENT(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider);
/**
* A Supplier based computeIfAbsent function to fill the most used usecase of this function
* If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null".
* A "Null Value" will be treated as "Do not insert/remove" based on how the Java has specified it.
* @param key the key that should be computed
* @param valueProvider the value if not present
* @return the result of the computed value or present value
*/
public VALUE_TYPE SUPPLY_IF_ABSENTNonDefault(KEY_TYPE key, VALUE_SUPPLIER VALUE_GENERIC_TYPE valueProvider);
/** /**
* A Type Specific compute method to reduce boxing/unboxing * A Type Specific compute method to reduce boxing/unboxing
* If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null". * If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null".
@ -418,6 +444,16 @@ public interface MAP KEY_VALUE_GENERIC_TYPE extends Map<CLASS_TYPE, CLASS_VALUE_
* @note if not present then compute is not executed * @note if not present then compute is not executed
*/ */
public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction); public VALUE_TYPE COMPUTE_IF_PRESENT(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction);
/**
* A Type Specific compute method to reduce boxing/unboxing
* If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null".
* A "Null Value" will be treated as "Do not insert/remove" based on how the Java has specified it.
* @param key the key that should be computed
* @param mappingFunction the operator that should generate the value if present
* @return the result of the default return value or present value
* @note if not present then compute is not executed
*/
public VALUE_TYPE COMPUTE_IF_PRESENTNonDefault(KEY_TYPE key, UNARY_OPERATOR KEY_VALUE_GENERIC_TYPE mappingFunction);
/** /**
* A Type Specific merge method to reduce boxing/unboxing * A Type Specific merge method to reduce boxing/unboxing
* If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null". * If the generated value equals the getDefaultReturnValue it will simply not insert it since that is treated as "null".

View File

@ -1,5 +1,8 @@
package speiger.src.collections.utils; package speiger.src.collections.utils;
import java.util.Collection;
import java.util.NoSuchElementException;
import java.util.function.IntFunction;
/** /**
* The Stack Interface represents the Last-In-First-Out layout (LIFO). * The Stack Interface represents the Last-In-First-Out layout (LIFO).
@ -16,6 +19,14 @@ public interface Stack<T>
*/ */
public void push(T e); public void push(T e);
/**
* Helper function that pushes the top element on top of the stack again.
* @throws NoSuchElementException if the stack is empty
*/
public default void pushTop() {
push(top());
}
/** /**
* Removes the Object on top of the stack. * Removes the Object on top of the stack.
* @return the element that is on top of the stack * @return the element that is on top of the stack
@ -59,4 +70,33 @@ public interface Stack<T>
* @throws ArrayIndexOutOfBoundsException if the index is out of bounds * @throws ArrayIndexOutOfBoundsException if the index is out of bounds
*/ */
public T peek(int index); public T peek(int index);
/**
* A method to drop the contents of the Queue without clearing the queue
* @param <E> the keyType of elements maintained by this Collection
* @return the contents of the queue into a seperate array.
*/
public default <E> E[] toArray() {
return toArray((E[])new Object[size()]);
}
/**
* A method to drop the contents of the Stack without clearing the stack
* @param array where the elements should be inserted to. If it does not fit then it creates a new appropriately created array
* @param <E> the keyType of elements maintained by this Collection
* @return the contents of the stack into a separate array.
* @note if the Type is generic then a Object Array is created instead of a Type Array
*/
public <E> E[] toArray(E[] array);
/**
* A Helper function that simplifies the process of creating a new Array.
* @param action the array creation function
* @param <E> the returning arrayType
* @return an array containing all of the elements in this collection
* @see Collection#toArray(Object[])
*/
public default <E> E[] toArray(IntFunction<E[]> action) {
return toArray(action.apply(size()));
}
} }