diff options
Diffstat (limited to 'src/main/java/bjc/esodata')
20 files changed, 1193 insertions, 273 deletions
diff --git a/src/main/java/bjc/esodata/AbbrevMap2.java b/src/main/java/bjc/esodata/AbbrevMap2.java index f131aec..259c963 100644 --- a/src/main/java/bjc/esodata/AbbrevMap2.java +++ b/src/main/java/bjc/esodata/AbbrevMap2.java @@ -36,9 +36,7 @@ public class AbbrevMap2 { */ public void add(String... words) { for (String word : words) { - for (String substr : genAbbrevs(word)) { - backing.add(substr, word); - } + for (String substr : genAbbrevs(word)) backing.add(substr, word); } } @@ -65,9 +63,7 @@ public class AbbrevMap2 { */ public void removeWords(String... words) { for (String word : words) { - for (String substr : genAbbrevs(word)) { - backing.remove(substr, word); - } + for (String substr : genAbbrevs(word)) backing.remove(substr, word); } } @@ -95,10 +91,7 @@ public class AbbrevMap2 { public String deabbrev(String word) { Set<String> st = backing.get(word); - if (st.size() == 1) { - return st.iterator().next(); - } else { - return null; - } + if (st.size() == 1) return st.iterator().next(); + else return null; } } diff --git a/src/main/java/bjc/esodata/DefaultList.java b/src/main/java/bjc/esodata/DefaultList.java index c4535bd..e622301 100644 --- a/src/main/java/bjc/esodata/DefaultList.java +++ b/src/main/java/bjc/esodata/DefaultList.java @@ -90,10 +90,8 @@ public class DefaultList<ValueType> extends AbstractList<ValueType> { @Override public ValueType get(int idx) { - if (idx < 0 || idx >= backing.size()) - return defVal; - - return backing.get(idx); + if (idx < 0 || idx >= backing.size()) return defVal; + else return backing.get(idx); } @Override diff --git a/src/main/java/bjc/esodata/Directory.java b/src/main/java/bjc/esodata/Directory.java index e083cd8..fa47b6f 100644 --- a/src/main/java/bjc/esodata/Directory.java +++ b/src/main/java/bjc/esodata/Directory.java @@ -59,8 +59,7 @@ public interface Directory<K, V> { * @return The new sub-directory, or null if one by that name already exists. */ default Directory<K, V> newSubdirectory(final K key) { - if (hasSubdirectory(key)) - return null; + if (hasSubdirectory(key)) return null; final Directory<K, V> dir = new SimpleDirectory<>(); diff --git a/src/main/java/bjc/esodata/DoubleTape.java b/src/main/java/bjc/esodata/DoubleTape.java index cc7cdb9..30d94a1 100644 --- a/src/main/java/bjc/esodata/DoubleTape.java +++ b/src/main/java/bjc/esodata/DoubleTape.java @@ -112,9 +112,7 @@ public class DoubleTape<T> implements Tape<T>, DoubleSided { public boolean left(final int amt) { final boolean succ = front.left(amt); - if (succ) { - back.right(amt); - } + if (succ) back.right(amt); return succ; } @@ -128,9 +126,7 @@ public class DoubleTape<T> implements Tape<T>, DoubleSided { public boolean right(final int amt) { final boolean succ = front.right(amt); - if (succ) { - back.left(amt); - } + if (succ) back.left(amt); return succ; } @@ -167,26 +163,23 @@ public class DoubleTape<T> implements Tape<T>, DoubleSided { @Override public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof DoubleTape<?>)) - return false; + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof DoubleTape<?>)) return false; final DoubleTape<?> other = (DoubleTape<?>) obj; if (back == null) { - if (other.back != null) - return false; - } else if (!back.equals(other.back)) + if (other.back != null) return false; + } else if (!back.equals(other.back)) { return false; + } if (front == null) { - if (other.front != null) - return false; - } else if (!front.equals(other.front)) + if (other.front != null) return false; + } else if (!front.equals(other.front)) { return false; + } return true; } diff --git a/src/main/java/bjc/esodata/FlatNestIterator.java b/src/main/java/bjc/esodata/FlatNestIterator.java new file mode 100644 index 0000000..42981f5 --- /dev/null +++ b/src/main/java/bjc/esodata/FlatNestIterator.java @@ -0,0 +1,103 @@ +package bjc.esodata; + +import java.util.*; + +import bjc.data.*; + +final class FlatNestIterator<Element> implements ListIterator<Element> +{ + private Deque<ListIterator<Either<Element, NestList<Element>>>> iterators; + + public FlatNestIterator(ListIterator<Either<Element, NestList<Element>>> iterator) + { + this.iterators = new ArrayDeque<>(); + this.iterators.add(iterator); + } + + @Override + public boolean hasNext() { + boolean result = false; + do { + result = iterators.peek().hasNext(); + + if (result == false) iterators.pop(); + } while (result == false && iterators.isEmpty() == false); + + return result; + } + + @Override + public Element next() { + Holder<Element> element = Holder.of(null); + do { + element = iterators.peek().next().extract((ele) -> { + return Holder.of(ele); + }, (lst) -> { + // Ignore empty sublists. + if (lst.size() != 0) iterators.push(lst.listIterator()); + + return null; + }); + } while (element == null && hasNext()); + + if (element == null) throw new NoSuchElementException(); + + return element.getValue(); + } + + @Override + public boolean hasPrevious() { + boolean result = false; + do { + result = iterators.peek().hasPrevious(); + + if (result == false) iterators.pop(); + } while (result == false && iterators.isEmpty() == false); + + return result; + } + + @Override + public Element previous() { + Holder<Element> element = Holder.of(null); + do { + element = iterators.peek().previous().extract((ele) -> { + return Holder.of(ele); + }, (lst) -> { + // Ignore empty sublists. + if (lst.size() != 0) iterators.push(lst.listIterator()); + + return null; + }); + } while (element == null && hasPrevious()); + + if (element == null) throw new NoSuchElementException(); + + return element.getValue(); + } + + @Override + public int nextIndex() { + return iterators.peek().nextIndex(); + } + + @Override + public int previousIndex() { + return iterators.peek().previousIndex(); + } + + @Override + public void remove() { + iterators.peek().remove(); + } + + @Override + public void set(Element e) { + iterators.peek().set(Either.left(e)); + } + + @Override + public void add(Element e) { + iterators.peek().add(Either.left(e)); + } +}
\ No newline at end of file diff --git a/src/main/java/bjc/esodata/MapSet.java b/src/main/java/bjc/esodata/MapSet.java index a80c482..7d77ad6 100644 --- a/src/main/java/bjc/esodata/MapSet.java +++ b/src/main/java/bjc/esodata/MapSet.java @@ -116,8 +116,7 @@ public class MapSet<KeyType, ValueType> extends AbstractMap<KeyType, ValueType> * @return False if there is no map attached to the key, true otherwise. */ public boolean setMap(String key) { - if (!backing.containsKey(key)) - return false; + if (!backing.containsKey(key)) return false; currentMap = backing.get(key); @@ -165,16 +164,14 @@ public class MapSet<KeyType, ValueType> extends AbstractMap<KeyType, ValueType> @Override public Set<Map.Entry<KeyType, ValueType>> entrySet() { - if (currentMap == null) - throw new NullPointerException("Current map is not set"); + if (currentMap == null) throw new NullPointerException("Current map is not set"); return currentMap.entrySet(); } @Override public ValueType put(KeyType key, ValueType value) { - if (currentMap == null) - throw new NullPointerException("Current map is not set"); + if (currentMap == null) throw new NullPointerException("Current map is not set"); return currentMap.put(key, value); } diff --git a/src/main/java/bjc/esodata/MinMaxList.java b/src/main/java/bjc/esodata/MinMaxList.java new file mode 100644 index 0000000..6747831 --- /dev/null +++ b/src/main/java/bjc/esodata/MinMaxList.java @@ -0,0 +1,238 @@ +package bjc.esodata; + +import java.util.*; + +// @FIXME Nov 15th, 2020 Ben Culkin :RecalcMinMax +// Is there some sort of way to avoid having to recalculate these elements when +// that element is removed? +/** + * A list that automatically tracks the minimum & maximum element of a list. + * + * @author Ben Culkin + * + * @param <ValueType> The type of element stored in the list. + * + */ +public class MinMaxList<ValueType> extends AbstractList<ValueType> { + private final List<ValueType> backing; + private final Comparator<ValueType> picker; + + private ValueType minElement; + private boolean recalcMin = false; + + private ValueType maxElement; + private boolean recalcMax = false; + + // Create constructors + + /** + * Create a new min/max list using the given comparator. + * + * @param picker The comparator to use to determine min/max elements. + */ + public MinMaxList(Comparator<ValueType> picker) { + this(picker, new ArrayList<>()); + } + + /** + * Create a new min/max list using the given comparator. + * + * @param picker The comparator to use to determine min/max elements. + * @param values The values to fill the list from. + */ + @SafeVarargs + public MinMaxList(Comparator<ValueType> picker, ValueType... values) { + this(picker); + + for (ValueType value : values) { + add(value); + } + } + /** + * Create a new min/max list using the given comparator. + * + * @param picker The comparator to use to determine min/max elements. + * @param backing The collection to use values from. + */ + public MinMaxList(Comparator<ValueType> picker, Collection<ValueType> backing) { + this(picker, new ArrayList<>(backing)); + } + + /** + * Create a new min/max list using the given comparator. + * + * @param picker The comparator to use to determine min/max elements. + * @param backing The list to use as a backing list. + */ + public MinMaxList(Comparator<ValueType> picker, List<ValueType> backing) { + this.backing = backing; + this.picker = picker; + + calculateBoth(); + } + + @Override + public ValueType get(int index) { + return backing.get(index); + } + + @Override + public ValueType set(int index, ValueType element) { + ValueType oldElement = backing.set(index, element); + + if (minElement == null) { + minElement = element; + } else if (picker.compare(element, minElement) < 0) { + minElement = element; + recalcMin = false; + } else if (oldElement.equals(minElement)) { + minElement = null; + recalcMin = true; + } + + if (maxElement == null) { + maxElement = element; + } else if (picker.compare(element, maxElement) > 0) { + maxElement = element; + recalcMax = false; + } else if (oldElement.equals(maxElement)) { + maxElement = null; + recalcMax = true; + } + + return oldElement; + } + + @Override + public void add(int index, ValueType element) { + backing.add(index, element); + + if (minElement == null) { + minElement = element; + } else if (picker.compare(element, minElement) < 0) { + minElement = element; + recalcMin = false; + } + + if (maxElement == null) { + maxElement = element; + } else if (picker.compare(element, maxElement) > 0) { + maxElement = element; + recalcMax = false; + } + } + + @Override + public ValueType remove(int index) { + ValueType oldElement = backing.remove(index); + + if (oldElement.equals(minElement)) { + minElement = null; + recalcMin = true; + } + + if (oldElement.equals(maxElement)) { + maxElement = null; + recalcMax = true; + } + + return oldElement; + } + + @Override + public int size() { + return backing.size(); + } + + /** + * Get the minimum element currently stored in this list. + * + * @return The minimum element stored in the list. + */ + public ValueType minimum() { + if (recalcMin) calculateMinimum(); + + return minElement; + } + + /** + * Get the maximum element currently stored in this list. + * + * @return The maximum element stored in the list. + */ + public ValueType maximum() { + if (recalcMax) calculateMaximum(); + + return maxElement; + } + + private void calculateMinimum() { + for (ValueType element : backing) { + if (minElement == null) { + minElement = element; + } else if (picker.compare(element, minElement) < 0) { + minElement = element; + } + } + + recalcMin = false; + } + + private void calculateMaximum() { + for (ValueType element : backing) { + if (maxElement == null) { + maxElement = element; + } else if (picker.compare(element, maxElement) > 0) { + maxElement = element; + } + } + + recalcMax = false; + } + + private void calculateBoth() { + for (ValueType element : backing) { + if (minElement == null) { + minElement = element; + } else if (picker.compare(element, minElement) < 0) { + minElement = element; + } + + if (maxElement == null) { + maxElement = element; + } else if (picker.compare(element, maxElement) > 0) { + maxElement = element; + } + } + + recalcMin = false; + recalcMax = false; + } + + @Override + public String toString() { + return String.format("%s (min: %s) (max: %s)", backing, + recalcMin ? "(unknown)" : minElement, + recalcMax ? "(unknown)" : maxElement); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Objects.hash(backing, picker); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!super.equals(obj)) return false; + if (getClass() != obj.getClass()) return false; + + MinMaxList<?> other = (MinMaxList<?>) obj; + + return Objects.equals(backing, other.backing) + && Objects.equals(picker, other.picker); + } +} diff --git a/src/main/java/bjc/esodata/Multimap.java b/src/main/java/bjc/esodata/Multimap.java index a79f1b0..fae872e 100644 --- a/src/main/java/bjc/esodata/Multimap.java +++ b/src/main/java/bjc/esodata/Multimap.java @@ -51,9 +51,8 @@ public class Multimap<KeyType, ValueType> { */ public void remove(KeyType key, ValueType value) { // We have no values for that key; bail. - if (!backing.containsKey(key)) - return; - + if (!backing.containsKey(key)) return; + backing.get(key).remove(value); } @@ -76,10 +75,8 @@ public class Multimap<KeyType, ValueType> { * @return A set containing all of the values that have been mapped to that key. */ public Set<ValueType> get(KeyType key) { - if (!backing.containsKey(key)) - return new HashSet<>(); - - return backing.get(key).values(); + if (!backing.containsKey(key)) return new HashSet<>(); + else return backing.get(key).values(); } /** @@ -107,8 +104,7 @@ public class Multimap<KeyType, ValueType> { * mapping. */ public boolean contains(KeyType key, ValueType value) { - if (!backing.containsKey(key)) - return false; + if (!backing.containsKey(key)) return false; return backing.get(key).contains(value) > 0; } diff --git a/src/main/java/bjc/esodata/NestList.java b/src/main/java/bjc/esodata/NestList.java new file mode 100644 index 0000000..eccaf9d --- /dev/null +++ b/src/main/java/bjc/esodata/NestList.java @@ -0,0 +1,389 @@ +package bjc.esodata; + +import static bjc.functypes.Combinators.*; + +import java.util.*; +import java.util.function.*; + +import bjc.data.*; + +/** + * A list which can contain sublists of itself. + * + * N.B: Be careful if you form a recursive list, as there is no form of detection + * in place for that. Some operations may work, but those that do a deep traversal + * of the list will not. + * + * @author Ben Culkin + * + * @param <Element> The type contained in the list. + */ +public class NestList<Element> extends AbstractList<Either<Element, NestList<Element>>> +{ + private final List<Either<Element, NestList<Element>>> backing; + + /** + * Create a new empty nesting list. + */ + public NestList() { + backing = new ArrayList<>(); + } + + /** + * Create a new empty nesting list with the given capacity. + * + * @param cap The capacity for the nesting list. + */ + public NestList(int cap) { + backing = new ArrayList<>(cap); + } + + /** + * Add an element to this list. + * + * @param element The element to add to the list. + * + * @return Whether we could add the element. + */ + public boolean addItem(Element element) { + return backing.add(Either.left(element)); + } + + /** + * Add a sublist to this list. + * + * @param element The sublist to add to this list. + * + * @return Whether we could add the sublist. + */ + public boolean addItem(NestList<Element> element) { + return backing.add(Either.right(element)); + } + /** + * Add elements to this list. + * + * @param elements The elements to add to the list. + * + * @return Whether we could add each element. + */ + public boolean[] addItems(@SuppressWarnings("unchecked") Element... elements) { + boolean[] vals = new boolean[elements.length]; + + for (int i = 0; i < vals.length; i++) + { + vals[i] = addItem(elements[i]); + } + + return vals; + } + + /** + * Add sublists to this list. + * + * @param elements The sublists to add to this list. + * + * @return Whether we could add each sublist. + */ + public boolean[] addItems(@SuppressWarnings("unchecked") NestList<Element>... elements) { + boolean[] vals = new boolean[elements.length]; + + for (int i = 0; i < vals.length; i++) + { + vals[i] = addItem(elements[i]); + } + + return vals; + } + + /** + * Add a sublist with the given elements to this list. + * + * @param elements The elements of the sublist. + * + * @return Whether or not we could add the sublist. + */ + public boolean addSublist(@SuppressWarnings("unchecked") Element... elements) { + NestList<Element> container = new NestList<>(elements.length); + + for (Element ele : elements) { + container.addItem(ele); + } + + return addItem(container); + } + + /** + * Return an iterator over a flattened version of this list. + * + * N.B: In certain cases involving empty sublists, the hasNext() operation\ + * may not be 100% accurate. Be warned. + * + * @return An iterator over a flattened variant of this list. + */ + public ListIterator<Element> flatIterator() { + return new FlatNestIterator<>(listIterator()); + } + + /** + * Flatten one level of nesting from this list. + * + * @return The list with one level of nesting flattened. + */ + public NestList<Element> flatten() { + NestList<Element> flatterList = new NestList<>(size()); + + backing.forEach((element) -> + element.pick(flatterList::addItem, flatterList::addAll) + ); + + return flatterList; + } + + /** + * Flatten this list recursively. + * + * @return A flattened form of this list. + */ + public List<Element> deepFlatten() { + List<Element> flatList = new ArrayList<>(); + + flatIterator().forEachRemaining(flatList::add); + + return flatList; + } + + /** + * Get the total number of elements contained in this list and all sublists. + * + * @return The total number of elements contained in this list. + */ + public int deepSize() { + int size = 0; + + for (Either<Element, NestList<Element>> element : backing) + { + size += element.extract((ele) -> 1, (lst) -> lst.deepSize()); + } + + return size; + } + + /** + * Replace all of the elements in this list in-place with transformed versions. + * + * @param elementOperator The operator to apply to elements. + * @param listOperator The operator to apply to sublists. + */ + public void replace( + UnaryOperator<Element> elementOperator, + UnaryOperator<NestList<Element>> listOperator) { + backing.replaceAll((ele) -> ele.map(elementOperator, listOperator)); + } + + /** + * Perform a shallow mapping over this list. + * + * @param <NewElement> The new element type. + * + * @param elementMapper The function to map elements. + * @param listMapper The function to map lists. + * + * @return A new list containing the mapped elements. + */ + public <NewElement> NestList<NewElement> map( + Function<Element, NewElement> elementMapper, + Function<NestList<Element>, NestList<NewElement>> listMapper) + { + NestList<NewElement> nest = new NestList<>(backing.size()); + + for (Either<Element, NestList<Element>> element : backing) + { + nest.add(element.map(elementMapper, listMapper)); + } + + return nest; + } + + /** + * Perform a recursive mapping over this list. + * + * @param <NewElement> The new element type. + * + * @param mapper The element mapper. + * + * @return A new list with the same structure, but transformed elements. + */ + public <NewElement> NestList<NewElement> deepMap( + Function<Element, NewElement> mapper) + { + return map(mapper, (lst) -> lst.deepMap(mapper)); + } + + /** + * Perform a mapping on the list with controllable recursion. + * + * Inspired by the function of the same name from Raku. + * + * @param <NewElement> The new element type. + * + * @param recurPredicate Determines whether to recur into a list or not. + * @param elementMapper The mapper on elements. + * @param listMapper The mapper on lists we aren't recursing into. + * + * @return A new list with its elements mapped. + */ + public <NewElement> NestList<NewElement> duckMap( + Predicate<NestList<Element>> recurPredicate, + Function<Element, NewElement> elementMapper, + Function<NestList<Element>, NestList<NewElement>> listMapper) + { + return map( + elementMapper, + iftt(recurPredicate, + (list) -> list.duckMap( + recurPredicate, elementMapper, listMapper), + listMapper + ) + ); + } + + /** + * Perform a reduction over this list. + * + * @param <Output> The type of the output value. + * + * @param initial The initial state of the output value. + * @param elementFolder The function to fold elements with. + * @param listFolder The function to fold lists with. + * + * @return The result of reducing the list. + */ + public <Output> Output reduce( + Output initial, + BiFunction<Output, Element, Output> elementFolder, + BiFunction<Output, NestList<Element>, Output> listFolder) + { + Holder<Output> out = Holder.of(initial); + for (Either<Element, NestList<Element>> item : backing) + { + out.transform((state) -> item.extract( + (ele) -> elementFolder.apply(state, ele), + (lst) -> listFolder.apply(state, lst)) + ); + } + + return out.getValue(); + } + + /** + * Perform a recursive reduction over this list. + * + * @param <Output> The type of the output value. + * + * @param initial The initial state of the output value. + * @param elementFolder The function to fold elements with. + * + * @return The result of recursively reducing the list. + */ + public <Output> Output deepReduce( + Output initial, + BiFunction<Output, Element, Output> elementFolder) + { + return reduce( + initial, + elementFolder, + (state, lst) -> lst.deepReduce(state, elementFolder)); + } + + /** + * Conditionally expand elements of this list into the provided list. + * + * @param nest The list to expand elements into. + * @param expandPicker Picks whether or not to expand a list. + * @param recur Whether or not to recursively expand lists. + * + * @return The provided list. + */ + public NestList<Element> expandInto( + NestList<Element> nest, + Predicate<NestList<Element>> expandPicker, + boolean recur) + { + return reduce(nest, + (state, item) -> with(state, (stat) -> stat.addItem(item)), + (state, list) -> { + if (expandPicker.test(list)) { + return list.reduce(nest, + (substate, subitem) + -> with(substate, + (subst) -> subst.addItem(subitem)), + (substate, sublist) + -> with(substate, (subst) -> { + if (recur) { + sublist.expandInto( + subst, + expandPicker, + recur); + } else { + subst.addItem(sublist); + } + })); + } else { + state.addItem(list); + return state; + } + }); + } + // List methods and other things. + + @Override + public boolean add(Either<Element, NestList<Element>> e) { + return backing.add(e); + } + + @Override + public void add(int index, Either<Element, NestList<Element>> element) { + backing.add(index, element); + } + + @Override + public Either<Element, NestList<Element>> get(int index) { + return backing.get(index); + } + + @SuppressWarnings("unlikely-arg-type") + @Override + public boolean remove(Object o) { + return backing.remove(o); + } + + + @Override + public Either<Element, NestList<Element>> remove(int index) { + return backing.remove(index); + } + + @Override + public int size() { + return backing.size(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Objects.hash(backing); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!super.equals(obj)) return false; + if (getClass() != obj.getClass()) return false; + + NestList<?> other = (NestList<?>) obj; + + return Objects.equals(backing, other.backing); + } +} diff --git a/src/main/java/bjc/esodata/PushdownMap.java b/src/main/java/bjc/esodata/PushdownMap.java index 54ae939..76dd2db 100644 --- a/src/main/java/bjc/esodata/PushdownMap.java +++ b/src/main/java/bjc/esodata/PushdownMap.java @@ -1,12 +1,10 @@ package bjc.esodata; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; +import java.util.*; +import java.util.function.*; -import bjc.funcdata.FunctionalMap; -import bjc.funcdata.IList; -import bjc.funcdata.IMap; +import bjc.data.*; +import bjc.funcdata.*; /** * A variant of a map where inserting a duplicate key shadows the existing value @@ -22,22 +20,22 @@ import bjc.funcdata.IMap; * @param <ValueType> * The values in the map. */ -public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> { +public class PushdownMap<KeyType, ValueType> implements MapEx<KeyType, ValueType> { /* Our backing storage. */ - private final IMap<KeyType, Stack<ValueType>> backing; + private final MapEx<KeyType, Stack<ValueType>> backing; + private boolean isFrozen = false; + private boolean thawEnabled = true; + /** Create a new empty stack-based map. */ public PushdownMap() { backing = new FunctionalMap<>(); } - /** Create a new empty stack-based map using the specified backing. */ - private PushdownMap(final IMap<KeyType, Stack<ValueType>> back) { - backing = back; - } - @Override public void clear() { + if (isFrozen) throw new ObjectFrozen("Can't clear frozen map"); + backing.clear(); } @@ -45,30 +43,15 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> public boolean containsKey(final KeyType key) { return backing.containsKey(key); } - - @Override - public IMap<KeyType, ValueType> extend() { - return new PushdownMap<>(backing.extend()); - } - + @Override public void forEach(final BiConsumer<KeyType, ValueType> action) { backing.forEach((key, stk) -> action.accept(key, stk.top())); } @Override - public void forEachKey(final Consumer<KeyType> action) { - backing.forEachKey(action); - } - - @Override - public void forEachValue(final Consumer<ValueType> action) { - backing.forEachValue(stk -> action.accept(stk.top())); - } - - @Override - public ValueType get(final KeyType key) { - return backing.get(key).top(); + public Optional<ValueType> get(final KeyType key) { + return backing.get(key).map((stack) -> stack.top()); } @Override @@ -77,23 +60,16 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> } @Override - public IList<KeyType> keyList() { + public ListEx<KeyType> keyList() { return backing.keyList(); } @Override - public <V2> IMap<KeyType, V2> transform(final Function<ValueType, V2> transformer) { - /* - * @NOTE Can and should we support this? More to the point, maybe this should be - * a map sub-type that does what it needs to? - */ - throw new UnsupportedOperationException("Cannot transform pushdown maps."); - } - - @Override public ValueType put(final KeyType key, final ValueType val) { + if (isFrozen) throw new ObjectFrozen("Can't insert key " + key + " into frozen map"); + if (backing.containsKey(key)) { - final Stack<ValueType> stk = backing.get(key); + final Stack<ValueType> stk = backing.get(key).get(); final ValueType vl = stk.top(); @@ -111,18 +87,19 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> @Override public ValueType remove(final KeyType key) { - final Stack<ValueType> stk = backing.get(key); + if (isFrozen) throw new ObjectFrozen("Can't remove key " + key + " from frozen map"); - if (stk.size() > 1) { - return stk.pop(); - } + Holder<ValueType> result = Holder.of(null); + + backing.get(key).ifPresent((stk) -> { + if (stk.size() > 1) { + result.replace(stk.pop()); + } else { + result.replace(backing.remove(key).top()); + } + }); - return backing.remove(key).top(); - } - - @Override - public IList<ValueType> valueList() { - return backing.valueList().map(Stack::top); + return result.getValue(); } @Override @@ -137,20 +114,17 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> @Override public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof PushdownMap<?, ?>)) - return false; + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof PushdownMap<?, ?>)) return false; final PushdownMap<?, ?> other = (PushdownMap<?, ?>) obj; if (backing == null) { - if (other.backing != null) - return false; - } else if (!backing.equals(other.backing)) + if (other.backing != null) return false; + } else if (!backing.equals(other.backing)) { return false; + } return true; } @@ -159,4 +133,43 @@ public class PushdownMap<KeyType, ValueType> implements IMap<KeyType, ValueType> public String toString() { return String.format("PushdownMap [backing=%s]", backing); } + + @Override + public boolean freeze() { + isFrozen = true; + + return true; + } + + @Override + public boolean thaw() { + if (thawEnabled) { + isFrozen = false; + return true; + } else { + return false; + } + } + + @Override + public boolean deepFreeze() { + thawEnabled = true; + + return freeze(); + } + + @Override + public boolean canFreeze() { + return true; + } + + @Override + public boolean canThaw() { + return thawEnabled; + } + + @Override + public boolean isFrozen() { + return isFrozen; + } } diff --git a/src/main/java/bjc/esodata/QueueStack.java b/src/main/java/bjc/esodata/QueueStack.java index c40721a..e310f16 100644 --- a/src/main/java/bjc/esodata/QueueStack.java +++ b/src/main/java/bjc/esodata/QueueStack.java @@ -29,16 +29,14 @@ public class QueueStack<T> extends Stack<T> { @Override public T pop() { - if (backing.isEmpty()) - throw new StackUnderflow(); + if (backing.isEmpty()) throw new StackUnderflow(); return backing.remove(); } @Override public T top() { - if (backing.isEmpty()) - throw new StackUnderflow(); + if (backing.isEmpty()) throw new StackUnderflow(); return backing.peek(); } @@ -76,20 +74,17 @@ public class QueueStack<T> extends Stack<T> { @Override public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof QueueStack<?>)) - return false; + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof QueueStack<?>)) return false; final QueueStack<?> other = (QueueStack<?>) obj; if (backing == null) { - if (other.backing != null) - return false; - } else if (!backing.equals(other.backing)) + if (other.backing != null) return false; + } else if (!backing.equals(other.backing)) { return false; + } return true; } diff --git a/src/main/java/bjc/esodata/SimpleDirectory.java b/src/main/java/bjc/esodata/SimpleDirectory.java index 672d92f..13a9f3e 100644 --- a/src/main/java/bjc/esodata/SimpleDirectory.java +++ b/src/main/java/bjc/esodata/SimpleDirectory.java @@ -1,7 +1,7 @@ package bjc.esodata; import bjc.funcdata.FunctionalMap; -import bjc.funcdata.IMap; +import bjc.funcdata.MapEx; /** * Simple implementation of {@link Directory}. @@ -18,9 +18,9 @@ import bjc.funcdata.IMap; */ public class SimpleDirectory<K, V> implements Directory<K, V> { /* Our sub-directories. */ - private final IMap<K, Directory<K, V>> children; + private final MapEx<K, Directory<K, V>> children; /* Our data. */ - private final IMap<K, V> data; + private final MapEx<K, V> data; /** Create a new directory. */ public SimpleDirectory() { @@ -30,7 +30,7 @@ public class SimpleDirectory<K, V> implements Directory<K, V> { @Override public Directory<K, V> getSubdirectory(final K key) { - return children.get(key); + return children.get(key).orElse(null); } @Override @@ -50,7 +50,7 @@ public class SimpleDirectory<K, V> implements Directory<K, V> { @Override public V getKey(final K key) { - return data.get(key); + return data.get(key).orElse(null); } @Override @@ -71,26 +71,23 @@ public class SimpleDirectory<K, V> implements Directory<K, V> { @Override public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof SimpleDirectory<?, ?>)) - return false; + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof SimpleDirectory<?, ?>)) return false; final SimpleDirectory<?, ?> other = (SimpleDirectory<?, ?>) obj; if (children == null) { - if (other.children != null) - return false; - } else if (!children.equals(other.children)) + if (other.children != null) return false; + } else if (!children.equals(other.children)) { return false; + } if (data == null) { - if (other.data != null) - return false; - } else if (!data.equals(other.data)) + if (other.data != null) return false; + } else if (!data.equals(other.data)) { return false; + } return true; } diff --git a/src/main/java/bjc/esodata/SimpleStack.java b/src/main/java/bjc/esodata/SimpleStack.java index b50521e..9c016c3 100644 --- a/src/main/java/bjc/esodata/SimpleStack.java +++ b/src/main/java/bjc/esodata/SimpleStack.java @@ -27,16 +27,14 @@ public class SimpleStack<T> extends Stack<T> { @Override public T pop() { - if (backing.isEmpty()) - throw new StackUnderflow(); + if (backing.isEmpty()) throw new StackUnderflow(); return backing.pop(); } @Override public T top() { - if (backing.isEmpty()) - throw new StackUnderflow(); + if (backing.isEmpty()) throw new StackUnderflow(); return backing.peek(); } @@ -69,20 +67,17 @@ public class SimpleStack<T> extends Stack<T> { @Override public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof SimpleStack<?>)) - return false; + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof SimpleStack<?>)) return false; final SimpleStack<?> other = (SimpleStack<?>) obj; if (backing == null) { - if (other.backing != null) - return false; - } else if (!backing.equals(other.backing)) + if (other.backing != null) return false; + } else if (!backing.equals(other.backing)) { return false; + } return true; } diff --git a/src/main/java/bjc/esodata/SingleTape.java b/src/main/java/bjc/esodata/SingleTape.java index ec56e2b..7c3a34f 100644 --- a/src/main/java/bjc/esodata/SingleTape.java +++ b/src/main/java/bjc/esodata/SingleTape.java @@ -45,9 +45,7 @@ public class SingleTape<T> implements Tape<T> { backing = new ArrayList<>(vals.length); - for (T val : vals) { - backing.add(val); - } + for (T val : vals) backing.add(val); } /** @@ -66,9 +64,7 @@ public class SingleTape<T> implements Tape<T> { public SingleTape(Iterable<T> itr) { this(false); - for (T itm : itr) { - backing.add(itm); - } + for (T itm : itr) backing.add(itm); } /** @@ -86,8 +82,7 @@ public class SingleTape<T> implements Tape<T> { @Override public T item() { - if (pos < 0 || pos >= backing.size()) - return null; + if (pos < 0 || pos >= backing.size()) return null; return backing.get(pos); } @@ -114,19 +109,16 @@ public class SingleTape<T> implements Tape<T> { @Override public void insertAfter(final T itm) { - if (pos == backing.size() - 1) { - backing.add(itm); - } else { - backing.add(pos + 1, itm); - } + if (pos == backing.size() - 1) backing.add(itm); + else backing.add(pos + 1, itm); } @Override public T remove() { final T res = backing.remove(pos); - if (pos != 0) { - pos -= 1; - } + + if (pos != 0) pos -= 1; + return res; } @@ -147,8 +139,7 @@ public class SingleTape<T> implements Tape<T> { @Override public boolean left(final int amt) { - if (pos - amt < 0) - return false; + if (pos - amt < 0) return false; pos -= amt; return true; @@ -163,11 +154,10 @@ public class SingleTape<T> implements Tape<T> { public boolean right(final int amt) { if (pos + amt > backing.size()) { if (autoExtend) { - while (pos + amt >= backing.size() - 1) { - backing.add(null); - } - } else + while (pos + amt >= backing.size() - 1) backing.add(null); + } else { return false; + } } pos += amt; @@ -176,15 +166,15 @@ public class SingleTape<T> implements Tape<T> { @Override public boolean seekTo(int tgtPos) { - if (tgtPos < 0) - return false; + if (tgtPos < 0) return false; - if (tgtPos >= backing.size() - 1) - if (autoExtend) - while (tgtPos >= backing.size() - 1) - backing.add(null); - else + if (tgtPos >= backing.size() - 1) { + if (autoExtend) { + while (tgtPos >= backing.size() - 1) backing.add(null); + } else { return false; + } + } pos = tgtPos; @@ -208,20 +198,17 @@ public class SingleTape<T> implements Tape<T> { @Override public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof SingleTape<?>)) - return false; + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof SingleTape<?>)) return false; final SingleTape<?> other = (SingleTape<?>) obj; if (backing == null) { - if (other.backing != null) - return false; - } else if (!backing.equals(other.backing)) + if (other.backing != null) return false; + } else if (!backing.equals(other.backing)) { return false; + } return true; } diff --git a/src/main/java/bjc/esodata/SpaghettiStack.java b/src/main/java/bjc/esodata/SpaghettiStack.java index fc3e154..4bd77d3 100644 --- a/src/main/java/bjc/esodata/SpaghettiStack.java +++ b/src/main/java/bjc/esodata/SpaghettiStack.java @@ -37,16 +37,14 @@ class SpaghettiStack<T> extends Stack<T> { @Override public T pop() { - if (backing.isEmpty()) - return parent.pop(); + if (backing.isEmpty()) return parent.pop(); return backing.pop(); } @Override public T top() { - if (backing.isEmpty()) - return parent.top(); + if (backing.isEmpty()) return parent.top(); return backing.top(); } @@ -82,26 +80,23 @@ class SpaghettiStack<T> extends Stack<T> { @Override public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof SpaghettiStack<?>)) - return false; + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof SpaghettiStack<?>)) return false; final SpaghettiStack<?> other = (SpaghettiStack<?>) obj; if (backing == null) { - if (other.backing != null) - return false; - } else if (!backing.equals(other.backing)) + if (other.backing != null) return false; + } else if (!backing.equals(other.backing)) { return false; + } if (parent == null) { - if (other.parent != null) - return false; - } else if (!parent.equals(other.parent)) + if (other.parent != null) return false; + } else if (!parent.equals(other.parent)) { return false; + } return true; } diff --git a/src/main/java/bjc/esodata/Stack.java b/src/main/java/bjc/esodata/Stack.java index 5ee5ef2..360e57d 100644 --- a/src/main/java/bjc/esodata/Stack.java +++ b/src/main/java/bjc/esodata/Stack.java @@ -96,9 +96,7 @@ public abstract class Stack<T> { * The elements to insert. */ public void pushAll(@SuppressWarnings("unchecked") T... elms) { - for (T elm : elms) { - push(elm); - } + for (T elm : elms) push(elm); } /** @@ -108,9 +106,7 @@ public abstract class Stack<T> { * The elements to insert. */ public void pushAll(List<T> elms) { - for (T elm : elms) { - push(elm); - } + for (T elm : elms) push(elm); } /** @@ -124,9 +120,7 @@ public abstract class Stack<T> { public List<T> multipop(int n) { List<T> lst = new LinkedList<>(); - for (int i = 0; i < n; i++) { - lst.add(pop()); - } + for (int i = 0; i < n; i++) lst.add(pop()); return lst; } @@ -142,9 +136,7 @@ public abstract class Stack<T> { public List<T> multipoprev(int n) { LinkedList<T> lst = new LinkedList<>(); - for (int i = 0; i < n; i++) { - lst.addFirst(pop()); - } + for (int i = 0; i < n; i++) lst.addFirst(pop()); return lst; } @@ -160,9 +152,7 @@ public abstract class Stack<T> { * The number of items to drop. */ public void drop(final int n) { - for (int i = 0; i < n; i++) { - pop(); - } + for (int i = 0; i < n; i++) pop(); } /** Drop one item from the stack. */ @@ -201,9 +191,7 @@ public abstract class Stack<T> { public void multidup(final int n, final int m) { List<T> lst = multipoprev(n); - for (int i = 0; i <= m; i++) { - pushAll(lst); - } + for (int i = 0; i <= m; i++) pushAll(lst); } /** @@ -235,15 +223,11 @@ public abstract class Stack<T> { List<T> lst = multipoprev(n); - for (final T nelm : lst) { - push(nelm); - } + for (final T nelm : lst) push(nelm); push(elm); - for (int i = 0; i < m; i++) { - pushAll(lst); - } + for (int i = 0; i < m; i++) pushAll(lst); } /** @@ -555,9 +539,7 @@ public abstract class Stack<T> { public void multiapply(final int n, final int m, final Consumer<Stack<T>> action) { final List<Consumer<Stack<T>>> actions = new ArrayList<>(m); - for (int i = 0; i < m; i++) { - actions.add(action); - } + for (int i = 0; i < m; i++) actions.add(action); multispread(n, actions); } diff --git a/src/main/java/bjc/esodata/TapeLibrary.java b/src/main/java/bjc/esodata/TapeLibrary.java new file mode 100644 index 0000000..922833f --- /dev/null +++ b/src/main/java/bjc/esodata/TapeLibrary.java @@ -0,0 +1,163 @@ +package bjc.esodata; + +import java.util.*; + +/** + * Represents a library of possible tapes, with a single tape 'mounted' or active + * at a time. + * + * @author Ben Culkin + * + * @param <ElementType> The type stored on each tape. + */ +public class TapeLibrary<ElementType> implements TapeView<ElementType> +{ + private final Map<String, Tape<ElementType>> library; + + private String currentLabel; + private Tape<ElementType> currentTape; + + private boolean allowAutoCreation; + + /** + * Get a view of this tape library as a map. + * + * Modifications to this map will apply to the library, but will not + * affect whether a given tape is mounted or not. Be forewarned. + * + * @return A view onto this tape library as a map. + */ + public Map<String, Tape<ElementType>> asMap() + { + return library; + } + + /** + * Create a new empty tape library, with no tape mounted. + */ + public TapeLibrary() + { + library = new HashMap<>(); + } + + /** + * Create a new tape, with a given tape mounted by default. + * + * @param label The label of the tape. + * @param tape The tape to mount. + */ + public TapeLibrary(String label, Tape<ElementType> tape) + { + this(); + library.put(label, tape); + + this.currentLabel = label; + this.currentTape = tape; + } + + @Override + public Tape<ElementType> tapeView() + { + return currentTape; + } + + /** + * Insert a tape into this library. + * + * @param label The label to use for the tape. + * @param tape The tape to add. + * + * @return The tape which previously had that label, or null if there was not one. + */ + public Tape<ElementType> insertTape(String label, Tape<ElementType> tape) + { + return library.put(label, tape); + } + + /** + * Remove a tape from this library. + * + * @param label The label of the tape to remove. + * + * @return The tape which had that label, or null if there was not one. + */ + public Tape<ElementType> removeTape(String label) + { + return library.remove(label); + } + + /** + * Check if this library has a tape with a given label. + * + * @param label The label of the tape to check for. + * + * @return Whether or not the library contains a tape with that label. + */ + public boolean hasTape(String label) + { + return allowAutoCreation ? true : library.containsKey(label); + } + + /** + * Mount a different tape in the library. + * + * @param label The label of the tape to mount. + * + * @return True if the tape was successfully mounted, false otherwise. + */ + public boolean mountTape(String label) + { + if (library.containsKey(label) || allowAutoCreation) + { + currentLabel = label; + currentTape = library.computeIfAbsent( + label, + (ignored) -> new SingleTape<>()); + + return true; + } else { + return false; + } + } + + /** + * Returns the label of the current tape. + * + * @return The label of the current tape, or null if no tape is + * currently 'mounted'. + */ + public String currentLabel() + { + return currentLabel; + } + + /** + * Unmount the currently mounted tape. + */ + public void ejectTape() + { + currentTape = null; + currentLabel = null; + } + + /** + * Check if this tape library currently allows auto-creation of + * non-existing tapes. + * + * @return Whether or not auto-creation of tapes is currently allowed. + */ + public boolean isAllowAutoCreation() { + return allowAutoCreation; + } + + /** + * Set whether or not this library allows auto-creation of non-existing + * tapes. + * + * @param allowAutoCreation Whether tape auto-creation is allowed. + */ + public void setAllowAutoCreation(boolean allowAutoCreation) + { + this.allowAutoCreation = allowAutoCreation; + } +} diff --git a/src/main/java/bjc/esodata/TapeView.java b/src/main/java/bjc/esodata/TapeView.java new file mode 100644 index 0000000..bfc33a9 --- /dev/null +++ b/src/main/java/bjc/esodata/TapeView.java @@ -0,0 +1,102 @@ +package bjc.esodata; + +/** + * An interface which allows you to view a given type as a tape. + * + * @author Ben Culkin + * + * @param <ElementType> The type of element contained in the tape. + */ +public interface TapeView<ElementType> extends Tape<ElementType> +{ + /** + * Return a view of this object as a tape. + * + * @return A view of this object as a tape. + */ + public Tape<ElementType> tapeView(); + + @Override + public default ElementType item() + { + return tapeView().item(); + } + + @Override + public default void item(ElementType itm) + { + tapeView().item(itm); + } + + @Override + public default int size() + { + return tapeView().size(); + } + + @Override + public default int position() + { + return tapeView().position(); + } + + @Override + public default void insertBefore(ElementType itm) + { + tapeView().insertBefore(itm); + } + + @Override + public default void insertAfter(ElementType itm) + { + tapeView().insertAfter(itm); + } + + @Override + public default ElementType remove() + { + return tapeView().remove(); + } + + @Override + public default void first() + { + tapeView().first(); + } + + @Override + public default void last() + { + tapeView().last(); + } + + @Override + public default boolean left() + { + return tapeView().left(); + } + + @Override + public default boolean left(int amt) + { + return tapeView().left(amt); + } + + @Override + public default boolean right() + { + return tapeView().right(); + } + + @Override + public default boolean right(int amt) + { + return tapeView().right(amt); + } + + @Override + public default boolean seekTo(int pos) + { + return tapeView().seekTo(pos); + } +} diff --git a/src/main/java/bjc/esodata/ThresholdSet.java b/src/main/java/bjc/esodata/ThresholdSet.java index ae277e1..9b8560b 100644 --- a/src/main/java/bjc/esodata/ThresholdSet.java +++ b/src/main/java/bjc/esodata/ThresholdSet.java @@ -37,8 +37,7 @@ public class ThresholdSet<KeyType> { int ret = ThresholdSet.this.add(key); // No change to set contents - if (ret > 2) - return false; + if (ret > 2) return false; return true; } @@ -52,8 +51,7 @@ public class ThresholdSet<KeyType> { int ret = ThresholdSet.this.remove(k); // We removed the element. - if (ret == 0) - return true; + if (ret == 0) return true; return false; } @@ -67,8 +65,7 @@ public class ThresholdSet<KeyType> { int ret = ThresholdSet.this.contains(k); // The object is set-visible - if (ret == 1) - return true; + if (ret == 1) return true; return false; } @@ -112,9 +109,7 @@ public class ThresholdSet<KeyType> { public int[] addKeys(@SuppressWarnings("unchecked") KeyType... keys) { int[] ret = new int[keys.length]; - for (int i = 0; i < keys.length; i++) { - ret[i] = add(keys[i]); - } + for (int i = 0; i < keys.length; i++) ret[i] = add(keys[i]); return ret; } @@ -162,9 +157,7 @@ public class ThresholdSet<KeyType> { public int[] removeKeys(@SuppressWarnings("unchecked") KeyType... keys) { int[] ret = new int[keys.length]; - for (int i = 0; i < keys.length; i++) { - ret[i] = remove(keys[i]); - } + for (int i = 0; i < keys.length; i++) ret[i] = remove(keys[i]); return ret; } @@ -217,9 +210,7 @@ public class ThresholdSet<KeyType> { public int[] containsKeys(@SuppressWarnings("unchecked") KeyType... keys) { int[] ret = new int[keys.length]; - for (int i = 0; i < keys.length; i++) { - ret[i] = contains(keys[i]); - } + for (int i = 0; i < keys.length; i++) ret[i] = contains(keys[i]); return ret; } @@ -233,12 +224,9 @@ public class ThresholdSet<KeyType> { * @return The number of times the key occurs; -1 if it doesn't occur. */ public int contains(KeyType key) { - if (keySet.contains(key)) - return 1; - if (!keyMap.containsKey(key)) - return -1; - - return keyMap.get(key); + if (keySet.contains(key)) return 1; + if (!keyMap.containsKey(key)) return -1; + else return keyMap.get(key); } /** diff --git a/src/main/java/bjc/esodata/UnifiedDirectory.java b/src/main/java/bjc/esodata/UnifiedDirectory.java index 2221615..1b630eb 100644 --- a/src/main/java/bjc/esodata/UnifiedDirectory.java +++ b/src/main/java/bjc/esodata/UnifiedDirectory.java @@ -1,7 +1,7 @@ package bjc.esodata; import bjc.funcdata.FunctionalMap; -import bjc.funcdata.IMap; +import bjc.funcdata.MapEx; /** * Simple implementation of {@link Directory}. @@ -18,9 +18,9 @@ import bjc.funcdata.IMap; */ public class UnifiedDirectory<K, V> implements Directory<K, V> { /* Our directory children. */ - private final IMap<K, Directory<K, V>> children; + private final MapEx<K, Directory<K, V>> children; /* Our data children. */ - private final IMap<K, V> data; + private final MapEx<K, V> data; /** Create a new directory. */ public UnifiedDirectory() { @@ -30,7 +30,7 @@ public class UnifiedDirectory<K, V> implements Directory<K, V> { @Override public Directory<K, V> getSubdirectory(final K key) { - return children.get(key); + return children.get(key).orElse(null); } @Override @@ -56,7 +56,7 @@ public class UnifiedDirectory<K, V> implements Directory<K, V> { @Override public V getKey(final K key) { - return data.get(key); + return data.get(key).orElse(null); } @Override @@ -82,26 +82,23 @@ public class UnifiedDirectory<K, V> implements Directory<K, V> { @Override public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof UnifiedDirectory<?, ?>)) - return false; + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof UnifiedDirectory<?, ?>)) return false; final UnifiedDirectory<?, ?> other = (UnifiedDirectory<?, ?>) obj; if (children == null) { - if (other.children != null) - return false; - } else if (!children.equals(other.children)) + if (other.children != null) return false; + } else if (!children.equals(other.children)) { return false; + } if (data == null) { - if (other.data != null) - return false; - } else if (!data.equals(other.data)) + if (other.data != null) return false; + } else if (!data.equals(other.data)) { return false; + } return true; } |
