package speiger.src.collections.PACKAGE.utils; import java.util.Objects; #if TYPE_BOOLEAN import java.util.concurrent.atomic.AtomicInteger; #else if TYPE_OBJECT import java.util.Comparator; #endif import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; import speiger.src.collections.PACKAGE.collections.ITERABLE; import speiger.src.collections.PACKAGE.collections.COLLECTION; #if !TYPE_OBJECT import speiger.src.collections.objects.collections.ObjectIterable; import speiger.src.collections.objects.collections.ObjectIterator; import speiger.src.collections.PACKAGE.functions.CONSUMER; import speiger.src.collections.PACKAGE.functions.COMPARATOR; #endif import speiger.src.collections.PACKAGE.collections.ITERATOR; import speiger.src.collections.PACKAGE.functions.function.TO_OBJECT_FUNCTION; import speiger.src.collections.PACKAGE.functions.function.PREDICATE; import speiger.src.collections.utils.ISizeProvider; /** * A Helper class for Iterables */ public class ITERABLES { /** * A Helper function that maps a Java-Iterable into a new Type. * @param iterable the iterable that should be mapped * @param mapper the function that decides what the result turns into. * @Type(T) * @param The return type. * @return a iterable that is mapped to a new result */ public static GENERIC_KEY_SPECIAL_BRACES ObjectIterable map(Iterable iterable, TO_OBJECT_FUNCTION KKS_GENERIC_TYPE mapper) { return new MappedIterable<>(wrap(iterable), mapper); } /** * A Helper function that maps a Iterable into a new Type. * @param iterable the iterable that should be mapped * @param mapper the function that decides what the result turns into. * @Type(T) * @param The return type. * @return a iterable that is mapped to a new result */ public static GENERIC_KEY_SPECIAL_BRACES ObjectIterable map(ITERABLE KEY_GENERIC_TYPE iterable, TO_OBJECT_FUNCTION KKS_GENERIC_TYPE mapper) { return new MappedIterable<>(iterable, mapper); } /** * A Helper function that flatMaps a Java-Iterable into a new Type. * @param iterable the iterable that should be flatMapped * @param mapper the function that decides what the result turns into. * @Type(T) * @param The return type supplier. * @param The return type. * @return a iterable that is flatMapped to a new result */ public static GENERIC_KEY_SPECIAL_BRACES> ObjectIterable flatMap(Iterable iterable, TO_OBJECT_FUNCTION KKS_GENERIC_TYPE mapper) { return new FlatMappedIterable<>(wrap(iterable), mapper); } /** * A Helper function that flatMaps a Iterable into a new Type. * @param iterable the iterable that should be flatMapped * @param mapper the function that decides what the result turns into. * @Type(T) * @param The return type supplier. * @param The return type. * @return a iterable that is flatMapped to a new result */ public static GENERIC_KEY_SPECIAL_BRACES> ObjectIterable flatMap(ITERABLE KEY_GENERIC_TYPE iterable, TO_OBJECT_FUNCTION KKS_GENERIC_TYPE mapper) { return new FlatMappedIterable<>(iterable, mapper); } /** * A Helper function that flatMaps a Java-Iterable into a new Type. * @param iterable the iterable that should be flatMapped * @param mapper the function that decides what the result turns into. * @Type(T) * @param The return type. * @return a iterable that is flatMapped to a new result */ public static GENERIC_KEY_SPECIAL_BRACES ObjectIterable arrayFlatMap(Iterable iterable, TO_OBJECT_FUNCTION KKS_GENERIC_TYPE mapper) { return new FlatMappedArrayIterable<>(wrap(iterable), mapper); } /** * A Helper function that flatMaps a Iterable into a new Type. * @param iterable the iterable that should be flatMapped * @param mapper the function that decides what the result turns into. * @Type(T) * @param The return type. * @return a iterable that is flatMapped to a new result */ public static GENERIC_KEY_SPECIAL_BRACES ObjectIterable arrayFlatMap(ITERABLE KEY_GENERIC_TYPE iterable, TO_OBJECT_FUNCTION KKS_GENERIC_TYPE mapper) { return new FlatMappedArrayIterable<>(iterable, mapper); } /** * A Helper function that filters out all desired elements from a Java-Iterable * @param iterable that should be filtered. * @param filter the filter that decides that should be let through * @Type(T) * @return a filtered iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE filter(Iterable iterable, PREDICATE KEY_GENERIC_TYPE filter) { return new FilteredIterableBRACES(wrap(iterable), filter); } /** * A Helper function that filters out all desired elements * @param iterable that should be filtered. * @param filter the filter that decides that should be let through * @Type(T) * @return a filtered iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE filter(ITERABLE KEY_GENERIC_TYPE iterable, PREDICATE KEY_GENERIC_TYPE filter) { return new FilteredIterableBRACES(iterable, filter); } /** * A Helper function that filters out all duplicated elements. * @param iterable that should be distinct * @Type(T) * @return a distinct iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE distinct(ITERABLE KEY_GENERIC_TYPE iterable) { return new DistinctIterableBRACES(iterable); } /** * A Helper function that filters out all duplicated elements from a Java Iterable. * @param iterable that should be distinct * @Type(T) * @return a distinct iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE distinct(Iterable iterable) { return new DistinctIterableBRACES(wrap(iterable)); } /** * A Helper function that repeats the Iterable a specific amount of times * @param iterable that should be repeated * @param repeats the amount of times the iterable should be repeated * @Type(T) * @return a repeating iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE repeat(ITERABLE KEY_GENERIC_TYPE iterable, int repeats) { return new RepeatingIterableBRACES(iterable, repeats); } /** * A Helper function that repeats the Iterable a specific amount of times from a Java Iterable * @param iterable that should be repeated * @param repeats the amount of times the iterable should be repeated * @Type(T) * @return a repeating iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE repeat(Iterable iterable, int repeats) { return new RepeatingIterableBRACES(wrap(iterable), repeats); } /** * A Helper function that hard limits the Iterable to a specific size * @param iterable that should be limited * @param limit the amount of elements it should be limited to * @Type(T) * @return a limited iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE limit(ITERABLE KEY_GENERIC_TYPE iterable, long limit) { return new LimitedIterableBRACES(iterable, limit); } /** * A Helper function that hard limits the Iterable to a specific size from a Java Iterable * @param iterable that should be limited * @param limit the amount of elements it should be limited to * @Type(T) * @return a limited iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE limit(Iterable iterable, long limit) { return new LimitedIterableBRACES(wrap(iterable), limit); } /** * A Helper function that sorts the Iterable. * This operation is heavily hurting performance because it rebuilds the entire iterator and then sorts it. * @param iterable that should be sorted * @param sorter that sorts the iterable. Can be null. * @Type(T) * @return a sorted iterable. */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE sorted(ITERABLE KEY_GENERIC_TYPE iterable, COMPARATOR KEY_GENERIC_TYPE sorter) { return new SortedIterableBRACES(iterable, sorter); } /** * A Helper function that sorts the Iterable from a Java Iterable * This operation is heavily hurting performance because it rebuilds the entire iterator and then sorts it. * @param iterable that should be sorted * @param sorter that sorts the iterable. Can be null. * @Type(T) * @return a sorted iterable. */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE sorted(Iterable iterable, COMPARATOR KEY_GENERIC_TYPE sorter) { return new SortedIterableBRACES(wrap(iterable), sorter); } /** * A Helper function that allows to preview the result of a Iterable. * @param iterable that should be peeked at * @param action callback that receives the value before the iterable returns it * @Type(T) * @return a peeked iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE peek(ITERABLE KEY_GENERIC_TYPE iterable, CONSUMER KEY_GENERIC_TYPE action) { return new PeekIterableBRACES(iterable, action); } /** * A Helper function that allows to preview the result of a Iterable from a Java Iterable * @param iterable that should be peeked at * @param action callback that receives the value before the iterable returns it * @Type(T) * @return a peeked iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE peek(Iterable iterable, CONSUMER KEY_GENERIC_TYPE action) { return new PeekIterableBRACES(wrap(iterable), action); } /** * A Wrapper function that wraps a Java-Iterable into a Type Specific Iterable * @param iterable that should be wrapped * @Type(T) * @return a type specific iterable */ public static GENERIC_KEY_BRACES ITERABLE KEY_GENERIC_TYPE wrap(Iterable iterable) { return new WrappedIterableBRACES(iterable); } private static class WrappedIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE, ISizeProvider { Iterable iterable; public WrappedIterable(Iterable iterable) { this.iterable = iterable; } public ITERATOR KEY_GENERIC_TYPE iterator() { 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) { Objects.requireNonNull(action); iterable.forEach(action); } #else public void forEach(Consumer action) { Objects.requireNonNull(action); iterable.forEach(action); } #endif } private static class MappedIterable KSS_GENERIC_TYPE implements ObjectIterable, ISizeProvider { ITERABLE KEY_SPECIAL_GENERIC_TYPE iterable; TO_OBJECT_FUNCTION KSS_GENERIC_TYPE mapper; MappedIterable(ITERABLE KEY_SPECIAL_GENERIC_TYPE iterable, TO_OBJECT_FUNCTION KSS_GENERIC_TYPE mapper) { this.iterable = iterable; this.mapper = mapper; } public ObjectIterator iterator() { 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 action) { Objects.requireNonNull(action); iterable.forEach(E -> action.accept(mapper.apply(E))); } } private static class FlatMappedIterable KSS_GENERIC_TYPE> implements ObjectIterable { ITERABLE KEY_SPECIAL_GENERIC_TYPE iterable; TO_OBJECT_FUNCTION KSS_GENERIC_TYPE mapper; FlatMappedIterable(ITERABLE KEY_SPECIAL_GENERIC_TYPE iterable, TO_OBJECT_FUNCTION KSS_GENERIC_TYPE mapper) { this.iterable = iterable; this.mapper = mapper; } @Override public ObjectIterator iterator() { return ITERATORS.flatMap(iterable.iterator(), mapper); } @Override public void forEach(Consumer action) { Objects.requireNonNull(action); iterable.forEach(E -> mapper.apply(E).forEach(action)); } } private static class FlatMappedArrayIterable KSS_GENERIC_TYPE implements ObjectIterable { ITERABLE KEY_SPECIAL_GENERIC_TYPE iterable; TO_OBJECT_FUNCTION KSS_GENERIC_TYPE mapper; FlatMappedArrayIterable(ITERABLE KEY_SPECIAL_GENERIC_TYPE iterable, TO_OBJECT_FUNCTION KSS_GENERIC_TYPE mapper) { this.iterable = iterable; this.mapper = mapper; } @Override public ObjectIterator iterator() { return ITERATORS.arrayFlatMap(iterable.iterator(), mapper); } @Override public void forEach(Consumer action) { Objects.requireNonNull(action); iterable.forEach(E -> { T[] array = mapper.apply(E); for(int i = 0,m=array.length;i action) { Objects.requireNonNull(action); COLLECTION KEY_GENERIC_TYPE repeater = COLLECTIONS.wrapper(); iterable.forEach(T -> {action.accept(T); repeater.add(T);}); for(int i = 0;i { if(!filter.test(T)) action.accept(T); } ); } #else public void forEach(Consumer action) { Objects.requireNonNull(action); iterable.forEach(T -> { if(!filter.test(T)) action.accept(T); } ); } #endif } private static class LimitedIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE, ISizeProvider { ITERABLE KEY_GENERIC_TYPE iterable; long limit; public LimitedIterable(ITERABLE KEY_GENERIC_TYPE iterable, long limit) { this.iterable = iterable; this.limit = limit; } @Override public ITERATOR KEY_GENERIC_TYPE iterator() { 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) { Objects.requireNonNull(action); AtomicLong counter = new AtomicLong(); iterable.forEach(T -> { if(counter.get() >= limit) return; counter.incrementAndGet(); action.accept(T); }); } #else public void forEach(Consumer action) { Objects.requireNonNull(action); AtomicLong counter = new AtomicLong(); iterable.forEach(T -> { if(counter.get() >= limit) return; counter.incrementAndGet(); action.accept(T); }); } #endif } private static class SortedIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE, ISizeProvider { ITERABLE KEY_GENERIC_TYPE iterable; COMPARATOR KEY_GENERIC_TYPE sorter; public SortedIterable(ITERABLE KEY_GENERIC_TYPE iterable, COMPARATOR KEY_GENERIC_TYPE sorter) { this.iterable = iterable; this.sorter = sorter; } @Override public ITERATOR KEY_GENERIC_TYPE iterator() { 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) { Objects.requireNonNull(action); COLLECTIONS.CollectionWrapper KEY_GENERIC_TYPE wrapper = COLLECTIONS.wrapper(); iterable.forEach(wrapper::add); wrapper.unstableSort(sorter); wrapper.forEach(action); } #else @Override public void forEach(Consumer action) { Objects.requireNonNull(action); COLLECTIONS.CollectionWrapper KEY_GENERIC_TYPE wrapper = COLLECTIONS.wrapper(); iterable.forEach(wrapper::add); wrapper.unstableSort(sorter); wrapper.forEach(action); } #endif } private static class DistinctIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE { ITERABLE KEY_GENERIC_TYPE iterable; public DistinctIterable(ITERABLE KEY_GENERIC_TYPE iterable) { this.iterable = iterable; } @Override public ITERATOR KEY_GENERIC_TYPE iterator() { return ITERATORS.distinct(iterable.iterator()); } #if !TYPE_OBJECT @Override public void forEach(CONSUMER action) { Objects.requireNonNull(action); #if TYPE_BOOLEAN AtomicInteger result = new AtomicInteger(); iterable.forEach(T -> { if(((result.get() & (T ? 2 : 1)) != 0)) return; result.getAndAdd(T ? 2 : 1); action.accept(T); }); #else COLLECTION KEY_GENERIC_TYPE filtered = COLLECTIONS.distinctWrapper(); iterable.forEach(T -> { if(filtered.add(T)) action.accept(T); }); #endif } #else public void forEach(Consumer action) { Objects.requireNonNull(action); COLLECTION KEY_GENERIC_TYPE filtered = COLLECTIONS.distinctWrapper(); iterable.forEach(T -> { if(filtered.add(T)) action.accept(T); }); } #endif } private static class PeekIterable KEY_GENERIC_TYPE implements ITERABLE KEY_GENERIC_TYPE, ISizeProvider { ITERABLE KEY_GENERIC_TYPE iterable; CONSUMER KEY_GENERIC_TYPE action; public PeekIterable(ITERABLE KEY_GENERIC_TYPE iterable, CONSUMER KEY_GENERIC_TYPE action) { this.iterable = iterable; this.action = action; } @Override public ITERATOR KEY_GENERIC_TYPE iterator() { 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) { Objects.requireNonNull(action); iterable.forEach(this.action.andThen(action)); } #else public void forEach(Consumer action) { Objects.requireNonNull(action); iterable.forEach(this.action.andThen(action)); } #endif } }