From: Robert Varga Date: Mon, 2 Jan 2017 13:29:57 +0000 (+0100) Subject: BUG-7464: make LNodeEntry implement Map.Entry X-Git-Tag: release/carbon~130 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;ds=sidebyside;h=e9fc6471a187f916885d36187b79e0fa95fb4ee3;p=yangtools.git BUG-7464: make LNodeEntry implement Map.Entry Since LNodeEntry already contains a key/value mapping, it is advantageous to make it also implement Map.Entry, simply because that allows us to skip temporary object instantiation when iterating over entries. This could be done via subclassing SimpleImmutableEntry, but that forces us to implement Serializable, which is not what we want. Change-Id: I3b0a2384dfbb9c2ed14dd6c9d66dfe91e883f97a Signed-off-by: Robert Varga --- diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java index 74ef6236d0..af9a8a2bd6 100644 --- a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java +++ b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/INode.java @@ -301,13 +301,13 @@ final class INode extends BasicNode { if (cond == null) { if (entry != null) { - return replaceln(ln, entry, v, ct) ? Optional.of(entry.value()) : null; + return replaceln(ln, entry, v, ct) ? Optional.of(entry.getValue()) : null; } return insertln(ln, k, v, ct) ? Optional.empty() : null; } else if (cond == ABSENT) { if (entry != null) { - return Optional.of(entry.value()); + return Optional.of(entry.getValue()); } return insertln(ln, k, v, ct) ? Optional.empty() : null; @@ -316,13 +316,13 @@ final class INode extends BasicNode { return Optional.empty(); } - return replaceln(ln, entry, v, ct) ? Optional.of(entry.value()) : null; + return replaceln(ln, entry, v, ct) ? Optional.of(entry.getValue()) : null; } else { - if (entry == null || !cond.equals(entry.value())) { + if (entry == null || !cond.equals(entry.getValue())) { return Optional.empty(); } - return replaceln(ln, entry, v, ct) ? Optional.of(entry.value()) : null; + return replaceln(ln, entry, v, ct) ? Optional.of(entry.getValue()) : null; } } else { throw new IllegalStateException("Unhandled node " + m); @@ -397,7 +397,7 @@ final class INode extends BasicNode { } else if (m instanceof LNode) { // 5) an l-node final LNodeEntry entry = ((LNode) m).get(ct.equiv(), k); - return entry != null ? entry.value() : null; + return entry != null ? entry.getValue() : null; } else { throw new IllegalStateException("Unhandled node " + m); } @@ -501,7 +501,7 @@ final class INode extends BasicNode { return Optional.empty(); } - final V value = entry.value(); + final V value = entry.getValue(); if (cond != null && !cond.equals(value)) { // Value does not match return Optional.empty(); diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNode.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNode.java index 40d2b782b2..ca28a06216 100644 --- a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNode.java +++ b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNode.java @@ -17,7 +17,6 @@ package org.opendaylight.yangtools.triemap; import java.util.Iterator; import java.util.Map.Entry; -import java.util.Optional; final class LNode extends MainNode { private final LNodeEntries listmap; @@ -38,11 +37,9 @@ final class LNode extends MainNode { // We only ever create ListMaps with two or more entries, and remove them as soon as they reach one element // (below), so we cannot observe a null return here. final LNodeEntries map = listmap.remove(entry); - final Optional> maybeKv = map.maybeSingleton(); - if (maybeKv.isPresent()) { - final Entry kv = maybeKv.get(); + if (map.isSingle()) { // create it tombed so that it gets compressed on subsequent accesses - return new TNode<>(kv.getKey(), kv.getValue(), hc); + return new TNode<>(map.getKey(), map.getValue(), hc); } return new LNode<>(map); @@ -70,6 +67,4 @@ final class LNode extends MainNode { Iterator> iterator() { return listmap.iterator(); } - - } \ No newline at end of file diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNodeEntries.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNodeEntries.java index 93382a9e63..e1a859afc5 100644 --- a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNodeEntries.java +++ b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNodeEntries.java @@ -15,11 +15,9 @@ */ package org.opendaylight.yangtools.triemap; -import java.util.AbstractMap.SimpleImmutableEntry; import java.util.Iterator; import java.util.Map.Entry; import java.util.NoSuchElementException; -import java.util.Optional; /** * Similar to Scala's ListMap. Stores a linked set of entries, guaranteed to contain unique entry keys. @@ -30,7 +28,7 @@ import java.util.Optional; * @param the type of values */ final class LNodeEntries extends LNodeEntry { - // Modified during remove0 only + // Modified during remove only private LNodeEntries next; private LNodeEntries(final K k, final V v) { @@ -46,8 +44,8 @@ final class LNodeEntries extends LNodeEntry { return new LNodeEntries<>(k1, v1, new LNodeEntries<>(k2, v2)); } - Optional> maybeSingleton() { - return next != null ? Optional.empty() : Optional.of(new SimpleImmutableEntry<>(key(), value())); + boolean isSingle() { + return next == null; } int size() { @@ -60,14 +58,14 @@ final class LNodeEntries extends LNodeEntry { LNodeEntry findEntry(final Equivalence equiv, final K key) { // We do not perform recursion on purpose here, so we do not run out of stack if the key hashing fails. - LNodeEntries head = this; + LNodeEntries entry = this; do { - if (equiv.equivalent(head.key(), key)) { - return head; + if (equiv.equivalent(entry.getKey(), key)) { + return entry; } - head = head.next; - } while (head != null); + entry = entry.next; + } while (entry != null); return null; } @@ -77,7 +75,7 @@ final class LNodeEntries extends LNodeEntry { } LNodeEntries replace(final LNodeEntry entry, final V v) { - return new LNodeEntries<>(entry.key(), v, remove(entry)); + return new LNodeEntries<>(entry.getKey(), v, remove(entry)); } LNodeEntries remove(final LNodeEntry entry) { @@ -85,22 +83,24 @@ final class LNodeEntries extends LNodeEntry { return next; } - final LNodeEntries ret = new LNodeEntries<>(key(), value()); + final LNodeEntries ret = new LNodeEntries<>(getKey(), getValue()); LNodeEntries last = ret; LNodeEntries cur = next; while (cur != null) { - if (entry.equals(cur)) { + // We cannot use equals() here, as it is wired to key/value equality, + // which we really do not want. + if (entry == cur) { last.next = cur.next; return ret; } - last.next = new LNodeEntries<>(cur.key(), cur.value()); + last.next = new LNodeEntries<>(cur.getKey(), cur.getValue()); last = last.next; cur = cur.next; } - throw new IllegalStateException("Entry " + entry + " not found in entries " + this); + throw new IllegalStateException(String.format("Entry %s not found", entry)); } Iterator> iterator() { @@ -125,7 +125,7 @@ final class LNodeEntries extends LNodeEntry { throw new NoSuchElementException(); } - final Entry res = new SimpleImmutableEntry<>(n.key(), n.value()); + final Entry res = n; n = n.next; return res; } diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNodeEntry.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNodeEntry.java index 66c11b721b..9005dc2ddd 100644 --- a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNodeEntry.java +++ b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/LNodeEntry.java @@ -15,29 +15,53 @@ */ package org.opendaylight.yangtools.triemap; +import java.util.Map.Entry; + /** - * A single entry in {@link LNodeEntries}. + * A single entry in {@link LNodeEntries}, implements {@link Entry} in order to prevent instantiation of objects for + * iteration. * * @author Robert Varga * * @param the type of key * @param the type of value */ -abstract class LNodeEntry { - private final V value; +abstract class LNodeEntry implements Entry { private final K key; + private final V value; LNodeEntry(final K key, final V value) { - this.value = value; this.key = key; + this.value = value; } - final K key() { + @Override + public final K getKey() { return key; } - final V value() { + @Override + public final V getValue() { return value; } + @Override + public final V setValue(final V value) { + throw new UnsupportedOperationException(); + } + + @Override + public final int hashCode() { + return EntryUtil.hash(key, value); + } + + @Override + public final boolean equals(final Object o) { + return EntryUtil.equal(o, key, value); + } + + @Override + public final String toString() { + return EntryUtil.string(key, value); + } }