diff --git a/lib/src/io/github/alechenninger/monarch/Assignments.java b/lib/src/io/github/alechenninger/monarch/Assignments.java index 082ed3b..d06c923 100644 --- a/lib/src/io/github/alechenninger/monarch/Assignments.java +++ b/lib/src/io/github/alechenninger/monarch/Assignments.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; @@ -34,6 +35,7 @@ public class Assignments implements Iterable { private final Set explicit = new LinkedHashSet<>(); private final Set implicit = new LinkedHashSet<>(); + private final Map byVariable = new HashMap<>(); private final Inventory inventory; private final int hash; @@ -119,12 +121,11 @@ public Assignments forkAt(String variable) { } public boolean isAssigned(String variable) { - return stream().anyMatch(a -> a.variable().name().equals(variable)); + return byVariable.containsKey(variable); } public Assignment forVariable(String variable) { - return stream().filter(a -> a.variable().name().equals(variable)) - .findAny() + return Optional.ofNullable(byVariable.get(variable)) .orElseThrow(NoSuchElementException::new); } @@ -255,7 +256,7 @@ public Map toMap() { } public Stream stream() { - return Stream.concat(explicit.stream(), implicit.stream()); + return byVariable.values().stream(); } @Override @@ -332,6 +333,7 @@ private void add(Assignment assignment) { } explicit.add(assignment); + byVariable.put(variable.name(), assignment); assignment.implied().forEach(this::addImplicit); } @@ -347,6 +349,7 @@ private void addImplicit(Assignment assignment) { } this.implicit.add(assignment); + byVariable.put(assignment.variable().name(), assignment); assignment.implied().forEach(this::addImplicit); } diff --git a/lib/src/io/github/alechenninger/monarch/Variable.java b/lib/src/io/github/alechenninger/monarch/Variable.java index 8fb2a4b..629a7e1 100644 --- a/lib/src/io/github/alechenninger/monarch/Variable.java +++ b/lib/src/io/github/alechenninger/monarch/Variable.java @@ -19,6 +19,7 @@ package io.github.alechenninger.monarch; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -32,6 +33,8 @@ public class Variable { private final List assignables; private final Inventory inventory; + private final Map cachedAssignments = new HashMap<>(); + public Variable(String name, List assignables, Inventory inventory) { this.name = Objects.requireNonNull(name, "name"); this.assignables = Objects.requireNonNull(assignables, "assignables"); @@ -76,18 +79,27 @@ public Set values(Assignments assignments) { } public Assignment assign(String value) { - Optional assignable = assignables.stream() - .filter(a -> a.value().equals(value)) - .findFirst(); + Assignment assignment; + + if (cachedAssignments.containsKey(value)) { + assignment = cachedAssignments.get(value); + } else { + assignment = assignables.stream() + .filter(a -> a.value().equals(value)) + .findFirst() + .map(a -> new Assignment(inventory, this, a)) + .orElse(null); + cachedAssignments.put(value, assignment); + } - if (!assignable.isPresent()) { + if (assignment == null) { throw new IllegalArgumentException("Cannot assign value <" + value + "> to variable <" + name + "> because value is not assignable for this variable. Check your assignment or " + "add value to inventory. An inventory needs to be comprehensive so it can be used to " + "discover all of the sources in your hierarchy."); } - return new Assignment(inventory, this, assignable.get()); + return assignment; } @Override