summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java2
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java4
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java1
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java4
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java113
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java70
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/IPair.java54
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/Pair.java104
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java4
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java13
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java35
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java284
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java168
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java202
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java172
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java22
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java47
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java7
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java4
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java76
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java53
-rw-r--r--BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java21
22 files changed, 358 insertions, 1102 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
index a1c4461..c52bb08 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/GenericCommandMode.java
@@ -87,6 +87,8 @@ public class GenericCommandMode implements ICommandMode {
+ " while invoking it with the name of a topic will print the entry"
+ " for that topic"));
+ addCommandAlias("help", "man");
+
// Add commands handled in a upper layer
defaultHandlers.put("clear", new GenericCommand((args) -> {
errorOutput.accept(
diff --git a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java
index 4cd2dd1..7029829 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/cli/ICommand.java
@@ -33,5 +33,7 @@ public interface ICommand {
*
* @return Whether or not this command is an alias of another
*/
- public boolean isAlias();
+ public default boolean isAlias() {
+ return false;
+ }
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java
index 6c374be..52a1999 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/ComponentDescriptionState.java
@@ -8,6 +8,7 @@ package bjc.utils.components;
*/
public class ComponentDescriptionState {
private String name;
+
private String description;
private String author;
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 c720015..348be3e 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/components/IComponentRepository.java
@@ -17,7 +17,9 @@ public interface IComponentRepository<E extends IDescribedComponent> {
*
* @return A list of all the registered components
*/
- public IFunctionalList<E> getComponentList();
+ public default IFunctionalList<E> getComponentList() {
+ return getComponents().valueList();
+ }
/**
* Get all of the components this repository knows about
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java
deleted file mode 100644
index bd87f07..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/data/GenHolder.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package bjc.utils.data;
-
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-/**
- * Holds a single value of a specific type. This is used for indirect
- * references to data, and more specifically for accessing non-final
- * variables from a lambda. AKA the identity monad
- *
- * This is an eager variant of {@link IHolder}
- *
- * @author ben
- *
- * @param <T>
- * The type of the data being held
- */
-public class GenHolder<T> implements IHolder<T> {
- /**
- * The state this holder is responsible for.
- */
- private T heldValue;
-
- /**
- * Creates a new empty holder, with its state set to null
- */
- public GenHolder() {
- heldValue = null;
- }
-
- /**
- * Creates a new holder, with its state initialized to the provided
- * value
- *
- * @param held
- * The state to initialize this holder to.
- */
- public GenHolder(T held) {
- heldValue = held;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see bjc.utils.data.IHolder#doWith(java.util.function.Consumer)
- */
- @Override
- public void doWith(Consumer<T> action) {
- if (action == null) {
- throw new NullPointerException("Action must be non-null");
- }
-
- action.accept(heldValue);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see bjc.utils.data.IHolder#map(java.util.function.Function)
- */
- @Override
- public <NewT> IHolder<NewT> map(Function<T, NewT> transformer) {
- if (transformer == null) {
- throw new NullPointerException("Transformer must be non-null");
- }
-
- return new GenHolder<>(transformer.apply(heldValue));
- }
-
- /*
- * (non-Javadoc)
- *
- * @see bjc.utils.data.IHolder#transform(java.util.function.Function)
- */
- @Override
- public IHolder<T> transform(Function<T, T> transformer) {
- if (transformer == null) {
- throw new NullPointerException("Transformer must be non-null");
- }
-
- heldValue = transformer.apply(heldValue);
-
- return this;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see bjc.utils.data.IHolder#unwrap(java.util.function.Function)
- */
- @Override
- public <E> E unwrap(Function<T, E> unwrapper) {
- if (unwrapper == null) {
- throw new NullPointerException("Unwrapper must be null");
- }
-
- return unwrapper.apply(heldValue);
- }
-
- @Override
- public String toString() {
- if (heldValue == null) {
- return "(null)";
- }
-
- return heldValue.toString();
- }
-
- @Override
- public <E> IHolder<E> bind(Function<T, IHolder<E>> binder) {
- return binder.apply(heldValue);
- }
-}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java
deleted file mode 100644
index a4f4013..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/data/IHolder.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package bjc.utils.data;
-
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-/**
- * Generic interface for things that store a single value in a roughly
- * monadic fashion
- *
- * @author ben
- *
- * @param <T>
- * The type of data being stored
- */
-public interface IHolder<T> {
-
- /**
- * Call a provided function with the value being held
- *
- * @param action
- * The function to call
- */
- public void doWith(Consumer<T> action);
-
- /**
- * Return the result of applying the given transformation to the held
- * value. Doesn't change the held value.
- *
- * @param <NewT>
- * The new type of the held value
- *
- * @param transformer
- * The transformation to apply
- * @return A holder with the transformed value
- */
- public <NewT> IHolder<NewT> map(Function<T, NewT> transformer);
-
- /**
- * Apply the given transformation to the held value. Returns the holder
- * for allowing chaining of transforms
- *
- * @param transformer
- * The transform to apply to the value
- * @return The holder
- */
- public IHolder<T> transform(Function<T, T> transformer);
-
- /**
- * Returns a raw mapped value, not contained in a GenHolder
- *
- * @param <E>
- * The type of the value that is the end result
- *
- * @param unwrapper
- * The function to use for mapping the value
- * @return The mapped value outside of a GenHolder
- */
- public <E> E unwrap(Function<T, E> unwrapper);
-
- /**
- * Bind the value in this holder to a new value
- *
- * @param <E>
- * The new type of the held value
- * @param binder
- * The function to do the binding with
- * @return The bound value
- */
- public <E> IHolder<E> bind(Function<T, IHolder<E>> binder);
-} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java
deleted file mode 100644
index 98f425f..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/data/IPair.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package bjc.utils.data;
-
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-
-/**
- * An interface representing a pair of values
- *
- * @author ben
- *
- * @param <L>
- * The type stored in the left side of the pair
- * @param <R>
- * The type stored in the right side of the pair
- */
-public interface IPair<L, R> {
- /**
- * Apply a function to the two internal values that returns a new pair.
- *
- * Is a monadic bind.
- *
- * @param <L2>
- * The new left pair type
- * @param <R2>
- * The new right pair type
- * @param binder
- * The function to use as a bind
- * @return The new pair
- */
- public <L2, R2> IPair<L2, R2> bind(
- BiFunction<L, R, IPair<L2, R2>> binder);
-
- /**
- * Execute an action with the values of this pair. Has no effect on the
- * internal contents
- *
- * @param action
- * The action to execute on the values
- */
- public void doWith(BiConsumer<L, R> action);
-
- /**
- * Collapse this pair to a single value. Does not change the internal
- * contents of this pair.
- *
- * @param <E>
- * The resulting type after merging
- *
- * @param merger
- * The function to use to collapse the pair.
- * @return The collapsed value.
- */
- public <E> E merge(BiFunction<L, R, E> merger);
-} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java b/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
deleted file mode 100644
index 87727be..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/data/Pair.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package bjc.utils.data;
-
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-
-/**
- * Holds a pair of values of two different types.
- *
- * Is an eager variant of {@link IPair}
- *
- * @author ben
- *
- * @param <L>
- * The type of the thing held on the left (first)
- * @param <R>
- * The type of the thing held on the right (second)
- */
-public class Pair<L, R> implements IPair<L, R> {
- /**
- * The left value of the pair
- */
- protected L leftValue;
-
- /**
- * The right value of the pair
- */
- protected R rightValue;
-
- /**
- * Create a new pair that holds two nulls.
- */
- public Pair() {
-
- }
-
- /**
- * Create a new pair holding the specified values.
- *
- * @param left
- * The value to hold on the left.
- * @param right
- * The value to hold on the right.
- */
- public Pair(L left, R right) {
- leftValue = left;
- rightValue = right;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer)
- */
- @Override
- public void doWith(BiConsumer<L, R> action) {
- if (action == null) {
- throw new NullPointerException("Action must be non-null");
- }
-
- action.accept(leftValue, rightValue);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see bjc.utils.data.IPair#merge(java.util.function.BiFunction)
- */
- @Override
- public <E> E merge(BiFunction<L, R, E> merger) {
- if (merger == null) {
- throw new NullPointerException("Merger must be non-null");
- }
-
- return merger.apply(leftValue, rightValue);
- }
-
- @Override
- public String toString() {
- String leftValueString;
-
- if (leftValue != null) {
- leftValueString = leftValue.toString();
- } else {
- leftValueString = "(null)";
- }
-
- String rightValueString;
-
- if (rightValue != null) {
- rightValueString = rightValue.toString();
- } else {
- rightValueString = "(null)";
- }
-
- return "pair[l=" + leftValueString + ", r=" + rightValueString
- + "]";
- }
-
- @Override
- public <L2, R2> IPair<L2, R2> bind(
- BiFunction<L, R, IPair<L2, R2>> binder) {
- return binder.apply(leftValue, rightValue);
- }
-}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java
index 7d1d7a0..6ccf115 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IHolder.java
@@ -94,6 +94,8 @@ public interface IHolder<ContainedType> {
* @return The holder itself
*/
public default IHolder<ContainedType> replace(ContainedType newValue) {
- return transform((oldValue) -> newValue);
+ return transform((oldValue) -> {
+ return newValue;
+ });
}
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java
index fb9648e..f5ca240 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/data/experimental/IPair.java
@@ -1,5 +1,6 @@
package bjc.utils.data.experimental;
+import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
@@ -81,4 +82,16 @@ public interface IPair<LeftType, RightType> {
public default RightType getRight() {
return merge((leftValue, rightValue) -> rightValue);
}
+
+ /**
+ * Immediately perfom the specified action with the contents of this pair
+ * @param consumer The action to perform on the pair
+ */
+ public default void doWith(BiConsumer<LeftType, RightType> consumer) {
+ merge((leftValue, rightValue) -> {
+ consumer.accept(leftValue, rightValue);
+
+ return null;
+ });
+ }
}
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java
deleted file mode 100644
index a4fab67..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/ILazy.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package bjc.utils.data.lazy;
-
-/**
- * Interface for some maintenance operations on lazy objects
- *
- * @author ben
- *
- */
-public interface ILazy {
- /**
- * Check if this object has been materialized
- *
- * @return Whether or not this object has been materialized
- */
- public boolean isMaterialized();
-
- /**
- * Check if there are pending actions that need to be applied
- *
- * @return Whether or not there are pending actions
- */
- public boolean hasPendingActions();
-
- /**
- * Make this object materialize itelf
- */
- public void materialize();
-
- /**
- * Make this object apply any pending objects
- *
- * As a requirement, will materialize the object if it is not materialized
- */
- public void applyPendingActions();
-}
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
deleted file mode 100644
index 141d558..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyHolder.java
+++ /dev/null
@@ -1,284 +0,0 @@
-package bjc.utils.data.lazy;
-
-import java.util.function.Consumer;
-import java.util.function.Function;
-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
- * references to data, and more specifically for accessing non-final
- * variables from a lambda. AKA the identity monad
- *
- * This is a lazy variant of {@link IHolder}
- *
- * @author ben
- *
- * @param <T>
- * The type of the data being held
- */
-public class LazyHolder<T> implements IHolder<T>, ILazy {
- private static final class LazyHolderHolder<T2>
- implements IHolder<T2> {
- private Supplier<IHolder<T2>> holderSource;
-
- private IHolder<T2> holder;
-
- private IFunctionalList<Function<T2, T2>> actions = new FunctionalList<>();
-
- public LazyHolderHolder(Supplier<IHolder<T2>> source) {
-
- holderSource = source;
- }
-
- @Override
- public void doWith(Consumer<T2> action) {
- actions.add((val) -> {
- action.accept(val);
-
- return val;
- });
- }
-
- @Override
- public <NewT> IHolder<NewT> map(Function<T2, NewT> transformer) {
- // TODO implement me
- throw new UnsupportedOperationException(
- "Mapping is not yet supported on bound holders");
- }
-
- @Override
- public IHolder<T2> transform(Function<T2, T2> transformer) {
- actions.add(transformer);
-
- return this;
- }
-
- @Override
- public <E> E unwrap(Function<T2, E> unwrapper) {
- if (holder == null) {
- holder = holderSource.get();
- }
-
- if (!actions.isEmpty()) {
- actions.forEach((transform) -> {
- holder.transform(transform);
- });
- }
-
- return holder.unwrap(unwrapper);
- }
-
- @Override
- public <E> IHolder<E> bind(Function<T2, IHolder<E>> binder) {
- return new LazyHolderHolder<>(() -> {
- return binder.apply(unwrap((val) -> val));
- });
- }
-
- @Override
- public String toString() {
- if (holderSource == null) {
- if (holder == null) {
- return "(null)";
- }
-
- return holder.toString();
- }
-
- if (holder == null) {
- return "(unmaterialized values)";
- }
-
- return holder.toString();
- }
- }
-
- private static final class LazyHolderSupplier<NewT, T2>
- implements Supplier<NewT> {
- private IFunctionalList<Function<T2, T2>> pendingActions;
- private Function<T2, NewT> pendingTransform;
-
- private T2 heldValue;
- private Supplier<T2> heldSource;
-
- public LazyHolderSupplier(IFunctionalList<Function<T2, T2>> actons,
- Function<T2, NewT> transform, T2 heldValue,
- Supplier<T2> heldSource) {
- // 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 = new FunctionalList<>();
-
- for (Function<T2, T2> action : actons.toIterable()) {
- pendingActions.add(action);
- }
-
- this.pendingTransform = transform;
- this.heldValue = heldValue;
- this.heldSource = heldSource;
- }
-
- @Override
- public NewT get() {
- if (heldValue == null) {
- return pendingActions.reduceAux(heldSource.get(),
- Function<T2, T2>::apply, pendingTransform::apply);
- }
-
- return pendingActions.reduceAux(heldValue,
- Function<T2, T2>::apply, pendingTransform::apply);
- }
- }
-
- /**
- * List of queued actions to be performed on realized values
- */
- private IFunctionalList<Function<T, T>> actions = new FunctionalList<>();
-
- /**
- * The value internally held by this lazy holder
- */
- private T heldValue;
-
- /**
- * The source for a value held by this lazy holder
- */
- private Supplier<T> heldSource;
-
- /**
- * Create a new lazy holder with the given supplier
- *
- * @param source
- * The supplier for a value when it is neededs
- */
- public LazyHolder(Supplier<T> source) {
- if (source == null) {
- throw new NullPointerException("Source must be non-null");
- }
-
- heldSource = source;
- heldValue = null;
- }
-
- /**
- * Create a new lazy holder with the given value
- *
- * @param value
- * The value held in the holder
- */
- public LazyHolder(T value) {
- heldSource = () -> value;
- }
-
- @Override
- public void doWith(Consumer<T> action) {
- if (action == null) {
- throw new NullPointerException("Action must be non-null");
- }
-
- transform((value) -> {
- // Do the action with the value
- action.accept(value);
-
- // Return the untransformed value
- return value;
- });
- }
-
- @Override
- public <NewT> IHolder<NewT> map(Function<T, NewT> transform) {
- if (transform == null) {
- throw new NullPointerException("Transform must be non-null");
- }
-
- // Don't actually map until we need to
- return new LazyHolder<>(new LazyHolderSupplier<>(actions,
- transform, heldValue, heldSource));
- }
-
- @Override
- public IHolder<T> transform(Function<T, T> transform) {
- if (transform == null) {
- throw new NullPointerException("Transform must be non-null");
- }
-
- // Queue the transform until we need to apply it
- actions.add(transform);
-
- return this;
- }
-
- @Override
- public <E> E unwrap(Function<T, E> unwrapper) {
- if (unwrapper == null) {
- throw new NullPointerException("Unwrapper must be null");
- }
-
- // Actualize ourselves
- if (heldValue == null) {
- heldValue = heldSource.get();
- }
-
- // Apply all pending transforms
- actions.forEach((action) -> heldValue = action.apply(heldValue));
-
- return unwrapper.apply(heldValue);
- }
-
- @Override
- public boolean isMaterialized() {
- if (heldSource != null) {
- // We're materialized if a value exists
- return heldValue == null;
- }
-
- // We're materialized by default
- return true;
- }
-
- @Override
- public boolean hasPendingActions() {
- return actions.isEmpty();
- }
-
- @Override
- public void materialize() {
- // Only materialize if we haven't already
- if (!isMaterialized()) {
- heldValue = heldSource.get();
- }
- }
-
- @Override
- public void applyPendingActions() {
- materialize();
-
- actions.forEach((action) -> {
- heldValue = action.apply(heldValue);
- });
- }
-
- @Override
- public <T2> IHolder<T2> bind(Function<T, IHolder<T2>> binder) {
- return new LazyHolderHolder<>(() -> {
- return binder.apply(unwrap((val) -> val));
- });
- }
-
- @Override
- public String toString() {
- if (isMaterialized()) {
- if (hasPendingActions()) {
- return heldValue.toString() + " (has pending actions)";
- }
-
- return heldValue.toString();
- }
-
- return "(unmaterialized value)";
- }
-} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java
deleted file mode 100644
index dcaeeba..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/LazyPair.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package bjc.utils.data.lazy;
-
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Supplier;
-
-import bjc.utils.data.IHolder;
-import bjc.utils.data.IPair;
-import bjc.utils.data.Pair;
-
-/**
- * A lazy holder of two values
- *
- * Lazy variant of {@link IPair}
- *
- * @author ben
- *
- * @param <L>
- * The type of value stored on the left side of the pair
- * @param <R>
- * The type of value stored on the right side of the pair
- */
-public class LazyPair<L, R> implements IPair<L, R>, ILazy {
- /**
- * The backing store for this pair
- */
- protected IHolder<IPair<L, R>> delegatePair;
-
- private boolean materialized = false;
- private boolean pendingActions = false;
-
- /**
- * Create a new blank lazy pair
- */
- public LazyPair() {
- delegatePair = new LazyHolder<>(new Pair<>());
- }
-
- /**
- * Create a new lazy pair with the specified initial values
- *
- * @param leftValue
- * The initial value for the left side of the pair
- * @param rightValue
- * The initial value for the right side of the pair
- */
- public LazyPair(L leftValue, R rightValue) {
- materialized = true;
-
- delegatePair = new LazyHolder<>(new Pair<>(leftValue, rightValue));
- }
-
- /**
- * Create a new lazy pair with the specified sources for initial values
- *
- * @param leftValueSource
- * The function to call for the left initial value
- * @param rightValueSource
- * The function to call for the right initial value
- */
- public LazyPair(Supplier<L> leftValueSource,
- Supplier<R> rightValueSource) {
- if (leftValueSource == null || rightValueSource == null) {
- throw new NullPointerException("Sources must be non-null");
- }
-
- delegatePair = new LazyHolder<>(() -> {
- return new Pair<>(leftValueSource.get(),
- rightValueSource.get());
- });
- }
-
- /**
- * Create a new lazy pair with a specified internal delegate
- *
- * @param delegate
- * The internal delegate for the pair
- */
- private LazyPair(IHolder<IPair<L, R>> delegate, boolean mater,
- boolean pend) {
- materialized = mater;
- pendingActions = pend;
-
- delegatePair = delegate;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see bjc.utils.data.IPair#doWith(java.util.function.BiConsumer)
- */
- @Override
- public void doWith(BiConsumer<L, R> action) {
- if (action == null) {
- throw new NullPointerException("Action must be non-null");
- }
-
- pendingActions = true;
-
- delegatePair.doWith((currentPair) -> {
- currentPair.doWith(action);
- });
- }
-
- /*
- * (non-Javadoc)
- *
- * @see bjc.utils.data.IPair#merge(java.util.function.BiFunction)
- */
- @Override
- public <E> E merge(BiFunction<L, R, E> merger) {
- if (merger == null) {
- throw new NullPointerException("Merger must be non-null");
- }
-
- materialized = true;
- pendingActions = false;
-
- return delegatePair
- .unwrap((currentPair) -> currentPair.merge(merger));
- }
-
- @Override
- public boolean isMaterialized() {
- return materialized;
- }
-
- @Override
- public boolean hasPendingActions() {
- return pendingActions;
- }
-
- /*
- * Note: Materializing will also apply all currently pending actions
- */
- @Override
- public void materialize() {
- merge((left, right) -> null);
-
- materialized = true;
- pendingActions = false;
- }
-
- @Override
- public void applyPendingActions() {
- merge((left, right) -> null);
-
- materialized = true;
- pendingActions = false;
- }
-
- @Override
- public <L2, R2> IPair<L2, R2> bind(
- BiFunction<L, R, IPair<L2, R2>> binder) {
- IHolder<IPair<L2, R2>> newDelegate = delegatePair
- .map((pairVal) -> {
- return pairVal.bind(binder);
- });
-
- return new LazyPair<>(newDelegate, isMaterialized(),
- hasPendingActions());
- }
-
- @Override
- public String toString() {
- return delegatePair.toString();
- }
-} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java b/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java
deleted file mode 100644
index 4bd3832..0000000
--- a/BJC-Utils2/src/main/java/bjc/utils/data/lazy/NewLazyPair.java
+++ /dev/null
@@ -1,202 +0,0 @@
-package bjc.utils.data.lazy;
-
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Supplier;
-
-import bjc.utils.data.GenHolder;
-import bjc.utils.data.IPair;
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.funcdata.IFunctionalList;
-
-/**
- * New implementation of lazy pair not delegating to {@link LazyHolder}
- *
- * @author ben
- * @param <L>
- * The type on the left side of the pair
- * @param <R>
- * The type on the right side of the pair
- *
- */
-public class NewLazyPair<L, R> implements IPair<L, R>, ILazy {
- private static class BoundLazyPair<OldL, OldR, NewL, NewR>
- implements IPair<NewL, NewR> {
- private Supplier<OldL> oldLeftSupplier;
- private Supplier<OldR> oldRightSupplier;
-
- private BiFunction<OldL, OldR, IPair<NewL, NewR>> newPairSupplier;
-
- private IPair<NewL, NewR> newPair;
-
- private boolean newPairMaterialized;
-
- public BoundLazyPair(Supplier<OldL> leftSup,
- Supplier<OldR> rightSup,
- BiFunction<OldL, OldR, IPair<NewL, NewR>> binder) {
- oldLeftSupplier = leftSup;
- oldRightSupplier = rightSup;
-
- newPairSupplier = binder;
- }
-
- @Override
- public <L2, R2> IPair<L2, R2> bind(
- BiFunction<NewL, NewR, IPair<L2, R2>> binder) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void doWith(BiConsumer<NewL, NewR> action) {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public <E> E merge(BiFunction<NewL, NewR, E> merger) {
- if (!newPairMaterialized) {
- newPair = newPairSupplier.apply(oldLeftSupplier.get(),
- oldRightSupplier.get());
- }
-
- return newPair.merge(merger);
- }
- }
-
- private L leftValue;
- private R rightValue;
-
- private Supplier<R> rightValueSupplier;
- private Supplier<L> leftValueSupplier;
-
- private boolean rightMaterialized;
- private boolean leftMaterialized;
-
- private IFunctionalList<BiConsumer<L, R>> actions;
-
- /**
- * Create a new lazy pair
- *
- * @param leftVal
- * The left value in the pair
- * @param rightVal
- * The right value in the pair
- */
- public NewLazyPair(L leftVal, R rightVal) {
- leftValueSupplier = () -> leftVal;
- rightValueSupplier = () -> rightVal;
- }
-
- /**
- * Create a new lazy pair
- *
- * @param leftSupplier
- * The supplier for the left value in the pair
- * @param rightSupplier
- * The supplier for the right value in the pair
- */
- public NewLazyPair(Supplier<L> leftSupplier,
- Supplier<R> rightSupplier) {
- leftValueSupplier = leftSupplier;
- rightValueSupplier = rightSupplier;
- }
-
- @Override
- public void applyPendingActions() {
- if (!isMaterialized()) {
- throw new UnsupportedOperationException(
- "Can only apply actions to materialized values");
- }
-
- actions.forEach((action) -> {
- action.accept(leftValue, rightValue);
- });
-
- actions = new FunctionalList<>();
- }
-
- private void applyPossiblyPendingActions(GenHolder<Boolean> hasActions,
- IFunctionalList<BiConsumer<L, R>> pendingActions) {
- if (hasActions.unwrap((val) -> val) == true) {
- pendingActions.forEach((action) -> {
- action.accept(leftValue, rightValue);
- });
-
- hasActions.transform((val) -> false);
- }
- }
-
- @Override
- public <L2, R2> IPair<L2, R2> bind(
- BiFunction<L, R, IPair<L2, R2>> binder) {
- GenHolder<Boolean> hasActions = new GenHolder<>(true);
- IFunctionalList<BiConsumer<L, R>> pendingActions = new FunctionalList<>();
-
- actions.forEach(pendingActions::add);
-
- return new BoundLazyPair<>(() -> {
- applyPossiblyPendingActions(hasActions, pendingActions);
-
- return leftValue;
- }, () -> {
- applyPossiblyPendingActions(hasActions, pendingActions);
-
- return rightValue;
- }, binder);
- }
-
- @Override
- public void doWith(BiConsumer<L, R> action) {
- actions.add(action);
- }
-
- @Override
- public boolean hasPendingActions() {
- return !actions.isEmpty();
- }
-
- @Override
- public boolean isMaterialized() {
- if (leftValueSupplier == null) {
- if (rightValueSupplier == null) {
- return true;
- }
-
- return rightMaterialized;
- }
-
- if (rightValueSupplier == null) {
- return leftMaterialized;
- }
-
- return leftMaterialized && rightMaterialized;
- }
-
- @Override
- public void materialize() {
- if (isMaterialized()) {
- throw new UnsupportedOperationException(
- "Cannot materialize lazy object twice");
- }
-
- if (leftValueSupplier != null) {
- leftValue = leftValueSupplier.get();
- }
-
- if (rightValueSupplier != null) {
- rightValue = rightValueSupplier.get();
- }
- }
-
- @Override
- public <E> E merge(BiFunction<L, R, E> merger) {
- if (!isMaterialized()) {
- materialize();
- }
-
- applyPendingActions();
-
- return merger.apply(leftValue, rightValue);
- }
-} \ No newline at end of file
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 9574376..9b388b2 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalList.java
@@ -5,17 +5,16 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
-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.GenHolder;
-import bjc.utils.data.IHolder;
-import bjc.utils.data.IPair;
-import bjc.utils.data.Pair;
+import bjc.utils.data.experimental.IHolder;
+import bjc.utils.data.experimental.IPair;
+import bjc.utils.data.experimental.Identity;
+import bjc.utils.data.experimental.Pair;
import java.util.ArrayList;
@@ -45,6 +44,8 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
/**
* Create a new functional list containing the specified items.
*
+ * Takes O(n) time, where n is the number of items specified
+ *
* @param items
* The items to put into this functional list.
*/
@@ -70,6 +71,8 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
/**
* Create a new functional list as a wrapper of a existing list.
*
+ * Takes O(1) time, since it doesn't copy the list.
+ *
* @param backingList
* The list to use as a backing list.
*/
@@ -82,7 +85,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
wrappedList = backingList;
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#add(E)
*/
@Override
@@ -90,8 +95,11 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return wrappedList.add(item);
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#allMatch(java.util.function.Predicate)
+ /*
+ * (non-Javadoc)
+ *
+ * @see bjc.utils.funcdata.IFunctionalList#allMatch(java.util.function.
+ * Predicate)
*/
@Override
public boolean allMatch(Predicate<E> matchPredicate) {
@@ -110,8 +118,11 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return true;
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#anyMatch(java.util.function.Predicate)
+ /*
+ * (non-Javadoc)
+ *
+ * @see bjc.utils.funcdata.IFunctionalList#anyMatch(java.util.function.
+ * Predicate)
*/
@Override
public boolean anyMatch(Predicate<E> matchPredicate) {
@@ -130,6 +141,13 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return false;
}
+ /**
+ * Clone this list into a new one, and clone the backing list as well
+ *
+ * Takes O(n) time, where n is the number of elements in the list
+ *
+ * @return A list
+ */
@Override
public IFunctionalList<E> clone() {
IFunctionalList<E> clonedList = new FunctionalList<>();
@@ -141,8 +159,12 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return clonedList;
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#combineWith(bjc.utils.funcdata.IFunctionalList, java.util.function.BiFunction)
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * bjc.utils.funcdata.IFunctionalList#combineWith(bjc.utils.funcdata.
+ * IFunctionalList, java.util.function.BiFunction)
*/
@Override
public <T, F> IFunctionalList<F> combineWith(
@@ -173,7 +195,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return returnedList;
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#contains(E)
*/
@Override
@@ -182,7 +206,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return this.anyMatch(item::equals);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#first()
*/
@Override
@@ -195,8 +221,11 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return wrappedList.get(0);
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#flatMap(java.util.function.Function)
+ /*
+ * (non-Javadoc)
+ *
+ * @see bjc.utils.funcdata.IFunctionalList#flatMap(java.util.function.
+ * Function)
*/
@Override
public <T> IFunctionalList<T> flatMap(
@@ -224,8 +253,11 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return returnedList;
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#forEach(java.util.function.Consumer)
+ /*
+ * (non-Javadoc)
+ *
+ * @see bjc.utils.funcdata.IFunctionalList#forEach(java.util.function.
+ * Consumer)
*/
@Override
public void forEach(Consumer<E> action) {
@@ -236,8 +268,12 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
wrappedList.forEach(action);
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#forEachIndexed(java.util.function.BiConsumer)
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * bjc.utils.funcdata.IFunctionalList#forEachIndexed(java.util.function
+ * .BiConsumer)
*/
@Override
public void forEachIndexed(BiConsumer<Integer, E> indexedAction) {
@@ -246,7 +282,7 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
}
// This is held b/c ref'd variables must be final/effectively final
- GenHolder<Integer> currentIndex = new GenHolder<>(0);
+ IHolder<Integer> currentIndex = new Identity<>(0);
wrappedList.forEach((element) -> {
// Call the action with the index and the value
@@ -258,7 +294,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
});
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#getByIndex(int)
*/
@Override
@@ -275,8 +313,12 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return wrappedList;
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#getMatching(java.util.function.Predicate)
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * bjc.utils.funcdata.IFunctionalList#getMatching(java.util.function.
+ * Predicate)
*/
@Override
public IFunctionalList<E> getMatching(Predicate<E> matchPredicate) {
@@ -296,7 +338,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return returnedList;
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#getSize()
*/
@Override
@@ -304,7 +348,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return wrappedList.size();
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#isEmpty()
*/
@Override
@@ -312,8 +358,11 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return wrappedList.isEmpty();
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#map(java.util.function.Function)
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * bjc.utils.funcdata.IFunctionalList#map(java.util.function.Function)
*/
@Override
public <T> IFunctionalList<T> map(Function<E, T> elementTransformer) {
@@ -332,8 +381,11 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return returnedList;
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#pairWith(bjc.utils.funcdata.IFunctionalList)
+ /*
+ * (non-Javadoc)
+ *
+ * @see bjc.utils.funcdata.IFunctionalList#pairWith(bjc.utils.funcdata.
+ * IFunctionalList)
*/
@Override
public <T> IFunctionalList<IPair<E, T>> pairWith(
@@ -341,7 +393,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return combineWith(rightList, Pair<E, T>::new);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#partition(int)
*/
@Override
@@ -357,7 +411,7 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
IFunctionalList<IFunctionalList<E>> returnedList = new FunctionalList<>();
// The current partition being filled
- GenHolder<IFunctionalList<E>> currentPartition = new GenHolder<>(
+ IHolder<IFunctionalList<E>> currentPartition = new Identity<>(
new FunctionalList<>());
this.forEach((element) -> {
@@ -383,12 +437,14 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
* Check if a partition has room for another item
*/
private Boolean isPartitionFull(int numberPerPartition,
- GenHolder<IFunctionalList<E>> currentPartition) {
+ IHolder<IFunctionalList<E>> currentPartition) {
return currentPartition.unwrap(
(partition) -> partition.getSize() >= numberPerPartition);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#prepend(E)
*/
@Override
@@ -396,23 +452,28 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
wrappedList.add(0, item);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#randItem(java.util.Random)
*/
@Override
- public E randItem(Random rnd) {
+ public E randItem(Function<Integer, Integer> rnd) {
if (rnd == null) {
throw new NullPointerException(
"Random source must not be null");
}
- int randomIndex = rnd.nextInt(wrappedList.size());
+ int randomIndex = rnd.apply(wrappedList.size());
return wrappedList.get(randomIndex);
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#reduceAux(T, java.util.function.BiFunction, java.util.function.Function)
+ /*
+ * (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,
@@ -425,7 +486,7 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
}
// The current collapsed list
- IHolder<T> currentState = new GenHolder<>(initialValue);
+ IHolder<T> currentState = new Identity<>(initialValue);
wrappedList.forEach(element -> {
// Accumulate a new value into the state
@@ -437,8 +498,11 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return currentState.unwrap(resultTransformer);
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#removeIf(java.util.function.Predicate)
+ /*
+ * (non-Javadoc)
+ *
+ * @see bjc.utils.funcdata.IFunctionalList#removeIf(java.util.function.
+ * Predicate)
*/
@Override
public boolean removeIf(Predicate<E> removePredicate) {
@@ -449,7 +513,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return wrappedList.removeIf(removePredicate);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#removeMatching(E)
*/
@Override
@@ -457,8 +523,11 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
removeIf((element) -> element.equals(desiredElement));
}
- /* (non-Javadoc)
- * @see bjc.utils.funcdata.IFunctionalList#search(E, java.util.Comparator)
+ /*
+ * (non-Javadoc)
+ *
+ * @see bjc.utils.funcdata.IFunctionalList#search(E,
+ * java.util.Comparator)
*/
@Override
public E search(E searchKey, Comparator<E> comparator) {
@@ -475,7 +544,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return null;
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#sort(java.util.Comparator)
*/
@Override
@@ -483,7 +554,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
Collections.sort(wrappedList, comparator);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see bjc.utils.funcdata.IFunctionalList#toIterable()
*/
@Override
@@ -512,4 +585,9 @@ public class FunctionalList<E> implements Cloneable, IFunctionalList<E> {
return sb.toString();
}
+
+ @Override
+ public E[] toArray(E[] arrType) {
+ return wrappedList.toArray(arrType);
+ }
} \ No newline at end of file
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 b505ebd..da30064 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/FunctionalMap.java
@@ -6,7 +6,7 @@ import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
-import bjc.utils.data.Pair;
+import bjc.utils.data.experimental.IPair;
/**
* Basic implementation of {@link IFunctionalMap}
@@ -102,6 +102,11 @@ public class FunctionalMap<K, V> implements IFunctionalMap<K, V> {
action.accept(transformer.apply(val));
});
}
+
+ @Override
+ public IFunctionalList<V2> valueList() {
+ return mapToTransform.valueList().map(transformer);
+ }
}
private Map<K, V> wrappedMap;
@@ -134,10 +139,10 @@ public class FunctionalMap<K, V> implements IFunctionalMap<K, V> {
* The entries to put into the map
*/
@SafeVarargs
- public FunctionalMap(Pair<K, V>... entries) {
+ public FunctionalMap(IPair<K, V>... entries) {
this();
- for (Pair<K, V> entry : entries) {
+ for (IPair<K, V> entry : entries) {
entry.doWith((key, val) -> {
wrappedMap.put(key, val);
});
@@ -243,4 +248,15 @@ public class FunctionalMap<K, V> implements IFunctionalMap<K, V> {
public void forEachValue(Consumer<V> action) {
wrappedMap.values().forEach(action);
}
+
+ @Override
+ public IFunctionalList<V> valueList() {
+ FunctionalList<V> values = new FunctionalList<>();
+
+ wrappedMap.values().forEach((value) -> {
+ values.add(value);
+ });
+
+ return values;
+ }
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java
index a017aa9..949fc33 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalList.java
@@ -1,20 +1,22 @@
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;
+import bjc.utils.data.experimental.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.
*
+ * NOTE: The indications of complexity for methods assume that the backing
+ * list has performance on the order of an array
+ *
* @author ben
*
* @param <E>
@@ -25,6 +27,8 @@ public interface IFunctionalList<E> {
/**
* Add an item to this list
*
+ * Takes O(1) time.
+ *
* @param item
* The item to add to this list.
* @return Whether the item was added to the list succesfully.
@@ -35,6 +39,10 @@ public interface IFunctionalList<E> {
* Check if all of the elements of this list match the specified
* predicate.
*
+ * Takes O(f * p(n)) time on average, where f is defined as the average
+ * number of elements in a list until the predicate returns false, and
+ * p is the average running time of the predicate
+ *
* @param matchPredicate
* The predicate to use for checking.
* @return Whether all of the elements of the list match the specified
@@ -45,6 +53,10 @@ public interface IFunctionalList<E> {
/**
* Check if any of the elements in this list match the specified list.
*
+ * Takes O(f * p(n)) time on average, where f is defined as the average
+ * number of elements in a list until the predicate returns true, and p
+ * is the average running time of the predicate
+ *
* @param matchPredicate
* The predicate to use for checking.
* @return Whether any element in the list matches the provided
@@ -60,6 +72,10 @@ public interface IFunctionalList<E> {
* NOTE: The returned list will have the length of the shorter of this
* list and the combined one.
*
+ * Takes O(q * c(q)), where q is defined as the length of the shorter
+ * of this list and the provided one, and c is the running time of the
+ * combiner.
+ *
* @param <T>
* The type of the second list
* @param <F>
@@ -77,6 +93,8 @@ public interface IFunctionalList<E> {
/**
* Check if the list contains the specified item
*
+ * Takes O(n) time, assuming object compare in constant time.
+ *
* @param item
* The item to see if it is contained
* @return Whether or not the specified item is in the list
@@ -86,6 +104,8 @@ public interface IFunctionalList<E> {
/**
* Get the first element in the list
*
+ * Takes O(1) time
+ *
* @return The first element in this list.
*/
E first();
@@ -94,6 +114,9 @@ public interface IFunctionalList<E> {
* Apply a function to each member of the list, then flatten the
* results. Does not change the underlying list.
*
+ * Takes O(n * m) time, where m is the average number of elements in
+ * the returned list.
+ *
* @param <T>
* The type of the flattened list
*
@@ -108,6 +131,9 @@ public interface IFunctionalList<E> {
/**
* Apply a given action for each member of the list
*
+ * Takes O(n * f(n)) time, where n is the length of the list, and f is
+ * the running time of the action.
+ *
* @param action
* The action to apply to each member of the list.
*/
@@ -116,6 +142,9 @@ public interface IFunctionalList<E> {
/**
* Apply a given function to each element in the list and its index.
*
+ * Takes O(n * f(n)) time, where n is the length of the list, and f is
+ * the running time of the action.
+ *
* @param indexedAction
* The function to apply to each element in the list and its
* index.
@@ -125,6 +154,8 @@ public interface IFunctionalList<E> {
/**
* Retrieve a value in the list by its index.
*
+ * Takes O(1) time.
+ *
* @param index
* The index to retrieve a value from.
* @return The value at the specified index in the list.
@@ -134,6 +165,7 @@ public interface IFunctionalList<E> {
/**
* Retrieve a list containing all elements matching a predicate
*
+ * Takes O(n) time, where n is the number of elements in the list
* @param matchPredicate
* The predicate to match by
* @return A list containing all elements that match the predicate
@@ -206,7 +238,7 @@ public interface IFunctionalList<E> {
* The random number generator to use.
* @return A random element from this list.
*/
- E randItem(Random rnd);
+ E randItem(Function<Integer, Integer> rnd);
/**
* Reduce this list to a single value, using a accumulative approach.
@@ -278,4 +310,13 @@ public interface IFunctionalList<E> {
* @return An iterable view onto the list
*/
Iterable<E> toIterable();
+
+ /**
+ * Convert this list into an array
+ *
+ * @param arrType
+ * The type of array to return
+ * @return The list, as an array
+ */
+ E[] toArray(E[] arrType);
} \ 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
index e089850..c879229 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcdata/IFunctionalMap.java
@@ -118,4 +118,11 @@ public interface IFunctionalMap<K, V> {
* The action to perform on each value in the map
*/
void forEachValue(Consumer<V> action);
+
+ /**
+ * Get a list of the values in this map
+ *
+ * @return A list of values in this map
+ */
+ IFunctionalList<V> valueList();
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java
index f490727..3374aa2 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/EnumUtils.java
@@ -28,7 +28,7 @@ public class EnumUtils {
Random rnd) {
E[] enumValues = enumClass.getEnumConstants();
- return new FunctionalList<>(enumValues).randItem(rnd);
+ return new FunctionalList<>(enumValues).randItem(rnd::nextInt);
}
/**
@@ -54,7 +54,7 @@ public class EnumUtils {
int randomValueCount = enumValues.length - nValues;
for (int i = 0; i <= randomValueCount; i++) {
- E rDir = valueList.randItem(rnd);
+ E rDir = valueList.randItem(rnd::nextInt);
valueList.removeMatching(rDir);
}
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 871e1cf..132e4c5 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/ListUtils.java
@@ -1,5 +1,6 @@
package bjc.utils.funcutils;
+import java.util.ArrayList;
import java.util.Deque;
import java.util.function.BiFunction;
import java.util.function.Consumer;
@@ -20,8 +21,8 @@ import bjc.utils.funcdata.IFunctionalList;
public class ListUtils {
private static final int MAX_NTRIESPART = 50;
- private static final class TokenDeaffixer
- implements BiFunction<String, String, IFunctionalList<String>> {
+ private static final class TokenDeaffixer implements
+ BiFunction<String, String, IFunctionalList<String>> {
private String token;
public TokenDeaffixer(String tok) {
@@ -53,8 +54,8 @@ public class ListUtils {
}
}
- private static final class TokenSplitter
- implements BiFunction<String, String, IFunctionalList<String>> {
+ private static final class TokenSplitter implements
+ BiFunction<String, String, IFunctionalList<String>> {
private String tokenToSplit;
public TokenSplitter(String tok) {
@@ -351,4 +352,71 @@ public class ListUtils {
});
}
}
+
+ /**
+ * Select a number of random items from the list, with replacement
+ *
+ * @param <E>
+ * The type of items to select
+ * @param list
+ * The list to select from
+ * @param numberOfItems
+ * The number of items to selet
+ * @param rng
+ * A function that creates a random number from 0 to the
+ * desired number
+ * @return A new list containing the desired number of items randomly
+ * selected from the specified list
+ */
+ public static <E> IFunctionalList<E> drawWithReplacement(
+ IFunctionalList<E> list, int numberOfItems,
+ Function<Integer, Integer> rng) {
+ IFunctionalList<E> selectedItems = new FunctionalList<>(
+ new ArrayList<>(numberOfItems));
+
+ for (int i = 0; i < numberOfItems; i++) {
+ selectedItems.add(list.randItem(rng));
+ }
+
+ return selectedItems;
+ }
+
+ /**
+ * Select a number of random items from the list without replacement
+ *
+ * @param <E>
+ * The type of items to select
+ * @param list
+ * The list to select from
+ * @param numberOfItems
+ * The number of items to selet
+ * @param rng
+ * A function that creates a random number from 0 to the
+ * desired number
+ * @return A new list containing the desired number of items randomly
+ * selected from the specified list without replacement
+ */
+
+ public static <E> IFunctionalList<E> drawWithoutReplacement(
+ IFunctionalList<E> list, int numberOfItems,
+ Function<Integer, Integer> rng) {
+ IFunctionalList<E> selectedItems = new FunctionalList<>(
+ new ArrayList<>(numberOfItems));
+
+ int totalItems = list.getSize();
+
+ list.forEachIndexed((index, element) -> {
+ int winningChance = numberOfItems - selectedItems.getSize();
+ // n - m
+ int totalChance = totalItems - (index - 1);
+ // N - t
+
+ // Probability of selecting the t+1'th element
+ if (NumberUtils.isProbable(winningChance, totalChance, rng)) {
+ selectedItems.add(element);
+ }
+ });
+
+ return selectedItems;
+ }
} \ No newline at end of file
diff --git a/BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java b/BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java
new file mode 100644
index 0000000..1f8f61d
--- /dev/null
+++ b/BJC-Utils2/src/main/java/bjc/utils/funcutils/NumberUtils.java
@@ -0,0 +1,53 @@
+package bjc.utils.funcutils;
+
+import java.util.function.Function;
+
+/**
+ * Utility functions for dealing with numbers
+ *
+ * @author ben
+ *
+ */
+public class NumberUtils {
+ /**
+ * Compute the falling factorial of a number
+ *
+ * @param value
+ * The number to compute
+ * @param power
+ * The power to do the falling factorial for
+ * @return The falling factorial of the number to the power
+ */
+ public static int fallingFactorial(int value, int power) {
+ if (power == 0) {
+ return 1;
+ } else if (power == 1) {
+ return value;
+ } else {
+ int result = 1;
+
+ for (int currentSub = 0; currentSub < power
+ + 1; currentSub++) {
+ result *= value - currentSub;
+ }
+
+ return result;
+ }
+ }
+
+ /**
+ * Evaluates a linear probability distribution
+ *
+ * @param topExp
+ * The number of winning possibilities
+ * @param bottomExp
+ * The number of total possibilities
+ * @param rng
+ * The function to use to generate a random possibility
+ * @return Whether or not a random possibility was a winning one
+ */
+ public static boolean isProbable(int topExp, int bottomExp,
+ Function<Integer, Integer> rng) {
+ return rng.apply(bottomExp) < topExp;
+ }
+}
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 10da34e..f10ee26 100644
--- a/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java
+++ b/BJC-Utils2/src/main/java/bjc/utils/gen/WeightedRandom.java
@@ -1,11 +1,12 @@
package bjc.utils.gen;
import java.util.Random;
+
+import bjc.utils.data.experimental.IHolder;
+import bjc.utils.data.experimental.IPair;
+import bjc.utils.data.experimental.Identity;
import bjc.utils.funcdata.FunctionalList;
import bjc.utils.funcdata.IFunctionalList;
-import bjc.utils.data.GenHolder;
-import bjc.utils.data.IHolder;
-import bjc.utils.data.IPair;
/**
* Represents a random number generator where certain results are weighted
@@ -25,14 +26,14 @@ public class WeightedRandom<E> {
/**
* The list of possible results to pick from
*/
- private IFunctionalList<E> results;
+ private IFunctionalList<E> results;
/**
* The source for any needed random numbers
*/
- private Random source;
+ private Random source;
- private int totalChance;
+ private int totalChance;
/**
* Create a new weighted random generator with the specified source of
@@ -74,10 +75,10 @@ public class WeightedRandom<E> {
* @return A random value selected in a weighted fashion.
*/
public E generateValue() {
- GenHolder<Integer> randomValue =
- new GenHolder<>(source.nextInt(totalChance));
- IHolder<E> currentResult = new GenHolder<>();
- GenHolder<Boolean> valuePicked = new GenHolder<>(true);
+ IHolder<Integer> randomValue = new Identity<>(
+ source.nextInt(totalChance));
+ IHolder<E> currentResult = new Identity<>();
+ IHolder<Boolean> valuePicked = new Identity<>(true);
probabilities.forEachIndexed((itemIndex, itemProbability) -> {
if (valuePicked.unwrap(bool -> bool)) {