From c82e3b3b2de0633317ec8fc85925e91422820597 Mon Sep 17 00:00:00 2001 From: "Benjamin J. Culkin" Date: Sun, 8 Oct 2017 22:39:59 -0300 Subject: Start splitting into maven modules --- base/src/main/java/bjc/utils/data/LazyPair.java | 240 ++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 base/src/main/java/bjc/utils/data/LazyPair.java (limited to 'base/src/main/java/bjc/utils/data/LazyPair.java') diff --git a/base/src/main/java/bjc/utils/data/LazyPair.java b/base/src/main/java/bjc/utils/data/LazyPair.java new file mode 100644 index 0000000..5cb85f3 --- /dev/null +++ b/base/src/main/java/bjc/utils/data/LazyPair.java @@ -0,0 +1,240 @@ +package bjc.utils.data; + +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; + +import bjc.utils.data.internals.BoundLazyPair; +import bjc.utils.data.internals.HalfBoundLazyPair; + +/** + * A lazy implementation of a pair + * + * @author ben + * + * @param + * The type on the left side of the pair + * @param + * The type on the right side of the pair + * + */ +public class LazyPair implements IPair { + private LeftType leftValue; + private RightType rightValue; + + private Supplier leftSupplier; + private Supplier rightSupplier; + + private boolean leftMaterialized; + private boolean rightMaterialized; + + /** + * Create a new lazy pair, using the set values + * + * @param leftVal + * The value for the left side of the pair + * @param rightVal + * The value for the right side of the pair + */ + public LazyPair(final LeftType leftVal, final RightType rightVal) { + leftValue = leftVal; + rightValue = rightVal; + + leftMaterialized = true; + rightMaterialized = true; + } + + /** + * Create a new lazy pair from the given value sources + * + * @param leftSupp + * The source for a value on the left side of the pair + * @param rightSupp + * The source for a value on the right side of the pair + */ + public LazyPair(final Supplier leftSupp, final Supplier rightSupp) { + // Use single suppliers to catch double-instantiation bugs + leftSupplier = new SingleSupplier<>(leftSupp); + rightSupplier = new SingleSupplier<>(rightSupp); + + leftMaterialized = false; + rightMaterialized = false; + } + + @Override + public IPair bind( + final BiFunction> binder) { + return new BoundLazyPair<>(leftSupplier, rightSupplier, binder); + } + + @Override + public IPair bindLeft( + final Function> leftBinder) { + final Supplier leftSupp = () -> { + if (leftMaterialized) return leftValue; + + return leftSupplier.get(); + }; + + return new HalfBoundLazyPair<>(leftSupp, leftBinder); + } + + @Override + public IPair bindRight( + final Function> rightBinder) { + final Supplier rightSupp = () -> { + if (rightMaterialized) return rightValue; + + return rightSupplier.get(); + }; + + return new HalfBoundLazyPair<>(rightSupp, rightBinder); + } + + @Override + public IPair combine( + final IPair otherPair, + final BiFunction leftCombiner, + final BiFunction rightCombiner) { + return otherPair.bind((otherLeft, otherRight) -> { + return bind((leftVal, rightVal) -> { + final CombinedLeft left = leftCombiner.apply(leftVal, otherLeft); + final CombinedRight right = rightCombiner.apply(rightVal, otherRight); + + return new LazyPair<>(left, right); + }); + }); + } + + @Override + public LeftType getLeft() { + if (!leftMaterialized) { + leftValue = leftSupplier.get(); + + leftMaterialized = true; + } + + return leftValue; + } + + @Override + public RightType getRight() { + if (!rightMaterialized) { + rightValue = rightSupplier.get(); + + rightMaterialized = true; + } + + return rightValue; + } + + @Override + public IPair mapLeft(final Function mapper) { + final Supplier leftSupp = () -> { + if (leftMaterialized) return mapper.apply(leftValue); + + return mapper.apply(leftSupplier.get()); + }; + + final Supplier rightSupp = () -> { + if (rightMaterialized) return rightValue; + + return rightSupplier.get(); + }; + + return new LazyPair<>(leftSupp, rightSupp); + } + + @Override + public IPair mapRight(final Function mapper) { + final Supplier leftSupp = () -> { + if (leftMaterialized) return leftValue; + + return leftSupplier.get(); + }; + + final Supplier rightSupp = () -> { + if (rightMaterialized) return mapper.apply(rightValue); + + return mapper.apply(rightSupplier.get()); + }; + + return new LazyPair<>(leftSupp, rightSupp); + } + + @Override + public MergedType merge(final BiFunction merger) { + if (!leftMaterialized) { + leftValue = leftSupplier.get(); + + leftMaterialized = true; + } + + if (!rightMaterialized) { + rightValue = rightSupplier.get(); + + rightMaterialized = true; + } + + return merger.apply(leftValue, rightValue); + } + + @Override + public String toString() { + String leftVal; + String rightVal; + + if (leftMaterialized) { + leftVal = leftValue.toString(); + } else { + leftVal = "(un-materialized)"; + } + + if (rightMaterialized) { + rightVal = rightValue.toString(); + } else { + rightVal = "(un-materialized)"; + } + + return String.format("pair[l=%s,r=%s]", leftVal, rightVal); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + + result = prime * result + (leftMaterialized ? 1231 : 1237); + result = prime * result + (leftValue == null ? 0 : leftValue.hashCode()); + result = prime * result + (rightMaterialized ? 1231 : 1237); + result = prime * result + (rightValue == null ? 0 : rightValue.hashCode()); + + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof LazyPair)) return false; + + final LazyPair other = (LazyPair) obj; + + if (leftMaterialized != other.leftMaterialized) return false; + + if (leftMaterialized) { + if (leftValue == null) { + if (other.leftValue != null) return false; + } else if (!leftValue.equals(other.leftValue)) return false; + } else return false; + + if (rightMaterialized != other.rightMaterialized) return false; + if (rightMaterialized) { + if (rightValue == null) { + if (other.rightValue != null) return false; + } else if (!rightValue.equals(other.rightValue)) return false; + } else return false; + + return true; + } +} -- cgit v1.2.3