diff options
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/funcdata')
6 files changed, 587 insertions, 272 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java index c680879..9574376 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java @@ -14,6 +14,7 @@ import java.util.function.Predicate; import bjc.utils.data.GenHolder; import bjc.utils.data.IHolder; +import bjc.utils.data.IPair; import bjc.utils.data.Pair; import java.util.ArrayList; @@ -28,7 +29,7 @@ import java.util.ArrayList; * @param <E> * The type in this list */ -public class FunctionalList<E> implements Cloneable { +public class FunctionalList<E> implements Cloneable, IFunctionalList<E> { /** * The list used as a backing store */ @@ -57,27 +58,6 @@ public class FunctionalList<E> implements Cloneable { } /** - * Create a functional list using the same backing list as the provided - * list. - * - * @param sourceList - * The source for a backing list - */ - public FunctionalList(FunctionalList<E> sourceList) { - if (sourceList == null) { - throw new NullPointerException("Source list must be non-null"); - } - - // Find out if this should make a copy of the source's wrapped list - // instead. - // - // I've decided it shouldn't. Call clone() if that's what you want. - // This method just creates another list that refers to the - // source's backing list - wrappedList = sourceList.wrappedList; - } - - /** * Create a new functional list with the specified size. * * @param size @@ -102,26 +82,18 @@ public class FunctionalList<E> implements Cloneable { wrappedList = backingList; } - /** - * Add an item to this list - * - * @param item - * The item to add to this list. - * @return Whether the item was added to the list succesfully. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#add(E) */ + @Override public boolean add(E item) { return wrappedList.add(item); } - /** - * Check if all of the elements of this list match the specified - * predicate. - * - * @param matchPredicate - * The predicate to use for checking. - * @return Whether all of the elements of the list match the specified - * predicate. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#allMatch(java.util.function.Predicate) */ + @Override public boolean allMatch(Predicate<E> matchPredicate) { if (matchPredicate == null) { throw new NullPointerException("Predicate must be non-null"); @@ -138,14 +110,10 @@ public class FunctionalList<E> implements Cloneable { return true; } - /** - * Check if any of the elements in this list match the specified list. - * - * @param matchPredicate - * The predicate to use for checking. - * @return Whether any element in the list matches the provided - * predicate. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#anyMatch(java.util.function.Predicate) */ + @Override public boolean anyMatch(Predicate<E> matchPredicate) { if (matchPredicate == null) { throw new NullPointerException("Predicate must be not null"); @@ -163,8 +131,8 @@ public class FunctionalList<E> implements Cloneable { } @Override - public FunctionalList<E> clone() { - FunctionalList<E> clonedList = new FunctionalList<>(); + public IFunctionalList<E> clone() { + IFunctionalList<E> clonedList = new FunctionalList<>(); for (E element : wrappedList) { clonedList.add(element); @@ -173,27 +141,12 @@ public class FunctionalList<E> implements Cloneable { return clonedList; } - /** - * Combine this list with another one into a new list and merge the - * results. Works sort of like a combined zip/map over resulting pairs. - * Does not change the underlying list. - * - * NOTE: The returned list will have the length of the shorter of this - * list and the combined one. - * - * @param <T> - * The type of the second list - * @param <F> - * The type of the combined list - * - * @param rightList - * The list to combine with - * @param itemCombiner - * The function to use for combining element pairs. - * @return A new list containing the merged pairs of lists. - */ - public <T, F> FunctionalList<F> combineWith( - FunctionalList<T> rightList, + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#combineWith(bjc.utils.funcdata.IFunctionalList, java.util.function.BiFunction) + */ + @Override + public <T, F> IFunctionalList<F> combineWith( + IFunctionalList<T> rightList, BiFunction<E, T, F> itemCombiner) { if (rightList == null) { throw new NullPointerException( @@ -202,7 +155,7 @@ public class FunctionalList<E> implements Cloneable { throw new NullPointerException("Combiner must not be null"); } - FunctionalList<F> returnedList = new FunctionalList<>(); + IFunctionalList<F> returnedList = new FunctionalList<>(); // Get the iterator for the other list Iterator<T> rightIterator = rightList.toIterable().iterator(); @@ -220,23 +173,19 @@ public class FunctionalList<E> implements Cloneable { return returnedList; } - /** - * Check if the list contains the specified item - * - * @param item - * The item to see if it is contained - * @return Whether or not the specified item is in the list + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#contains(E) */ + @Override public boolean contains(E item) { // Check if any items in the list match the provided item return this.anyMatch(item::equals); } - /** - * Get the first element in the list - * - * @return The first element in this list. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#first() */ + @Override public E first() { if (wrappedList.size() < 1) { throw new NoSuchElementException( @@ -246,29 +195,21 @@ public class FunctionalList<E> implements Cloneable { return wrappedList.get(0); } - /** - * Apply a function to each member of the list, then flatten the - * results. Does not change the underlying list. - * - * @param <T> - * The type of the flattened list - * - * @param elementExpander - * The function to apply to each member of the list. - * @return A new list containing the flattened results of applying the - * provided function. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#flatMap(java.util.function.Function) */ - public <T> FunctionalList<T> flatMap( - Function<E, FunctionalList<T>> elementExpander) { + @Override + public <T> IFunctionalList<T> flatMap( + Function<E, IFunctionalList<T>> elementExpander) { if (elementExpander == null) { throw new NullPointerException("Expander must not be null"); } - FunctionalList<T> returnedList = new FunctionalList<>( + IFunctionalList<T> returnedList = new FunctionalList<>( this.wrappedList.size()); forEach(element -> { - FunctionalList<T> expandedElement = elementExpander + IFunctionalList<T> expandedElement = elementExpander .apply(element); if (expandedElement == null) { @@ -283,12 +224,10 @@ public class FunctionalList<E> implements Cloneable { return returnedList; } - /** - * Apply a given action for each member of the list - * - * @param action - * The action to apply to each member of the list. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#forEach(java.util.function.Consumer) */ + @Override public void forEach(Consumer<E> action) { if (action == null) { throw new NullPointerException("Action is null"); @@ -297,13 +236,10 @@ public class FunctionalList<E> implements Cloneable { wrappedList.forEach(action); } - /** - * Apply a given function to each element in the list and its index. - * - * @param indexedAction - * The function to apply to each element in the list and its - * index. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#forEachIndexed(java.util.function.BiConsumer) */ + @Override public void forEachIndexed(BiConsumer<Integer, E> indexedAction) { if (indexedAction == null) { throw new NullPointerException("Action must not be null"); @@ -322,13 +258,10 @@ public class FunctionalList<E> implements Cloneable { }); } - /** - * Retrieve a value in the list by its index. - * - * @param index - * The index to retrieve a value from. - * @return The value at the specified index in the list. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#getByIndex(int) */ + @Override public E getByIndex(int index) { return wrappedList.get(index); } @@ -342,19 +275,16 @@ public class FunctionalList<E> implements Cloneable { return wrappedList; } - /** - * Retrieve a list containing all elements matching a predicate - * - * @param matchPredicate - * The predicate to match by - * @return A list containing all elements that match the predicate + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#getMatching(java.util.function.Predicate) */ - public FunctionalList<E> getMatching(Predicate<E> matchPredicate) { + @Override + public IFunctionalList<E> getMatching(Predicate<E> matchPredicate) { if (matchPredicate == null) { throw new NullPointerException("Predicate must not be null"); } - FunctionalList<E> returnedList = new FunctionalList<>(); + IFunctionalList<E> returnedList = new FunctionalList<>(); wrappedList.forEach((element) -> { if (matchPredicate.test(element)) { @@ -366,41 +296,32 @@ public class FunctionalList<E> implements Cloneable { return returnedList; } - /** - * Retrieve the size of the wrapped list - * - * @return The size of the wrapped list + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#getSize() */ + @Override public int getSize() { return wrappedList.size(); } - /** - * Check if this list is empty. - * - * @return Whether or not this list is empty. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#isEmpty() */ + @Override public boolean isEmpty() { return wrappedList.isEmpty(); } - /** - * Create a new list by applying the given function to each element in - * the list. Does not change the underlying list. - * - * @param <T> - * The type of the transformed list - * - * @param elementTransformer - * The function to apply to each element in the list - * @return A new list containing the mapped elements of this list. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#map(java.util.function.Function) */ - public <T> FunctionalList<T> map(Function<E, T> elementTransformer) { + @Override + public <T> IFunctionalList<T> map(Function<E, T> elementTransformer) { if (elementTransformer == null) { throw new NullPointerException("Transformer must be not null"); } - FunctionalList<T> returnedList = new FunctionalList<>( + IFunctionalList<T> returnedList = new FunctionalList<>( this.wrappedList.size()); forEach(element -> { @@ -411,30 +332,20 @@ public class FunctionalList<E> implements Cloneable { return returnedList; } - /** - * Zip two lists into a list of pairs - * - * @param <T> - * The type of the second list - * - * @param rightList - * The list to use as the left side of the pair - * @return A list containing pairs of this element and the specified - * list + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#pairWith(bjc.utils.funcdata.IFunctionalList) */ - public <T> FunctionalList<Pair<E, T>> pairWith( - FunctionalList<T> rightList) { + @Override + public <T> IFunctionalList<IPair<E, T>> pairWith( + IFunctionalList<T> rightList) { return combineWith(rightList, Pair<E, T>::new); } - /** - * Partition this list into a list of sublists - * - * @param numberPerPartition - * The size of elements to put into each one of the sublists - * @return A list partitioned into partitions of size nPerPart + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#partition(int) */ - public FunctionalList<FunctionalList<E>> partition( + @Override + public IFunctionalList<IFunctionalList<E>> partition( int numberPerPartition) { if (numberPerPartition < 1 || numberPerPartition > wrappedList.size()) { @@ -443,10 +354,10 @@ public class FunctionalList<E> implements Cloneable { + wrappedList.size()); } - FunctionalList<FunctionalList<E>> returnedList = new FunctionalList<>(); + IFunctionalList<IFunctionalList<E>> returnedList = new FunctionalList<>(); // The current partition being filled - GenHolder<FunctionalList<E>> currentPartition = new GenHolder<>( + GenHolder<IFunctionalList<E>> currentPartition = new GenHolder<>( new FunctionalList<>()); this.forEach((element) -> { @@ -472,29 +383,23 @@ public class FunctionalList<E> implements Cloneable { * Check if a partition has room for another item */ private Boolean isPartitionFull(int numberPerPartition, - GenHolder<FunctionalList<E>> currentPartition) { + GenHolder<IFunctionalList<E>> currentPartition) { return currentPartition.unwrap( (partition) -> partition.getSize() >= numberPerPartition); } - /** - * Prepend an item to the list - * - * @param item - * The item to prepend to the list + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#prepend(E) */ + @Override public void prepend(E item) { wrappedList.add(0, item); } - /** - * Select a random item from this list, using the provided random - * number generator. - * - * @param rnd - * The random number generator to use. - * @return A random element from this list. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#randItem(java.util.Random) */ + @Override public E randItem(Random rnd) { if (rnd == null) { throw new NullPointerException( @@ -506,25 +411,10 @@ public class FunctionalList<E> implements Cloneable { return wrappedList.get(randomIndex); } - /** - * Reduce this list to a single value, using a accumulative approach. - * - * @param <T> - * The in-between type of the values - * @param <F> - * The final value type - * - * @param initialValue - * The initial value of the accumulative state. - * @param stateAccumulator - * The function to use to combine a list element with the - * accumulative state. - * @param resultTransformer - * The function to use to convert the accumulative state - * into a final result. - * @return A single value condensed from this list and transformed into - * its final state. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#reduceAux(T, java.util.function.BiFunction, java.util.function.Function) */ + @Override public <T, F> F reduceAux(T initialValue, BiFunction<E, T, T> stateAccumulator, Function<T, F> resultTransformer) { @@ -547,13 +437,10 @@ public class FunctionalList<E> implements Cloneable { return currentState.unwrap(resultTransformer); } - /** - * Remove all elements that match a given predicate - * - * @param removePredicate - * The predicate to use to determine elements to delete - * @return Whether there was anything that satisfied the predicate + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#removeIf(java.util.function.Predicate) */ + @Override public boolean removeIf(Predicate<E> removePredicate) { if (removePredicate == null) { throw new NullPointerException("Predicate must be non-null"); @@ -562,28 +449,18 @@ public class FunctionalList<E> implements Cloneable { return wrappedList.removeIf(removePredicate); } - /** - * Remove all parameters that match a given parameter - * - * @param desiredElement - * The object to remove all matching copies of + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#removeMatching(E) */ + @Override public void removeMatching(E desiredElement) { removeIf((element) -> element.equals(desiredElement)); } - /** - * Perform a binary search for the specified key using the provided - * means of comparing elements. Since this IS a binary search, the list - * must have been sorted before hand. - * - * @param searchKey - * The key to search for. - * @param comparator - * The way to compare elements for searching. Pass null to - * use the natural ordering for E - * @return The element if it is in this list, or null if it is not. + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#search(E, java.util.Comparator) */ + @Override public E search(E searchKey, Comparator<E> comparator) { // Search our internal list int foundIndex = Collections.binarySearch(wrappedList, searchKey, @@ -598,23 +475,18 @@ public class FunctionalList<E> implements Cloneable { return null; } - /** - * Sort the elements of this list using the provided way of comparing - * elements. Does change the underlying list. - * - * @param comparator - * The way to compare elements for sorting. Pass null to use - * E's natural ordering + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#sort(java.util.Comparator) */ + @Override public void sort(Comparator<E> comparator) { Collections.sort(wrappedList, comparator); } - /** - * Convert the list into a iterable - * - * @return An iterable view onto the list + /* (non-Javadoc) + * @see bjc.utils.funcdata.IFunctionalList#toIterable() */ + @Override public Iterable<E> toIterable() { return wrappedList; } diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java index 0453988..fc4c4de 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java @@ -2,27 +2,40 @@ package bjc.utils.funcdata; import java.util.HashMap; import java.util.Map; +import java.util.function.BiConsumer; import java.util.function.Function; import bjc.utils.data.Pair; /** - * Functional wrapper over map providing some useful things + * Basic implementation of {@link IFunctionalMap} * * @author ben - * + * * @param <K> - * The type of this map's keys + * The type of the map's keys * @param <V> - * The type of this map's values - * + * The type of the map's values */ -public class FunctionalMap<K, V> { - private final class TransformedMap<V2> extends FunctionalMap<K, V2> { - private FunctionalMap<K, V> mapToTransform; - private Function<V, V2> transformer; +public class FunctionalMap<K, V> implements IFunctionalMap<K, V> { + /** + * A map that transforms values from one type to another + * + * @author ben + * + * @param <K> + * The type of the map's keys + * @param <V> + * The type of the map's values + * @param <V2> + * The type of the transformed values + */ + private static final class TransformedValueMap<K, V, V2> + implements IFunctionalMap<K, V2> { + private IFunctionalMap<K, V> mapToTransform; + private Function<V, V2> transformer; - public TransformedMap(FunctionalMap<K, V> destMap, + public TransformedValueMap(IFunctionalMap<K, V> destMap, Function<V, V2> transform) { mapToTransform = destMap; transformer = transform; @@ -42,6 +55,40 @@ public class FunctionalMap<K, V> { public String toString() { return mapToTransform.toString(); } + + @Override + public V2 put(K key, V2 val) { + throw new UnsupportedOperationException( + "Can't add items to transformed map"); + } + + @Override + public <V3> IFunctionalMap<K, V3> mapValues( + Function<V2, V3> transform) { + return new TransformedValueMap<>(this, transform); + } + + @Override + public IFunctionalList<K> keyList() { + return mapToTransform.keyList(); + } + + @Override + public void forEach(BiConsumer<K, V2> action) { + mapToTransform.forEach((key, val) -> { + action.accept(key, transformer.apply(val)); + }); + } + + @Override + public V2 remove(K key) { + return transformer.apply(mapToTransform.remove(key)); + } + + @Override + public int getSize() { + return mapToTransform.getSize(); + } } private Map<K, V> wrappedMap; @@ -84,18 +131,12 @@ public class FunctionalMap<K, V> { } } - /** - * Add an entry to the map - * - * @param key - * The key to put the value under - * @param val - * The value to add - * @return The previous value of the key in the map, or null if the key - * wasn't in the map. However, note that it may also return - * null if the key was set to null. + /* + * (non-Javadoc) * + * @see bjc.utils.funcdata.IFunctionalMap#put(K, V) */ + @Override public V put(K key, V val) { if (key == null) { throw new NullPointerException("Key must not be null"); @@ -104,15 +145,12 @@ public class FunctionalMap<K, V> { return wrappedMap.put(key, val); } - /** - * Get the value assigned to the given key - * - * @param key - * The key to look for a value under - * @return The value of the key - * + /* + * (non-Javadoc) * + * @see bjc.utils.funcdata.IFunctionalMap#get(K) */ + @Override public V get(K key) { if (key == null) { throw new NullPointerException("Key must not be null"); @@ -126,35 +164,28 @@ public class FunctionalMap<K, V> { return wrappedMap.get(key); } - /** - * Transform the values returned by this map. + /* + * (non-Javadoc) * - * NOTE: This transform is applied once for each lookup of a value, so - * the transform passed should be a proper function, or things will - * likely not work as expected. - * - * @param <V2> - * The new type of returned values - * @param transformer - * The function to use to transform values - * @return The map where each value will be transformed after lookup + * @see bjc.utils.funcdata.IFunctionalMap#mapValues(java.util.function. + * Function) */ - public <V2> FunctionalMap<K, V2> mapValues( + @Override + public <V2> IFunctionalMap<K, V2> mapValues( Function<V, V2> transformer) { if (transformer == null) { throw new NullPointerException("Transformer must not be null"); } - return new TransformedMap<>(this, transformer); + return new TransformedValueMap<>(this, transformer); } - /** - * Check if this map contains the specified key + /* + * (non-Javadoc) * - * @param key - * The key to check - * @return Whether or not the map contains the key + * @see bjc.utils.funcdata.IFunctionalMap#containsKey(K) */ + @Override public boolean containsKey(K key) { return wrappedMap.containsKey(key); } @@ -163,4 +194,30 @@ public class FunctionalMap<K, V> { public String toString() { return wrappedMap.toString(); } + + @Override + public IFunctionalList<K> keyList() { + FunctionalList<K> keys = new FunctionalList<>(); + + wrappedMap.keySet().forEach((key) -> { + keys.add(key); + }); + + return keys; + } + + @Override + public void forEach(BiConsumer<K, V> action) { + wrappedMap.forEach(action); + } + + @Override + public V remove(K key) { + return wrappedMap.remove(key); + } + + @Override + public int getSize() { + return wrappedMap.size(); + } }
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalStringTokenizer.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalStringTokenizer.java index 9ef59fb..0e2d199 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalStringTokenizer.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalStringTokenizer.java @@ -137,13 +137,13 @@ public class FunctionalStringTokenizer { * The function to use to convert tokens. * @return A list containing all of the converted tokens. */ - public <E> FunctionalList<E> toList( + public <E> IFunctionalList<E> toList( Function<String, E> tokenTransformer) { if (tokenTransformer == null) { throw new NullPointerException("Transformer must not be null"); } - FunctionalList<E> returnList = new FunctionalList<>(); + IFunctionalList<E> returnList = new FunctionalList<>(); // Add each token to the list after transforming it forEachToken(token -> { @@ -160,7 +160,7 @@ public class FunctionalStringTokenizer { * * @return This tokenizer, converted into a list of strings */ - public FunctionalList<String> toList() { + public IFunctionalList<String> toList() { return toList((String element) -> element); } diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java new file mode 100644 index 0000000..a017aa9 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java @@ -0,0 +1,281 @@ +package bjc.utils.funcdata; + +import java.util.Comparator; +import java.util.Random; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; + +import bjc.utils.data.IPair; + +/** + * A wrapper over another list that provides eager functional operations + * over it. Differs from a stream in every way except for the fact that + * they both provide functional operations. + * + * @author ben + * + * @param <E> + * The type in this list + */ +public interface IFunctionalList<E> { + + /** + * Add an item to this list + * + * @param item + * The item to add to this list. + * @return Whether the item was added to the list succesfully. + */ + boolean add(E item); + + /** + * Check if all of the elements of this list match the specified + * predicate. + * + * @param matchPredicate + * The predicate to use for checking. + * @return Whether all of the elements of the list match the specified + * predicate. + */ + boolean allMatch(Predicate<E> matchPredicate); + + /** + * Check if any of the elements in this list match the specified list. + * + * @param matchPredicate + * The predicate to use for checking. + * @return Whether any element in the list matches the provided + * predicate. + */ + boolean anyMatch(Predicate<E> matchPredicate); + + /** + * Combine this list with another one into a new list and merge the + * results. Works sort of like a combined zip/map over resulting pairs. + * Does not change the underlying list. + * + * NOTE: The returned list will have the length of the shorter of this + * list and the combined one. + * + * @param <T> + * The type of the second list + * @param <F> + * The type of the combined list + * + * @param rightList + * The list to combine with + * @param itemCombiner + * The function to use for combining element pairs. + * @return A new list containing the merged pairs of lists. + */ + <T, F> IFunctionalList<F> combineWith(IFunctionalList<T> rightList, + BiFunction<E, T, F> itemCombiner); + + /** + * Check if the list contains the specified item + * + * @param item + * The item to see if it is contained + * @return Whether or not the specified item is in the list + */ + boolean contains(E item); + + /** + * Get the first element in the list + * + * @return The first element in this list. + */ + E first(); + + /** + * Apply a function to each member of the list, then flatten the + * results. Does not change the underlying list. + * + * @param <T> + * The type of the flattened list + * + * @param elementExpander + * The function to apply to each member of the list. + * @return A new list containing the flattened results of applying the + * provided function. + */ + <T> IFunctionalList<T> flatMap( + Function<E, IFunctionalList<T>> elementExpander); + + /** + * Apply a given action for each member of the list + * + * @param action + * The action to apply to each member of the list. + */ + void forEach(Consumer<E> action); + + /** + * Apply a given function to each element in the list and its index. + * + * @param indexedAction + * The function to apply to each element in the list and its + * index. + */ + void forEachIndexed(BiConsumer<Integer, E> indexedAction); + + /** + * Retrieve a value in the list by its index. + * + * @param index + * The index to retrieve a value from. + * @return The value at the specified index in the list. + */ + E getByIndex(int index); + + /** + * Retrieve a list containing all elements matching a predicate + * + * @param matchPredicate + * The predicate to match by + * @return A list containing all elements that match the predicate + */ + IFunctionalList<E> getMatching(Predicate<E> matchPredicate); + + /** + * Retrieve the size of the wrapped list + * + * @return The size of the wrapped list + */ + int getSize(); + + /** + * Check if this list is empty. + * + * @return Whether or not this list is empty. + */ + boolean isEmpty(); + + /** + * Create a new list by applying the given function to each element in + * the list. Does not change the underlying list. + * + * @param <T> + * The type of the transformed list + * + * @param elementTransformer + * The function to apply to each element in the list + * @return A new list containing the mapped elements of this list. + */ + <T> IFunctionalList<T> map(Function<E, T> elementTransformer); + + /** + * Zip two lists into a list of pairs + * + * @param <T> + * The type of the second list + * + * @param rightList + * The list to use as the left side of the pair + * @return A list containing pairs of this element and the specified + * list + */ + <T> IFunctionalList<IPair<E, T>> pairWith( + IFunctionalList<T> rightList); + + /** + * Partition this list into a list of sublists + * + * @param numberPerPartition + * The size of elements to put into each one of the sublists + * @return A list partitioned into partitions of size nPerPart + */ + IFunctionalList<IFunctionalList<E>> partition(int numberPerPartition); + + /** + * Prepend an item to the list + * + * @param item + * The item to prepend to the list + */ + void prepend(E item); + + /** + * Select a random item from this list, using the provided random + * number generator. + * + * @param rnd + * The random number generator to use. + * @return A random element from this list. + */ + E randItem(Random rnd); + + /** + * Reduce this list to a single value, using a accumulative approach. + * + * @param <T> + * The in-between type of the values + * @param <F> + * The final value type + * + * @param initialValue + * The initial value of the accumulative state. + * @param stateAccumulator + * The function to use to combine a list element with the + * accumulative state. + * @param resultTransformer + * The function to use to convert the accumulative state + * into a final result. + * @return A single value condensed from this list and transformed into + * its final state. + */ + <T, F> F reduceAux(T initialValue, + BiFunction<E, T, T> stateAccumulator, + Function<T, F> resultTransformer); + + /** + * Remove all elements that match a given predicate + * + * @param removePredicate + * The predicate to use to determine elements to delete + * @return Whether there was anything that satisfied the predicate + */ + boolean removeIf(Predicate<E> removePredicate); + + /** + * Remove all parameters that match a given parameter + * + * @param desiredElement + * The object to remove all matching copies of + */ + void removeMatching(E desiredElement); + + /** + * Perform a binary search for the specified key using the provided + * means of comparing elements. Since this IS a binary search, the list + * must have been sorted before hand. + * + * @param searchKey + * The key to search for. + * @param comparator + * The way to compare elements for searching. Pass null to + * use the natural ordering for E + * @return The element if it is in this list, or null if it is not. + */ + E search(E searchKey, Comparator<E> comparator); + + /** + * Sort the elements of this list using the provided way of comparing + * elements. Does change the underlying list. + * + * @param comparator + * The way to compare elements for sorting. Pass null to use + * E's natural ordering + */ + void sort(Comparator<E> comparator); + + /** + * Convert the list into a iterable + * + * @return An iterable view onto the list + */ + Iterable<E> toIterable(); +}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java new file mode 100644 index 0000000..9bd62bc --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java @@ -0,0 +1,104 @@ +package bjc.utils.funcdata; + +import java.util.function.BiConsumer; +import java.util.function.Function; + +/** + * Functional wrapper over map providing some useful things + * + * @author ben + * + * @param <K> + * The type of this map's keys + * @param <V> + * The type of this map's values + * + */ +public interface IFunctionalMap<K, V> { + + /** + * Add an entry to the map + * + * @param key + * The key to put the value under + * @param val + * The value to add + * @return The previous value of the key in the map, or null if the key + * wasn't in the map. However, note that it may also return + * null if the key was set to null. + * + * @throws UnsupportedOperationException + * if the map implementation doesn't support modifying the + * map + */ + V put(K key, V val); + + /** + * Get the value assigned to the given key + * + * @param key + * The key to look for a value under + * @return The value of the key + * + * + */ + V get(K key); + + /** + * Transform the values returned by this map. + * + * NOTE: This transform is applied once for each lookup of a value, so + * the transform passed should be a proper function, or things will + * likely not work as expected. + * + * @param <V2> + * The new type of returned values + * @param transformer + * The function to use to transform values + * @return The map where each value will be transformed after lookup + */ + <V2> IFunctionalMap<K, V2> mapValues(Function<V, V2> transformer); + + /** + * Check if this map contains the specified key + * + * @param key + * The key to check + * @return Whether or not the map contains the key + */ + boolean containsKey(K key); + + /** + * Get a list of all the keys in this map + * + * @return A list of all the keys in this map + */ + IFunctionalList<K> keyList(); + + /** + * Execute an action for each entry in the map + * + * @param action + * the action to execute for each entry in the map + */ + void forEach(BiConsumer<K, V> action); + + /** + * Remove the value bound to the key + * + * @param key + * The key to remove from the map + * @return The previous value for the key in the map, or null if the + * key wasn't in the class. NOTE: Just because you recieved + * null, doesn't mean the map wasn't changed. It may mean that + * someone put a null value for that key into the map + */ + V remove(K key); + + /** + * Get the number of entries in this map + * + * @return The number of entries in this map + */ + int getSize(); +}
\ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTree.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTree.java index fa92f85..67b9985 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTree.java +++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTree.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.function.Predicate; import bjc.utils.funcdata.FunctionalList; +import bjc.utils.funcdata.IFunctionalList; import bjc.utils.funcdata.bst.ITreePart.TreeLinearizationMethod; /** @@ -68,7 +69,7 @@ public class BinarySearchTree<T> { * time, but also O(N) space. */ public void balance() { - FunctionalList<T> elements = new FunctionalList<>(); + IFunctionalList<T> elements = new FunctionalList<>(); // Add each element to the list in sorted order rootElement.forEach(TreeLinearizationMethod.INORDER, @@ -123,7 +124,7 @@ public class BinarySearchTree<T> { * The distance from the pivot * @return Whether the adjusted pivot is with the list */ - private boolean adjustedPivotInBounds(FunctionalList<T> elements, + private boolean adjustedPivotInBounds(IFunctionalList<T> elements, int pivot, int pivotAdjustment) { return (pivot - pivotAdjustment) >= 0 && (pivot + pivotAdjustment) < elements.getSize(); |
