summaryrefslogtreecommitdiff
path: root/BJC-Utils2/src/main/java/bjc
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2016-04-08 13:28:09 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2016-04-08 13:28:09 -0400
commit275a627719fc2231b16caea41130ff09f0f2b6a1 (patch)
tree757e8ca2061ba6ed9b2063f7155edbe954b72bdb /BJC-Utils2/src/main/java/bjc
parent79d3a4a47cbc1fcf17c77c6fc12ff826a3077bac (diff)
Switch functional data to use interfaces
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc')
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GeneralCommandMode.java69
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java59
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java23
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHelp.java26
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java16
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java9
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/Pair.java5
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java13
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java316
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java147
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalStringTokenizer.java6
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java281
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java104
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/bst/BinarySearchTree.java5
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java64
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcutils/FileUtils.java77
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcutils/FuncUtils.java44
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java57
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gen/RandomGrammar.java18
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java89
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java11
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/graph/AdjacencyMap.java55
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java58
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gui/ExtensionFileFilter.java10
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gui/ListParameterPanel.java4
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gui/awt/ExtensionFileFilter.java10
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java5
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java32
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java17
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java6
30 files changed, 1153 insertions, 483 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GeneralCommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GeneralCommandMode.java
index 4a41c1c..880e8c5 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GeneralCommandMode.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GeneralCommandMode.java
@@ -1,10 +1,11 @@
package bjc.utils.cli;
-import java.util.HashMap;
-import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.IFunctionalMap;
+
/**
* A general command mode, with a customizable set of commands
*
@@ -16,17 +17,19 @@ import java.util.function.Consumer;
*
*/
public class GeneralCommandMode implements ICommandMode {
- private Map<String, ICommandHandler> commandHandlers;
- private String customPrompt;
+ private IFunctionalMap<String, ICommand> commandHandlers;
+ private IFunctionalMap<String, ICommand> defaultHandlers;
+
+ private IFunctionalMap<String, ICommandHelp> helpTopics;
- private Map<String, ICommandHandler> defaultHandlers;
+ private BiConsumer<String, String[]> unknownCommandHandler;
- private Consumer<String> errorOutput;
- private String modeName;
+ private Consumer<String> errorOutput;
+ private Consumer<String> normalOutput;
- private Consumer<String> normalOutput;
+ private String modeName;
- private BiConsumer<String, String[]> unknownCommandHandler;
+ private String customPrompt;
/**
* Create a new general command mode
@@ -41,20 +44,35 @@ public class GeneralCommandMode implements ICommandMode {
this.normalOutput = normalOutput;
this.errorOutput = errorOutput;
- commandHandlers = new HashMap<>();
- defaultHandlers = new HashMap<>();
+ commandHandlers = new FunctionalMap<>();
+ defaultHandlers = new FunctionalMap<>();
- defaultHandlers.put("list", (args) -> {
+ defaultHandlers.put("list", new GenericCommand((args) -> {
listCommands();
return this;
- });
+ }, "list\tList available command",
+ "Lists all of the commands available in this mode,"
+ + " as well as the commands that are valid in any mode."));
- defaultHandlers.put("alias", (args) -> {
+ defaultHandlers.put("alias", new GenericCommand((args) -> {
aliasCommands(args);
return this;
- });
+ }, "alias\tAlias one command to another",
+ "alias gives a command another name it can be invoked by. It is invoked"
+ + " with two arguments, the name of the command to alias"
+ + ", and the alias to give that command."));
+
+ defaultHandlers.put("help", new GenericCommand((args) -> {
+ // TODO implement help system
+ return this;
+ }, "help\tConsult the help system",
+ "help consults the internal help system."
+ + " It can be invoked in two ways. Invoking it with no arguments"
+ + " causes it to print out all the topics you can ask for details on,"
+ + " while invoking it with the name of a topic will print the entry"
+ + " for that topic"));
}
/**
@@ -100,8 +118,7 @@ public class GeneralCommandMode implements ICommandMode {
* if the specified command already has a handler
* registered
*/
- public void addCommandHandler(String command,
- ICommandHandler handler) {
+ public void addCommandHandler(String command, ICommand handler) {
if (command == null) {
throw new NullPointerException("Command must not be null");
} else if (handler == null) {
@@ -162,14 +179,14 @@ public class GeneralCommandMode implements ICommandMode {
normalOutput.accept(
"The available commands for this mode are as follows:\n");
- commandHandlers.keySet().forEach((commandName) -> {
+ commandHandlers.keyList().forEach((commandName) -> {
normalOutput.accept("\t" + commandName);
});
normalOutput.accept(
"\nThe following commands are available in all modes:\n");
- defaultHandlers.keySet().forEach((commandName) -> {
+ defaultHandlers.keyList().forEach((commandName) -> {
normalOutput.accept("\t" + commandName);
});
@@ -181,14 +198,11 @@ public class GeneralCommandMode implements ICommandMode {
normalOutput.accept("\n");
if (defaultHandlers.containsKey(command)) {
- return defaultHandlers.get(command).handle(args);
+ return defaultHandlers.get(command).getHandler().handle(args);
} else if (commandHandlers.containsKey(command)) {
- return commandHandlers.get(command).handle(args);
+ return commandHandlers.get(command).getHandler().handle(args);
} else {
- if (unknownCommandHandler == null) {
- throw new UnsupportedOperationException(
- "Command " + command + " is invalid.");
- } else if (args != null) {
+ if (args != null) {
errorOutput.accept("ERROR: Unrecognized command " + command
+ String.join(" ", args));
} else {
@@ -196,6 +210,11 @@ public class GeneralCommandMode implements ICommandMode {
.accept("ERROR: Unrecognized command " + command);
}
+ if (unknownCommandHandler == null) {
+ throw new UnsupportedOperationException(
+ "Command " + command + " is invalid.");
+ }
+
unknownCommandHandler.accept(command, args);
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
new file mode 100644
index 0000000..99951cc
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommand.java
@@ -0,0 +1,59 @@
+package bjc.utils.cli;
+
+/**
+ * Generic command implementation
+ *
+ * @author ben
+ *
+ */
+public class GenericCommand implements ICommand {
+ private static class GenericHelp implements ICommandHelp {
+ private String summary;
+ private String description;
+
+ public GenericHelp(String summary, String description) {
+ this.summary = summary;
+ this.description = description;
+ }
+
+ @Override
+ public String getSummary() {
+ return summary;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ }
+
+ private ICommandHandler handler;
+ private ICommandHelp help;
+
+ /**
+ * Create a new generic command
+ *
+ * @param handler
+ * The handler to use for the command
+ * @param description
+ * The description of the command
+ * @param help
+ * The detailed help message for the command
+ */
+ public GenericCommand(ICommandHandler handler, String description,
+ String help) {
+ this.handler = handler;
+ this.help = new GenericHelp(description, help);
+ }
+
+ @Override
+ public ICommandHandler getHandler() {
+ return handler;
+ }
+
+ @Override
+ public ICommandHelp getHelp() {
+ return help;
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java
new file mode 100644
index 0000000..681986d
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java
@@ -0,0 +1,23 @@
+package bjc.utils.cli;
+
+/**
+ * Represents a command that can be invoked from a {@link ICommandMode}
+ *
+ * @author ben
+ *
+ */
+public interface ICommand {
+ /**
+ * Get the handler that executes this command
+ *
+ * @return The handler that executes this command
+ */
+ public ICommandHandler getHandler();
+
+ /**
+ * Get the help entry for this command
+ *
+ * @return The help entry for this command
+ */
+ public ICommandHelp getHelp();
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHelp.java b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHelp.java
new file mode 100644
index 0000000..ad03dac
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommandHelp.java
@@ -0,0 +1,26 @@
+package bjc.utils.cli;
+
+/**
+ * Interface for the help entry for a command
+ *
+ * @author ben
+ *
+ */
+public interface ICommandHelp {
+ /**
+ * Get the summary line for a command
+ *
+ * Used for 'help commands' which gives the user a brief idea what all
+ * the commands do
+ *
+ * @return The summary line line for a command
+ */
+ public String getSummary();
+
+ /**
+ * Get the description of a command
+ *
+ * @return The description of a command
+ */
+ public String getDescription();
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java b/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java
index 4aea0d6..37c94f6 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/FileComponentRepository.java
@@ -2,14 +2,15 @@ package bjc.utils.components;
import java.io.File;
import java.nio.file.Path;
-import java.util.HashMap;
-import java.util.Map;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.IFunctionalList;
+import bjc.utils.funcdata.IFunctionalMap;
/**
* A component repository that loads its components from files in a
@@ -29,7 +30,7 @@ public class FileComponentRepository<E extends IDescribedComponent>
/**
* The internal storage of components
*/
- private Map<String, E> components;
+ private IFunctionalMap<String, E> components;
/**
* The path that all the components came from
@@ -57,7 +58,8 @@ public class FileComponentRepository<E extends IDescribedComponent>
+ "Components can only be read from a directory");
}
- components = new HashMap<>();
+ components = new FunctionalMap<>();
+
sourceDirectory = directory.toPath().toAbsolutePath();
File[] listFiles = directory.listFiles();
@@ -100,8 +102,8 @@ public class FileComponentRepository<E extends IDescribedComponent>
}
@Override
- public FunctionalList<E> getComponentList() {
- FunctionalList<E> returnedList = new FunctionalList<>();
+ public IFunctionalList<E> getComponentList() {
+ IFunctionalList<E> returnedList = new FunctionalList<>();
components
.forEach((name, component) -> returnedList.add(component));
@@ -110,7 +112,7 @@ public class FileComponentRepository<E extends IDescribedComponent>
}
@Override
- public Map<String, E> getComponents() {
+ public IFunctionalMap<String, E> getComponents() {
return components;
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java b/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java
index 135e609..c720015 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java
@@ -1,8 +1,7 @@
package bjc.utils.components;
-import java.util.Map;
-
-import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
+import bjc.utils.funcdata.IFunctionalMap;
/**
* A collection of implementations of {@link IDescribedComponent}
@@ -18,7 +17,7 @@ public interface IComponentRepository<E extends IDescribedComponent> {
*
* @return A list of all the registered components
*/
- public FunctionalList<E> getComponentList();
+ public IFunctionalList<E> getComponentList();
/**
* Get all of the components this repository knows about
@@ -26,7 +25,7 @@ public interface IComponentRepository<E extends IDescribedComponent> {
* @return A map from component name to component, containing all of
* the components in the repositories
*/
- public Map<String, E> getComponents();
+ public IFunctionalMap<String, E> getComponents();
/**
* Get a component with a specific name
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
index 97cb195..f721a9a 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
@@ -92,4 +92,9 @@ public class Pair<L, R> implements IPair<L, R> {
return merger.apply(leftValue, rightValue);
}
+
+ @Override
+ public String toString() {
+ return "pair[l=" + leftValue.toString() + ", r=" + rightValue.toString() + "]";
+ }
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java
index 4b8ed30..2ad8dbf 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java
@@ -6,6 +6,7 @@ import java.util.function.Supplier;
import bjc.utils.data.IHolder;
import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
/**
* Holds a single value of a specific type. This is used for indirect
@@ -22,15 +23,19 @@ import bjc.utils.funcdata.FunctionalList;
public class LazyHolder<T> implements IHolder<T>, ILazy {
private final class LazyHolderSupplier<NewT>
implements Supplier<NewT> {
- private FunctionalList<Function<T, T>> pendingActions;
+ private IFunctionalList<Function<T, T>> pendingActions;
private Function<T, NewT> pendingTransform;
- public LazyHolderSupplier(FunctionalList<Function<T, T>> actons,
+ public LazyHolderSupplier(IFunctionalList<Function<T, T>> actons,
Function<T, NewT> transform) {
// Resolve latent bug I just realized. After a map, adding new
// actions to the original holder could've resulted in changes
// to all unactualized mapped values from that holder
- pendingActions = actons.clone();
+ pendingActions = new FunctionalList<>();
+
+ for (Function<T, T> action : actons.toIterable()) {
+ pendingActions.add(action);
+ }
this.pendingTransform = transform;
}
@@ -50,7 +55,7 @@ public class LazyHolder<T> implements IHolder<T>, ILazy {
/**
* List of queued actions to be performed on realized values
*/
- private FunctionalList<Function<T, T>> actions = new FunctionalList<>();
+ private IFunctionalList<Function<T, T>> actions = new FunctionalList<>();
/**
* The value internally held by this lazy holder
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();
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java
new file mode 100644
index 0000000..f490727
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java
@@ -0,0 +1,64 @@
+package bjc.utils.funcutils;
+
+import java.util.Random;
+import java.util.function.Consumer;
+
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
+
+/**
+ * Utility methods on enums
+ *
+ * @author ben
+ *
+ */
+public class EnumUtils {
+ /**
+ * Get a random value from an enum
+ *
+ * @param <E>
+ * The type of the enum
+ * @param enumClass
+ * The class of the enum
+ * @param rnd
+ * The random source to use
+ * @return A random value from the specified enum
+ */
+ public static <E extends Enum<E>> E getRandomValue(Class<E> enumClass,
+ Random rnd) {
+ E[] enumValues = enumClass.getEnumConstants();
+
+ return new FunctionalList<>(enumValues).randItem(rnd);
+ }
+
+ /**
+ * Do an action for a random number of enum values
+ *
+ * @param <E>
+ * The type of the enum
+ * @param enumClass
+ * The enum class
+ * @param nValues
+ * The number of values to execute the action on
+ * @param action
+ * The action to perform on random values
+ * @param rnd
+ * The source of randomness to use
+ */
+ public static <E extends Enum<E>> void doForValues(Class<E> enumClass,
+ int nValues, Consumer<E> action, Random rnd) {
+ E[] enumValues = enumClass.getEnumConstants();
+
+ IFunctionalList<E> valueList = new FunctionalList<>(enumValues);
+
+ int randomValueCount = enumValues.length - nValues;
+
+ for (int i = 0; i <= randomValueCount; i++) {
+ E rDir = valueList.randItem(rnd);
+
+ valueList.removeMatching(rDir);
+ }
+
+ valueList.forEach(action);
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/FileUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/FileUtils.java
new file mode 100644
index 0000000..fd09fbb
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/FileUtils.java
@@ -0,0 +1,77 @@
+package bjc.utils.funcutils;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.function.BiPredicate;
+
+/**
+ * Utilities for doing things with files
+ *
+ * @author ben
+ *
+ */
+public class FileUtils {
+ private static final class FunctionalFileVisitor
+ extends SimpleFileVisitor<Path> {
+ private BiPredicate<Path, BasicFileAttributes> traversalPredicate;
+ private BiPredicate<Path, BasicFileAttributes> traversalAction;
+
+ public FunctionalFileVisitor(
+ BiPredicate<Path, BasicFileAttributes> traversalPredicate,
+ BiPredicate<Path, BasicFileAttributes> traversalAction) {
+ this.traversalPredicate = traversalPredicate;
+ this.traversalAction = traversalAction;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir,
+ BasicFileAttributes attrs) throws IOException {
+ if (traversalPredicate.test(dir, attrs)) {
+ return FileVisitResult.CONTINUE;
+ }
+
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file,
+ BasicFileAttributes attrs) throws IOException {
+ if (traversalAction.test(file, attrs)) {
+ return FileVisitResult.CONTINUE;
+ }
+
+ return FileVisitResult.TERMINATE;
+ }
+ }
+
+ /**
+ * Traverse a directory recursively. This is a depth-first traversal
+ *
+ *
+ * @param root
+ * The directory to start the traversal at
+ * @param traversalPredicate
+ * The predicate to determine whether or not to traverse a
+ * directory
+ * @param traversalAction
+ * The action to invoke upon each file in the directory.
+ * Returning true means to continue the traversal, returning
+ * false stops it
+ * @throws IOException
+ * if the walk throws an exception
+ *
+ * TODO If it becomes necessary, write another overload for
+ * this with all the buttons and knobs from walkFileTree
+ */
+ public static void traverseDirectory(Path root,
+ BiPredicate<Path, BasicFileAttributes> traversalPredicate,
+ BiPredicate<Path, BasicFileAttributes> traversalAction)
+ throws IOException {
+ Files.walkFileTree(root, new FunctionalFileVisitor(
+ traversalPredicate, traversalAction));
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/FuncUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/FuncUtils.java
new file mode 100644
index 0000000..d89b7da
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/FuncUtils.java
@@ -0,0 +1,44 @@
+package bjc.utils.funcutils;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.IntConsumer;
+
+/**
+ * Utility things for functions
+ *
+ * @author ben
+ *
+ */
+public class FuncUtils {
+ /**
+ * Do the specified action the specified number of times
+ *
+ * @param nTimes
+ * The number of times to do the action
+ * @param cons
+ * The action to perform
+ */
+ public static void doTimes(int nTimes, IntConsumer cons) {
+ for (int i = 0; i < nTimes; i++) {
+ cons.accept(i);
+ }
+ }
+
+ /**
+ * Convert a binary function into a unary function that returns a
+ * function
+ *
+ * @param <A> The initial type of the function
+ * @param <B> The intermediate type of the function
+ * @param <C> The terminal type of the function
+ * @param func The function to transform
+ * @return The function transformed into a unary function returning a function
+ */
+ public static <A, B, C> Function<A, Function<B, C>> curry2(
+ BiFunction<A, B, C> func) {
+ return (arg1) -> (arg2) -> {
+ return func.apply(arg1, arg2);
+ };
+ }
+}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java
index 1d2750b..871e1cf 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java
@@ -6,8 +6,9 @@ import java.util.function.Consumer;
import java.util.function.Function;
import bjc.utils.data.GenHolder;
-import bjc.utils.data.Pair;
+import bjc.utils.data.IPair;
import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
/**
* Utilities for manipulating FunctionalLists that don't belong in the
@@ -20,7 +21,7 @@ public class ListUtils {
private static final int MAX_NTRIESPART = 50;
private static final class TokenDeaffixer
- implements BiFunction<String, String, FunctionalList<String>> {
+ implements BiFunction<String, String, IFunctionalList<String>> {
private String token;
public TokenDeaffixer(String tok) {
@@ -28,7 +29,7 @@ public class ListUtils {
}
@Override
- public FunctionalList<String> apply(String operatorName,
+ public IFunctionalList<String> apply(String operatorName,
String operatorRegex) {
if (operatorName == null) {
throw new NullPointerException(
@@ -53,7 +54,7 @@ public class ListUtils {
}
private static final class TokenSplitter
- implements BiFunction<String, String, FunctionalList<String>> {
+ implements BiFunction<String, String, IFunctionalList<String>> {
private String tokenToSplit;
public TokenSplitter(String tok) {
@@ -61,7 +62,7 @@ public class ListUtils {
}
@Override
- public FunctionalList<String> apply(String operatorName,
+ public IFunctionalList<String> apply(String operatorName,
String operatorRegex) {
if (operatorName == null) {
throw new NullPointerException(
@@ -77,10 +78,10 @@ public class ListUtils {
return new FunctionalList<>(tokenToSplit);
}
- FunctionalList<String> splitTokens = new FunctionalList<>(
+ IFunctionalList<String> splitTokens = new FunctionalList<>(
tokenToSplit.split(operatorRegex));
- FunctionalList<String> result = new FunctionalList<>();
+ IFunctionalList<String> result = new FunctionalList<>();
int tokenExpansionSize = splitTokens.getSize();
@@ -112,17 +113,17 @@ public class ListUtils {
*/
private static final class GroupPartIteration<E>
implements Consumer<E> {
- private FunctionalList<FunctionalList<E>> returnedList;
- private GenHolder<FunctionalList<E>> currentPartition;
- private FunctionalList<E> rejectedItems;
+ private IFunctionalList<IFunctionalList<E>> returnedList;
+ private GenHolder<IFunctionalList<E>> currentPartition;
+ private IFunctionalList<E> rejectedItems;
private GenHolder<Integer> numberInCurrentPartition;
private int numberPerPartition;
private Function<E, Integer> elementCounter;
public GroupPartIteration(
- FunctionalList<FunctionalList<E>> returned,
- GenHolder<FunctionalList<E>> currPart,
- FunctionalList<E> rejects,
+ IFunctionalList<IFunctionalList<E>> returned,
+ GenHolder<IFunctionalList<E>> currPart,
+ IFunctionalList<E> rejects,
GenHolder<Integer> numInCurrPart, int nPerPart,
Function<E, Integer> eleCount) {
this.returnedList = returned;
@@ -174,8 +175,8 @@ public class ListUtils {
* The number of elements to put in each partition
* @return A list partitioned according to the above rules
*/
- public static <E> FunctionalList<FunctionalList<E>> groupPartition(
- FunctionalList<E> input, Function<E, Integer> elementCounter,
+ public static <E> IFunctionalList<IFunctionalList<E>> groupPartition(
+ IFunctionalList<E> input, Function<E, Integer> elementCounter,
int numberPerPartition) {
if (input == null) {
throw new NullPointerException("Input list must not be null");
@@ -192,17 +193,17 @@ public class ListUtils {
/*
* List that holds our results
*/
- FunctionalList<FunctionalList<E>> returnedList = new FunctionalList<>();
+ IFunctionalList<IFunctionalList<E>> returnedList = new FunctionalList<>();
/*
* List that holds current partition
*/
- GenHolder<FunctionalList<E>> currentPartition = new GenHolder<>(
+ GenHolder<IFunctionalList<E>> currentPartition = new GenHolder<>(
new FunctionalList<>());
/*
* List that holds elements rejected during current pass
*/
- FunctionalList<E> rejectedElements = new FunctionalList<>();
+ IFunctionalList<E> rejectedElements = new FunctionalList<>();
/*
* The effective number of elements in the current partitition
@@ -251,9 +252,9 @@ public class ListUtils {
* @return A list of tokens split on all the operators
*
*/
- public static FunctionalList<String> splitTokens(
- FunctionalList<String> input,
- Deque<Pair<String, String>> operators) {
+ public static IFunctionalList<String> splitTokens(
+ IFunctionalList<String> input,
+ Deque<IPair<String, String>> operators) {
if (input == null) {
throw new NullPointerException("Input must not be null");
} else if (operators == null) {
@@ -261,7 +262,7 @@ public class ListUtils {
"Set of operators must not be null");
}
- GenHolder<FunctionalList<String>> returnedList = new GenHolder<>(
+ GenHolder<IFunctionalList<String>> returnedList = new GenHolder<>(
input);
operators.forEach((operator) -> returnedList
@@ -282,9 +283,9 @@ public class ListUtils {
* @return The tokens that have been deaffixed
*
*/
- public static FunctionalList<String> deAffixTokens(
- FunctionalList<String> input,
- Deque<Pair<String, String>> operators) {
+ public static IFunctionalList<String> deAffixTokens(
+ IFunctionalList<String> input,
+ Deque<IPair<String, String>> operators) {
if (input == null) {
throw new NullPointerException("Input must not be null");
} else if (operators == null) {
@@ -292,7 +293,7 @@ public class ListUtils {
"Set of operators must not be null");
}
- GenHolder<FunctionalList<String>> returnedList = new GenHolder<>(
+ GenHolder<IFunctionalList<String>> returnedList = new GenHolder<>(
input);
operators.forEach((operator) -> returnedList
@@ -311,7 +312,7 @@ public class ListUtils {
* The list of tokens to collapse
* @return The collapsed string of tokens
*/
- public static String collapseTokens(FunctionalList<String> input) {
+ public static String collapseTokens(IFunctionalList<String> input) {
if (input == null) {
throw new NullPointerException("Input must not be null");
}
@@ -329,7 +330,7 @@ public class ListUtils {
* The seperator to use for seperating tokens
* @return The collapsed string of tokens
*/
- public static String collapseTokens(FunctionalList<String> input,
+ public static String collapseTokens(IFunctionalList<String> input,
String seperator) {
if (input == null) {
throw new NullPointerException("Input must not be null");
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gen/RandomGrammar.java b/BJC-Utils2/src/main/java/bjc/utils/gen/RandomGrammar.java
index 4f194f3..349d9fa 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/gen/RandomGrammar.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/gen/RandomGrammar.java
@@ -1,8 +1,7 @@
package bjc.utils.gen;
-import java.util.HashMap;
-
-import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.IFunctionalList;
/**
* A weighted grammar where all the rules have a equal chance of occuring.
@@ -18,7 +17,7 @@ public class RandomGrammar<E> extends WeightedGrammar<E> {
* Create a new random grammar.
*/
public RandomGrammar() {
- rules = new HashMap<>();
+ rules = new FunctionalMap<>();
}
/**
@@ -30,8 +29,8 @@ public class RandomGrammar<E> extends WeightedGrammar<E> {
* The cases to add for this rule.
*/
@SafeVarargs
- public final void addCases(E rule, FunctionalList<E>... cases) {
- for (FunctionalList<E> currentCase : cases) {
+ public final void addCases(E rule, IFunctionalList<E>... cases) {
+ for (IFunctionalList<E> currentCase : cases) {
super.addCase(rule, 1, currentCase);
}
}
@@ -45,10 +44,10 @@ public class RandomGrammar<E> extends WeightedGrammar<E> {
* The cases to add for this rule.
*/
@SafeVarargs
- public final void makeRule(E rule, FunctionalList<E>... cases) {
+ public final void makeRule(E rule, IFunctionalList<E>... cases) {
super.addRule(rule);
- for (FunctionalList<E> currentCase : cases) {
+ for (IFunctionalList<E> currentCase : cases) {
super.addCase(rule, 1, currentCase);
}
}
@@ -61,7 +60,8 @@ public class RandomGrammar<E> extends WeightedGrammar<E> {
* @param cases
* The cases to add for this rule.
*/
- public void makeRule(E rule, FunctionalList<FunctionalList<E>> cases) {
+ public void makeRule(E rule,
+ IFunctionalList<IFunctionalList<E>> cases) {
if (cases == null) {
throw new NullPointerException("Cases must not be null");
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java
index 5d61201..37f31b0 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedGrammar.java
@@ -1,13 +1,14 @@
package bjc.utils.gen;
-import java.util.Hashtable;
-import java.util.Map;
import java.util.Random;
-import java.util.Set;
import java.util.function.Function;
+import bjc.utils.data.IPair;
import bjc.utils.data.Pair;
import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.IFunctionalList;
+import bjc.utils.funcdata.IFunctionalMap;
/**
* A random grammar, where certain rules will come up more often than
@@ -22,29 +23,29 @@ public class WeightedGrammar<E> {
/**
* The initial rule of the grammar
*/
- protected String initialRule;
+ protected String initialRule;
/**
* The rules currently in this grammar
*/
- protected Map<E, WeightedRandom<FunctionalList<E>>> rules;
+ protected IFunctionalMap<E, WeightedRandom<IFunctionalList<E>>> rules;
/**
* The random number generator used for random numbers
*/
- private Random rng;
+ private Random rng;
/**
* All of the subgrammars of this grammar
*/
- protected Map<E, WeightedGrammar<E>> subgrammars;
+ protected IFunctionalMap<E, WeightedGrammar<E>> subgrammars;
/**
* Create a new weighted grammar.
*/
public WeightedGrammar() {
- rules = new Hashtable<>();
- subgrammars = new Hashtable<>();
+ rules = new FunctionalMap<>();
+ subgrammars = new FunctionalMap<>();
}
/**
@@ -76,7 +77,7 @@ public class WeightedGrammar<E> {
* The case being added.
*/
public void addCase(E ruleName, int probability,
- FunctionalList<E> cse) {
+ IFunctionalList<E> cse) {
if (ruleName == null) {
throw new NullPointerException("Rule name must be not null");
} else if (cse == null) {
@@ -145,7 +146,7 @@ public class WeightedGrammar<E> {
* @return Whether or not the rule was succesfully added.
*/
public boolean addRule(E name,
- WeightedRandom<FunctionalList<E>> cases) {
+ WeightedRandom<IFunctionalList<E>> cases) {
if (name == null) {
throw new NullPointerException("Name must not be null");
} else if (cases == null) {
@@ -193,15 +194,15 @@ public class WeightedGrammar<E> {
* The rule to test.
* @return A set of sentances generated by the specified rule.
*/
- public FunctionalList<FunctionalList<E>> generateDebugValues(
+ public IFunctionalList<IFunctionalList<E>> generateDebugValues(
E ruleName) {
if (ruleName == null) {
throw new NullPointerException("Rule name must not be null");
}
- FunctionalList<FunctionalList<E>> returnedList = new FunctionalList<>();
+ IFunctionalList<IFunctionalList<E>> returnedList = new FunctionalList<>();
- WeightedRandom<FunctionalList<E>> ruleGenerator = rules
+ WeightedRandom<IFunctionalList<E>> ruleGenerator = rules
.get(ruleName);
for (int i = 0; i < 10; i++) {
@@ -226,7 +227,7 @@ public class WeightedGrammar<E> {
* @return A randomly generated sentance from the specified initial
* rule.
*/
- public <T> FunctionalList<T> generateGenericValues(E initRule,
+ public <T> IFunctionalList<T> generateGenericValues(E initRule,
Function<E, T> tokenTransformer, T spacer) {
if (initRule == null) {
throw new NullPointerException(
@@ -237,7 +238,7 @@ public class WeightedGrammar<E> {
throw new NullPointerException("Spacer must not be null");
}
- FunctionalList<T> returnedList = new FunctionalList<>();
+ IFunctionalList<T> returnedList = new FunctionalList<>();
if (subgrammars.containsKey(initRule)) {
subgrammars.get(initRule).generateGenericValues(initRule,
@@ -280,7 +281,7 @@ public class WeightedGrammar<E> {
* @return A list of random grammar elements generated by the specified
* rule.
*/
- public FunctionalList<E> generateListValues(E initRule, E spacer) {
+ public IFunctionalList<E> generateListValues(E initRule, E spacer) {
return generateGenericValues(initRule, strang -> strang, spacer);
}
@@ -342,16 +343,23 @@ public class WeightedGrammar<E> {
"Number of times to prefix must be positive.");
}
- WeightedRandom<FunctionalList<E>> rule = rules.get(ruleName);
+ WeightedRandom<IFunctionalList<E>> rule = rules.get(ruleName);
- FunctionalList<Pair<Integer, FunctionalList<E>>> newResults = new FunctionalList<>();
+ IFunctionalList<IPair<Integer, IFunctionalList<E>>> newResults = new FunctionalList<>();
rule.getValues().forEach((pair) -> {
- FunctionalList<FunctionalList<E>> newRule = new FunctionalList<>();
+ IFunctionalList<IFunctionalList<E>> newRule = new FunctionalList<>();
for (int i = 1; i <= numberOfTimes; i++) {
- FunctionalList<E> newCase = pair
- .merge((left, right) -> right.clone());
+ IFunctionalList<E> newCase = pair.merge((left, right) -> {
+ IFunctionalList<E> returnVal = new FunctionalList<>();
+
+ for (E val : right.toIterable()) {
+ returnVal.add(val);
+ }
+
+ return returnVal;
+ });
for (int j = 1; j <= i; j++) {
newCase.prepend(prefixToken);
@@ -392,13 +400,21 @@ public class WeightedGrammar<E> {
"Prefix token must not be null");
}
- WeightedRandom<FunctionalList<E>> rule = rules.get(ruleName);
+ WeightedRandom<IFunctionalList<E>> rule = rules.get(ruleName);
- FunctionalList<Pair<Integer, FunctionalList<E>>> newResults = new FunctionalList<>();
+ IFunctionalList<IPair<Integer, IFunctionalList<E>>> newResults = new FunctionalList<>();
rule.getValues().forEach((pair) -> {
- FunctionalList<E> newCase = pair
- .merge((left, right) -> right.clone());
+ IFunctionalList<E> newCase = pair.merge((left, right) -> {
+ IFunctionalList<E> returnVal = new FunctionalList<>();
+
+ for (E val : right.toIterable()) {
+ returnVal.add(val);
+ }
+
+ return returnVal;
+ });
+
newCase.prepend(prefixToken);
newResults.add(new Pair<>(pair.merge((left, right) -> left)
@@ -443,7 +459,7 @@ public class WeightedGrammar<E> {
* @return The number of rules in this grammar
*/
public int getRuleCount() {
- return rules.size();
+ return rules.getSize();
}
/**
@@ -451,8 +467,8 @@ public class WeightedGrammar<E> {
*
* @return The set of all rule names in this grammar
*/
- public Set<E> getRuleNames() {
- return rules.keySet();
+ public IFunctionalList<E> getRuleNames() {
+ return rules.keyList();
}
/**
@@ -484,13 +500,20 @@ public class WeightedGrammar<E> {
"Prefix token must not be null");
}
- WeightedRandom<FunctionalList<E>> rule = rules.get(ruleName);
+ WeightedRandom<IFunctionalList<E>> rule = rules.get(ruleName);
- FunctionalList<Pair<Integer, FunctionalList<E>>> newResults = new FunctionalList<>();
+ IFunctionalList<IPair<Integer, IFunctionalList<E>>> newResults = new FunctionalList<>();
rule.getValues().forEach((par) -> {
- FunctionalList<E> newCase = par
- .merge((left, right) -> right.clone());
+ IFunctionalList<E> newCase = par.merge((left, right) -> {
+ IFunctionalList<E> returnVal = new FunctionalList<>();
+
+ for (E val : right.toIterable()) {
+ returnVal.add(val);
+ }
+
+ return returnVal;
+ });
newCase.add(suffixToken);
newResults.add(new Pair<>(par.merge((left, right) -> left)
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java
index 5157ee2..10da34e 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java
@@ -2,9 +2,10 @@ package bjc.utils.gen;
import java.util.Random;
import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
import bjc.utils.data.GenHolder;
import bjc.utils.data.IHolder;
-import bjc.utils.data.Pair;
+import bjc.utils.data.IPair;
/**
* Represents a random number generator where certain results are weighted
@@ -19,12 +20,12 @@ public class WeightedRandom<E> {
/**
* The list of probabilities for each result
*/
- private FunctionalList<Integer> probabilities;
+ private IFunctionalList<Integer> probabilities;
/**
* The list of possible results to pick from
*/
- private FunctionalList<E> results;
+ private IFunctionalList<E> results;
/**
* The source for any needed random numbers
@@ -101,7 +102,7 @@ public class WeightedRandom<E> {
*
* @return A list of all the values that can be generated
*/
- public FunctionalList<E> getResults() {
+ public IFunctionalList<E> getResults() {
return results;
}
@@ -111,7 +112,7 @@ public class WeightedRandom<E> {
*
* @return A list of pairs of values and value probabilities
*/
- public FunctionalList<Pair<Integer, E>> getValues() {
+ public IFunctionalList<IPair<Integer, E>> getValues() {
return probabilities.pairWith(results);
}
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/graph/AdjacencyMap.java b/BJC-Utils2/src/main/java/bjc/utils/graph/AdjacencyMap.java
index 247ee31..a6e8eef 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/graph/AdjacencyMap.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/graph/AdjacencyMap.java
@@ -3,16 +3,15 @@ package bjc.utils.graph;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.InputMismatchException;
-import java.util.Map;
-import java.util.Map.Entry;
import java.util.Scanner;
-import java.util.Set;
import java.util.stream.IntStream;
import bjc.utils.data.GenHolder;
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.IFunctionalList;
+import bjc.utils.funcdata.IFunctionalMap;
/**
* An adjacency map representing a graph
@@ -65,7 +64,7 @@ public class AdjacencyMap<T> {
"The number of vertices must be greater than 0");
}
- Set<Integer> vertices = new HashSet<>();
+ IFunctionalList<Integer> vertices = new FunctionalList<>();
IntStream.range(0, numVertices)
.forEach(element -> vertices.add(element));
@@ -91,8 +90,9 @@ public class AdjacencyMap<T> {
try {
columnWeight = Integer.parseInt(part);
} catch (NumberFormatException nfex) {
- InputMismatchException imex = new InputMismatchException(
- "" + part + " is not a valid weight.");
+ InputMismatchException imex =
+ new InputMismatchException("" + part
+ + " is not a valid weight.");
imex.initCause(nfex);
@@ -119,7 +119,8 @@ public class AdjacencyMap<T> {
/**
* The backing storage of the map
*/
- private Map<T, Map<T, Integer>> adjacencyMap = new HashMap<>();
+ private IFunctionalMap<T, IFunctionalMap<T, Integer>> adjacencyMap =
+ new FunctionalMap<>();
/**
* Create a new map from a set of vertices
@@ -127,13 +128,13 @@ public class AdjacencyMap<T> {
* @param vertices
* The set of vertices to create a map from
*/
- public AdjacencyMap(Set<T> vertices) {
+ public AdjacencyMap(IFunctionalList<T> vertices) {
if (vertices == null) {
throw new NullPointerException("Vertices must not be null");
}
vertices.forEach(vertex -> {
- Map<T, Integer> vertexRow = new HashMap<>();
+ IFunctionalMap<T, Integer> vertexRow = new FunctionalMap<>();
vertices.forEach(
targetVertex -> vertexRow.put(targetVertex, 0));
@@ -150,16 +151,11 @@ public class AdjacencyMap<T> {
public boolean isDirected() {
GenHolder<Boolean> result = new GenHolder<>(true);
- adjacencyMap.entrySet().forEach(mapEntry -> {
- Set<Entry<T, Integer>> entryVertices = mapEntry.getValue()
- .entrySet();
+ adjacencyMap.forEach((key, value) -> {
+ value.forEach((targetKey, targetValue) -> {
+ int inverseValue = adjacencyMap.get(targetKey).get(key);
- entryVertices.forEach(targetVertex -> {
- int leftValue = targetVertex.getValue();
- int rightValue = adjacencyMap.get(targetVertex.getKey())
- .get(mapEntry.getKey());
-
- if (leftValue != rightValue) {
+ if (targetValue != inverseValue) {
result.transform((bool) -> false);
}
});
@@ -206,11 +202,11 @@ public class AdjacencyMap<T> {
public Graph<T> toGraph() {
Graph<T> returnedGraph = new Graph<>();
- adjacencyMap.entrySet().forEach(sourceVertex -> sourceVertex
- .getValue().entrySet()
- .forEach(targetVertex -> returnedGraph.addEdge(
- sourceVertex.getKey(), targetVertex.getKey(),
- targetVertex.getValue())));
+ adjacencyMap.forEach((key, value) -> {
+ value.forEach((targetKey, targetValue) -> {
+ returnedGraph.addEdge(key, targetKey, targetValue, true);
+ });
+ });
return returnedGraph;
}
@@ -229,10 +225,11 @@ public class AdjacencyMap<T> {
PrintStream outputPrinter = new PrintStream(outputSink);
- adjacencyMap.entrySet().forEach(sourceVertex -> {
- sourceVertex.getValue().entrySet()
- .forEach(targetVertex -> outputPrinter.printf("%d ",
- targetVertex.getValue()));
+ adjacencyMap.forEach((key, value) -> {
+ value.forEach((targetKey, targetValue) -> {
+ outputPrinter.printf("%d", targetValue);
+ });
+
outputPrinter.println();
});
diff --git a/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java b/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java
index f6bfc85..8041604 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/graph/Graph.java
@@ -1,11 +1,8 @@
package bjc.utils.graph;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.NoSuchElementException;
import java.util.PriorityQueue;
import java.util.Queue;
@@ -15,6 +12,9 @@ import java.util.function.BiPredicate;
import bjc.utils.data.GenHolder;
import bjc.utils.data.IHolder;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.IFunctionalList;
+import bjc.utils.funcdata.IFunctionalMap;
/**
* A directed weighted graph, where the vertices have some arbitrary label
@@ -29,13 +29,13 @@ public class Graph<T> {
/**
* The backing representation of the graph
*/
- private final Map<T, Map<T, Integer>> backingGraph;
+ private final IFunctionalMap<T, IFunctionalMap<T, Integer>> backingGraph;
/**
* Create a new graph
*/
public Graph() {
- backingGraph = new HashMap<>();
+ backingGraph = new FunctionalMap<>();
}
/**
@@ -47,8 +47,11 @@ public class Graph<T> {
* The target vertex for this edge
* @param distance
* The distance from the source vertex to the target vertex
+ * @param directed
+ * Whether or not
*/
- public void addEdge(T sourceVertex, T targetVertex, int distance) {
+ public void addEdge(T sourceVertex, T targetVertex, int distance,
+ boolean directed) {
// Can't add edges with a null source or target
if (sourceVertex == null) {
throw new NullPointerException(
@@ -60,17 +63,22 @@ public class Graph<T> {
// Initialize adjacency list for vertices if necessary
if (!backingGraph.containsKey(sourceVertex)) {
- backingGraph.put(sourceVertex, new HashMap<T, Integer>());
- }
- if (!backingGraph.containsKey(targetVertex)) {
- backingGraph.put(targetVertex, new HashMap<T, Integer>());
+ backingGraph.put(sourceVertex,
+ new FunctionalMap<T, Integer>());
}
// Add the edge to the graph
backingGraph.get(sourceVertex).put(targetVertex, distance);
- // Uncomment this to make the graph undirected
- // graph.get(target).put(source, distance);
+ // Handle possible directed edges
+ if (!directed) {
+ if (!backingGraph.containsKey(targetVertex)) {
+ backingGraph.put(targetVertex,
+ new FunctionalMap<T, Integer>());
+ }
+
+ backingGraph.get(targetVertex).put(sourceVertex, distance);
+ }
}
/**
@@ -107,7 +115,7 @@ public class Graph<T> {
* The vertex to use as a source
* @return All of the edges with the specified vertex as a source
*/
- public Map<T, Integer> getEdges(T source) {
+ public IFunctionalMap<T, Integer> getEdges(T source) {
// Can't find edges for a null source
if (source == null) {
throw new NullPointerException("The source cannot be null.");
@@ -116,7 +124,7 @@ public class Graph<T> {
"Vertex " + source + " is not in graph");
}
- return Collections.unmodifiableMap(backingGraph.get(source));
+ return backingGraph.get(source);
}
/**
@@ -125,7 +133,7 @@ public class Graph<T> {
* @return The initial vertex of the graph
*/
public T getInitial() {
- return backingGraph.keySet().iterator().next();
+ return backingGraph.keyList().first();
}
/**
@@ -195,7 +203,7 @@ public class Graph<T> {
* @return A count of the vertices in this graph
*/
public int getVertexCount() {
- return backingGraph.size();
+ return backingGraph.getSize();
}
/**
@@ -203,8 +211,8 @@ public class Graph<T> {
*
* @return A unmodifiable set of all the vertices in the graph.
*/
- public Set<T> getVertices() {
- return Collections.unmodifiableSet(backingGraph.keySet());
+ public IFunctionalList<T> getVertices() {
+ return backingGraph.keyList();
}
/**
@@ -249,13 +257,13 @@ public class Graph<T> {
*/
public AdjacencyMap<T> toAdjacencyMap() {
AdjacencyMap<T> adjacencyMap =
- new AdjacencyMap<>(backingGraph.keySet());
+ new AdjacencyMap<>(backingGraph.keyList());
- backingGraph.entrySet().forEach(sourceVertex -> sourceVertex
- .getValue()
- .forEach((targetVertex, vertexWeight) -> adjacencyMap
- .setWeight(sourceVertex.getKey(), targetVertex,
- vertexWeight)));
+ backingGraph.forEach((key, value) -> {
+ value.forEach((targetKey, targetValue) -> {
+ adjacencyMap.setWeight(key, targetKey, targetValue);
+ });
+ });
return adjacencyMap;
}
@@ -274,7 +282,7 @@ public class Graph<T> {
Graph<E> g = new Graph<>();
edges.forEach(edge -> g.addEdge(edge.getSource(), edge.getTarget(),
- edge.getDistance()));
+ edge.getDistance(), true));
return g;
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/ExtensionFileFilter.java b/BJC-Utils2/src/main/java/bjc/utils/gui/ExtensionFileFilter.java
index e563530..766b241 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/gui/ExtensionFileFilter.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/gui/ExtensionFileFilter.java
@@ -2,10 +2,10 @@ package bjc.utils.gui;
import java.io.File;
import javax.swing.filechooser.FileFilter;
-import java.util.ArrayList;
import java.util.List;
import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
/**
* A file filter based on extensions.
@@ -19,7 +19,7 @@ public class ExtensionFileFilter extends FileFilter {
/**
* The list holding all filtered extensions
*/
- private FunctionalList<String> extensions;
+ private IFunctionalList<String> extensions;
/**
* Create a new filter only showing files with the specified
@@ -40,11 +40,7 @@ public class ExtensionFileFilter extends FileFilter {
* The extensions to show in this filter.
*/
public ExtensionFileFilter(String... exts) {
- extensions = new FunctionalList<>(new ArrayList<>(exts.length));
-
- for (String extension : exts) {
- extensions.add(extension);
- }
+ extensions = new FunctionalList<>(exts);
}
@Override
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/ListParameterPanel.java b/BJC-Utils2/src/main/java/bjc/utils/gui/ListParameterPanel.java
index 4bbe6e7..26a5a78 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/gui/ListParameterPanel.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/gui/ListParameterPanel.java
@@ -9,7 +9,7 @@ import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
-import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
import bjc.utils.gui.layout.HLayout;
import bjc.utils.gui.layout.VLayout;
@@ -54,7 +54,7 @@ public class ListParameterPanel<E> extends JPanel {
*/
public ListParameterPanel(Supplier<E> addAction,
Consumer<E> editAction, Consumer<E> removeAction,
- FunctionalList<E> defaultValues) {
+ IFunctionalList<E> defaultValues) {
setLayout(new VLayout(2));
JList<E> list;
diff --git a/BJC-Utils2/src/main/java/bjc/utils/gui/awt/ExtensionFileFilter.java b/BJC-Utils2/src/main/java/bjc/utils/gui/awt/ExtensionFileFilter.java
index 7e2c2d2..230b768 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/gui/awt/ExtensionFileFilter.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/gui/awt/ExtensionFileFilter.java
@@ -2,10 +2,10 @@ package bjc.utils.gui.awt;
import java.io.File;
import java.io.FilenameFilter;
-import java.util.ArrayList;
import java.util.List;
import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
/**
* Filter a set of filenames by extension.
@@ -19,7 +19,7 @@ public class ExtensionFileFilter implements FilenameFilter {
/**
* The list of extensions to filter
*/
- private FunctionalList<String> extensions;
+ private IFunctionalList<String> extensions;
/**
* Create a new filter only showing files with the specified
@@ -44,11 +44,7 @@ public class ExtensionFileFilter implements FilenameFilter {
* The extensions to show in this filter.
*/
public ExtensionFileFilter(String... exts) {
- extensions = new FunctionalList<>(new ArrayList<>(exts.length));
-
- for (String extension : exts) {
- extensions.add(extension);
- }
+ extensions = new FunctionalList<>(exts);
}
@Override
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java
index 90961d5..88b4862 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/AST.java
@@ -183,11 +183,14 @@ public class AST<T> {
/**
* Expand the nodes in an AST
*
+ * This is actually equivalent to converting the tree into an ordered
+ * list, doing a flatMap, and then reconstructing the tree
+ *
* @param expander
* The function to use for expanding nodes
* @return The expanded AST
*/
- public AST<T> expand(Function<T, AST<T>> expander) {
+ public AST<T> flatMapTree(Function<T, AST<T>> expander) {
if (expander == null) {
throw new NullPointerException("Expander must not be null");
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
index b6162e5..999503c 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/RuleBasedConfigReader.java
@@ -8,6 +8,7 @@ import java.util.Scanner;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
+import bjc.utils.data.IPair;
import bjc.utils.data.Pair;
import bjc.utils.exceptions.UnknownPragmaException;
import bjc.utils.funcdata.FunctionalStringTokenizer;
@@ -20,9 +21,10 @@ import bjc.utils.funcdata.FunctionalStringTokenizer;
*
* @param <E>
* The type of the state object to use
+ *
*/
public class RuleBasedConfigReader<E> {
- private BiConsumer<FunctionalStringTokenizer, Pair<String, E>> startRule;
+ private BiConsumer<FunctionalStringTokenizer, IPair<String, E>> startRule;
private BiConsumer<FunctionalStringTokenizer, E> continueRule;
private Consumer<E> endRule;
@@ -39,7 +41,7 @@ public class RuleBasedConfigReader<E> {
* The action to fire when ending a rule
*/
public RuleBasedConfigReader(
- BiConsumer<FunctionalStringTokenizer, Pair<String, E>> startRule,
+ BiConsumer<FunctionalStringTokenizer, IPair<String, E>> startRule,
BiConsumer<FunctionalStringTokenizer, E> continueRule,
Consumer<E> endRule) {
this.startRule = startRule;
@@ -90,20 +92,26 @@ public class RuleBasedConfigReader<E> {
state = initialState;
boolean ruleOpen = false;
+
while (inputSource.hasNextLine()) {
String line = inputSource.nextLine();
- if (line.equals("")) {
+ if (line.startsWith("#") || line.startsWith("//")) {
+ // It's a comment
+ continue;
+ } else if (line.equals("")) {
if (ruleOpen == false) {
// Ignore blank line without an open rule
- }
-
- if (endRule == null) {
- // Nothing happens on rule end
} else {
- endRule.accept(state);
- }
+ if (endRule == null) {
+ // Nothing happens on rule end
+ ruleOpen = false;
+ } else {
+ endRule.accept(state);
+ }
+ ruleOpen = false;
+ }
continue;
} else if (line.startsWith("\t")) {
if (ruleOpen == false) {
@@ -125,9 +133,7 @@ public class RuleBasedConfigReader<E> {
String nextToken = tokenizer.nextToken();
- if (nextToken.equals("#") || nextToken.equals("//")) {
- // Do nothing, this is a comment
- } else if (nextToken.equals("pragma")) {
+ if (nextToken.equals("pragma")) {
String token = tokenizer.nextToken();
pragmas.getOrDefault(token, (tokenzer, stat) -> {
@@ -181,7 +187,7 @@ public class RuleBasedConfigReader<E> {
* The action to execute on starting of a rule
*/
public void setStartRule(
- BiConsumer<FunctionalStringTokenizer, Pair<String, E>> startRule) {
+ BiConsumer<FunctionalStringTokenizer, IPair<String, E>> startRule) {
if (startRule == null) {
throw new NullPointerException(
"Action on rule start must be non-null");
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
index 1e5d487..a60cb01 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/ShuntingYard.java
@@ -1,13 +1,14 @@
package bjc.utils.parserutils;
import java.util.Deque;
-import java.util.HashMap;
import java.util.LinkedList;
-import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.IFunctionalList;
+import bjc.utils.funcdata.IFunctionalMap;
import bjc.utils.funcutils.StringUtils;
/**
@@ -61,11 +62,11 @@ public class ShuntingYard<E> {
}
private final class TokenShunter implements Consumer<String> {
- private FunctionalList<E> output;
+ private IFunctionalList<E> output;
private Deque<String> stack;
private Function<String, E> transform;
- public TokenShunter(FunctionalList<E> outpt, Deque<String> stack,
+ public TokenShunter(IFunctionalList<E> outpt, Deque<String> stack,
Function<String, E> transform) {
this.output = outpt;
this.stack = stack;
@@ -115,13 +116,13 @@ public class ShuntingYard<E> {
/**
* Holds all the shuntable operations
*/
- private Map<String, IPrecedent> operators;
+ private IFunctionalMap<String, IPrecedent> operators;
/**
* Create a new shunting yard with a default set of operators
*/
public ShuntingYard() {
- operators = new HashMap<>();
+ operators = new FunctionalMap<>();
if (shouldConfigureBasicOperators) {
operators.put("+", Operator.ADD);
@@ -175,7 +176,7 @@ public class ShuntingYard<E> {
* The function to use to transform strings to tokens
* @return A list of tokens in postfix notation
*/
- public FunctionalList<E> postfix(FunctionalList<String> input,
+ public IFunctionalList<E> postfix(IFunctionalList<String> input,
Function<String, E> tokenTransformer) {
if (input == null) {
throw new NullPointerException("Input must not be null");
@@ -183,7 +184,7 @@ public class ShuntingYard<E> {
throw new NullPointerException("Transformer must not be null");
}
- FunctionalList<E> output = new FunctionalList<>();
+ IFunctionalList<E> output = new FunctionalList<>();
Deque<String> stack = new LinkedList<>();
diff --git a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
index 6fedf87..46e4da4 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/parserutils/TreeConstructor.java
@@ -9,7 +9,7 @@ import java.util.function.Predicate;
import bjc.utils.data.GenHolder;
import bjc.utils.data.IPair;
import bjc.utils.data.Pair;
-import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IFunctionalList;
/**
* Creates a parse tree from a postfix expression
@@ -119,7 +119,7 @@ public class TreeConstructor {
* operator
* @return A AST from the expression
*/
- public static <T> AST<T> constructTree(FunctionalList<T> tokens,
+ public static <T> AST<T> constructTree(IFunctionalList<T> tokens,
Predicate<T> operatorPredicate) {
return constructTree(tokens, operatorPredicate, (op) -> false,
null);
@@ -149,7 +149,7 @@ public class TreeConstructor {
* interface. Maybe there's a better way to express how that
* works
*/
- public static <T> AST<T> constructTree(FunctionalList<T> tokens,
+ public static <T> AST<T> constructTree(IFunctionalList<T> tokens,
Predicate<T> operatorPredicate, Predicate<T> isSpecialOperator,
Function<Deque<AST<T>>, AST<T>> handleSpecialOperator) {
if (tokens == null) {