diff --git a/Changelog.md b/Changelog.md index 6e4f56dd..047ae0c8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,10 @@ ### Version 0.4.5 - Added: removeAll/retainAll(Collection c, Consumer r) which receives all the elements that got deleted from the collection +- Fixed: Supplier get function wasn't referencing original function. +- Added: addIfPresent/Absent to lists +- Added: distinct, limit and peek iterators +- Added: Iterable's can now reduce its contents ### Version 0.4.4 - Fixed: ObjectArrayList.of was causing crashes because of a Poor implementation. diff --git a/src/builder/resources/speiger/assets/collections/templates/collections/Iterable.template b/src/builder/resources/speiger/assets/collections/templates/collections/Iterable.template index b859fa0b..f3c94c05 100644 --- a/src/builder/resources/speiger/assets/collections/templates/collections/Iterable.template +++ b/src/builder/resources/speiger/assets/collections/templates/collections/Iterable.template @@ -10,6 +10,7 @@ import speiger.src.collections.objects.collections.ObjectIterable; import speiger.src.collections.PACKAGE.functions.function.TO_OBJECT_FUNCTION; import speiger.src.collections.objects.functions.consumer.BI_FROM_OBJECT_CONSUMER; import speiger.src.collections.PACKAGE.functions.function.PREDICATE; +import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR; import speiger.src.collections.PACKAGE.collections.SPLIT_ITERATOR; import speiger.src.collections.PACKAGE.utils.SPLIT_ITERATORS; import speiger.src.collections.PACKAGE.utils.ITERABLES; @@ -171,6 +172,43 @@ public interface ITERABLE KEY_GENERIC_TYPE extends Iterable return EMPTY_VALUE; } + /** + * Performs a reduction on the + * elements of this Iterable + * @param operator the operation that should be applied + * @param identity the start value + * @return the reduction result, returns identity if nothing was found + */ + default KEY_TYPE reduce(KEY_TYPE identity, UNARY_OPERATOR KEY_KEY_GENERIC_TYPE operator) { + Objects.requireNonNull(operator); + KEY_TYPE state = identity; + for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) { + state = operator.APPLY_VALUE(state, iter.NEXT()); + } + return state; + } + + /** + * Performs a reduction on the + * elements of this Iterable + * @param operator the operation that should be applied + * @return the reduction result, returns null value if nothing was found + */ + default KEY_TYPE reduce(UNARY_OPERATOR KEY_KEY_GENERIC_TYPE operator) { + Objects.requireNonNull(operator); + KEY_TYPE state = EMPTY_VALUE; + boolean empty = true; + for(ITERATOR KEY_GENERIC_TYPE iter = iterator();iter.hasNext();) { + if(empty) { + empty = false; + state = iter.NEXT(); + continue; + } + state = operator.APPLY_VALUE(state, iter.NEXT()); + } + return state; + } + /** * Helper function to reduce stream usage that allows to count the valid elements. * @param filter that should be applied diff --git a/src/builder/resources/speiger/assets/collections/templates/functions/Supplier.template b/src/builder/resources/speiger/assets/collections/templates/functions/Supplier.template index 38856bb2..c90c528f 100644 --- a/src/builder/resources/speiger/assets/collections/templates/functions/Supplier.template +++ b/src/builder/resources/speiger/assets/collections/templates/functions/Supplier.template @@ -16,7 +16,7 @@ public interface SUPPLIER KEY_GENERIC_TYPE * @return the supplied value */ public KEY_TYPE GET_KEY(); -#if JDK_TYPE && PRIMITIVE +#if JDK_TYPE && PRIMITIVES @Override public default KEY_TYPE GET_JAVA() { diff --git a/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template b/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template index c5422df5..d25a53c8 100644 --- a/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template +++ b/src/builder/resources/speiger/assets/collections/templates/lists/ArrayList.template @@ -29,6 +29,7 @@ import speiger.src.collections.PACKAGE.functions.CONSUMER; #endif import speiger.src.collections.objects.functions.consumer.BI_FROM_OBJECT_CONSUMER; import speiger.src.collections.PACKAGE.functions.function.PREDICATE; +import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR; import speiger.src.collections.PACKAGE.utils.ARRAYS; import speiger.src.collections.PACKAGE.utils.ITERATORS; #if TYPE_OBJECT @@ -650,6 +651,32 @@ public class ARRAY_LIST KEY_GENERIC_TYPE extends ABSTRACT_LIST KEY_GENERIC_TYPE return EMPTY_VALUE; } + @Override + public KEY_TYPE reduce(KEY_TYPE identity, UNARY_OPERATOR KEY_KEY_GENERIC_TYPE operator) { + Objects.requireNonNull(operator); + KEY_TYPE state = identity; + for(int i = 0;i iterator) { + return new DistinctIteratorBRACES(wrap(iterator)); + } + + /** + * A Helper function that hard limits the Iterator to a specific size + * @param iterator that should be limited + * @param limit the amount of elements it should be limited to + * @Type(T) + * @return a limited iterator + */ + public static GENERIC_KEY_BRACES ITERATOR KEY_GENERIC_TYPE limit(ITERATOR KEY_GENERIC_TYPE iterator, long limit) { + return new LimitedIteratorBRACES(iterator, limit); + } + + /** + * A Helper function that hard limits the Iterator to a specific size from a Java Iterator + * @param iterator that should be limited + * @param limit the amount of elements it should be limited to + * @Type(T) + * @return a limited iterator + */ + public static GENERIC_KEY_BRACES ITERATOR KEY_GENERIC_TYPE limit(Iterator iterator, long limit) { + return new LimitedIteratorBRACES(wrap(iterator), limit); + } + + /** + * A Helper function that allows to preview the result of a Iterator. + * @param iterator that should be peeked at + * @param action callback that receives the value before the iterator returns it + * @Type(T) + * @return a peeked iterator + */ + public static GENERIC_KEY_BRACES ITERATOR KEY_GENERIC_TYPE peek(ITERATOR KEY_GENERIC_TYPE iterator, CONSUMER KEY_GENERIC_TYPE action) { + return new PeekIteratorBRACES(iterator, action); + } + + /** + * A Helper function that allows to preview the result of a Iterator from a Java Iterator + * @param iterator that should be peeked at + * @param action callback that receives the value before the iterator returns it + * @Type(T) + * @return a peeked iterator + */ + public static GENERIC_KEY_BRACES ITERATOR KEY_GENERIC_TYPE peek(Iterator iterator, CONSUMER KEY_GENERIC_TYPE action) { + return new PeekIteratorBRACES(wrap(iterator), action); + } + /** * Helper function to convert a Object Iterator into a Primitive Iterator * @param iterator that should be converted to a unboxing iterator @@ -799,6 +871,57 @@ public class ITERATORS } } + private static class DistinctIterator KEY_GENERIC_TYPE implements ITERATOR KEY_GENERIC_TYPE + { + ITERATOR KEY_GENERIC_TYPE iterator; +#if TYPE_BOOLEAN + int filtered; +#else + SET KEY_GENERIC_TYPE filtered = new HASH_SETBRACES(); +#endif + KEY_TYPE lastFound; + boolean foundNext = false; + + public DistinctIterator(ITERATOR KEY_GENERIC_TYPE iterator) { + this.iterator = iterator; + } + + void compute() { + if(foundNext) return; +#if TYPE_BOOLEAN + if(filtered == 3) return; +#endif + while(iterator.hasNext()) { + lastFound = iterator.NEXT(); +#if TYPE_BOOLEAN + if((filtered & (lastFound ? 1 : 2)) == 0) { + filtered |= (lastFound ? 1 : 2); + foundNext = true; + break; + } +#else + if(filtered.add(lastFound)) { + foundNext = true; + break; + } +#endif + } + } + + @Override + public boolean hasNext() { + compute(); + return foundNext; + } + + @Override + public KEY_TYPE NEXT() { + if(!hasNext()) throw new IllegalStateException("End of Iterator"); + foundNext = false; + return lastFound; + } + } + private static class FilteredIterator KEY_GENERIC_TYPE implements ITERATOR KEY_GENERIC_TYPE { ITERATOR KEY_GENERIC_TYPE iterator; @@ -835,4 +958,51 @@ public class ITERATORS return lastFound; } } + + private static class LimitedIterator KEY_GENERIC_TYPE implements ITERATOR KEY_GENERIC_TYPE + { + ITERATOR KEY_GENERIC_TYPE iterator; + long limit; + + public LimitedIterator(ITERATOR KEY_GENERIC_TYPE iterator, long limit) { + this.iterator = iterator; + this.limit = limit; + } + + @Override + public boolean hasNext() { + return limit > 0 && iterator.hasNext(); + } + + @Override + public KEY_TYPE NEXT() { + if(!hasNext()) throw new IllegalStateException("End of Iterator"); + limit--; + return iterator.NEXT(); + } + } + + private static class PeekIterator KEY_GENERIC_TYPE implements ITERATOR KEY_GENERIC_TYPE + { + ITERATOR KEY_GENERIC_TYPE iterator; + CONSUMER KEY_GENERIC_TYPE action; + + public PeekIterator(ITERATOR KEY_GENERIC_TYPE iterator, CONSUMER KEY_GENERIC_TYPE action) { + this.iterator = iterator; + this.action = action; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public KEY_TYPE NEXT() { + if(!hasNext()) throw new IllegalStateException("End of Iterator"); + KEY_TYPE result = iterator.NEXT(); + action.accept(result); + return result; + } + } } \ No newline at end of file diff --git a/src/builder/resources/speiger/assets/collections/templates/utils/PriorityQueues.template b/src/builder/resources/speiger/assets/collections/templates/utils/PriorityQueues.template index 25b20cb7..54932184 100644 --- a/src/builder/resources/speiger/assets/collections/templates/utils/PriorityQueues.template +++ b/src/builder/resources/speiger/assets/collections/templates/utils/PriorityQueues.template @@ -17,6 +17,7 @@ import speiger.src.collections.PACKAGE.queues.PRIORITY_QUEUE; import speiger.src.collections.PACKAGE.functions.CONSUMER; #endif import speiger.src.collections.PACKAGE.functions.function.PREDICATE; +import speiger.src.collections.PACKAGE.functions.function.UNARY_OPERATOR; import speiger.src.collections.objects.functions.consumer.BI_FROM_OBJECT_CONSUMER; /** @@ -131,6 +132,10 @@ public class PRIORITY_QUEUES @Override public KEY_TYPE findFirst(PREDICATE KEY_GENERIC_TYPE filter) { synchronized(mutex) { return queue.findFirst(filter); } } @Override + public KEY_TYPE reduce(KEY_TYPE identity, UNARY_OPERATOR KEY_KEY_GENERIC_TYPE operator) { synchronized(mutex) { return queue.reduce(identity, operator); } } + @Override + public KEY_TYPE reduce(UNARY_OPERATOR KEY_KEY_GENERIC_TYPE operator) { synchronized(mutex) { return queue.reduce(operator); } } + @Override public int count(PREDICATE KEY_GENERIC_TYPE filter) { synchronized(mutex) { return queue.count(filter); } } }