diff --git a/src/main/java/org/apache/commons/collections4/trie/AbstractKeyAnalyzer.java b/src/main/java/org/apache/commons/collections4/trie/AbstractKeyAnalyzer.java index 5b4187eeb..55297ec78 100644 --- a/src/main/java/org/apache/commons/collections4/trie/AbstractKeyAnalyzer.java +++ b/src/main/java/org/apache/commons/collections4/trie/AbstractKeyAnalyzer.java @@ -18,12 +18,12 @@ package org.apache.commons.collections4.trie; /** * TODO: add javadoc - * + * * @since 4.0 * @version $Id$ */ public abstract class AbstractKeyAnalyzer implements KeyAnalyzer { - + private static final long serialVersionUID = -20497563720380683L; /** @@ -36,34 +36,34 @@ public abstract class AbstractKeyAnalyzer implements KeyAnalyzer { } else if (o2 == null) { return 1; } - + return ((Comparable)o1).compareTo(o2); } - - /** + + /** * Returns true if bitIndex is a {@link KeyAnalyzer#OUT_OF_BOUNDS_BIT_KEY} */ static boolean isOutOfBoundsIndex(final int bitIndex) { return bitIndex == OUT_OF_BOUNDS_BIT_KEY; } - /** + /** * Returns true if bitIndex is a {@link KeyAnalyzer#EQUAL_BIT_KEY} */ static boolean isEqualBitKey(final int bitIndex) { return bitIndex == EQUAL_BIT_KEY; } - /** - * Returns true if bitIndex is a {@link KeyAnalyzer#NULL_BIT_KEY} + /** + * Returns true if bitIndex is a {@link KeyAnalyzer#NULL_BIT_KEY} */ static boolean isNullBitKey(final int bitIndex) { return bitIndex == NULL_BIT_KEY; } - /** - * Returns true if the given bitIndex is valid. Indices - * are considered valid if they're between 0 and + /** + * Returns true if the given bitIndex is valid. Indices + * are considered valid if they're between 0 and * {@link Integer#MAX_VALUE} */ static boolean isValidBitIndex(final int bitIndex) { diff --git a/src/main/java/org/apache/commons/collections4/trie/AbstractTrie.java b/src/main/java/org/apache/commons/collections4/trie/AbstractTrie.java index 295175640..a5e14adce 100644 --- a/src/main/java/org/apache/commons/collections4/trie/AbstractTrie.java +++ b/src/main/java/org/apache/commons/collections4/trie/AbstractTrie.java @@ -23,43 +23,43 @@ import java.util.Map; import org.apache.commons.collections4.Trie; /** - * This class provides some basic {@link Trie} functionality and + * This class provides some basic {@link Trie} functionality and * utility methods for actual {@link Trie} implementations. - * + * * @since 4.0 * @version $Id$ */ -abstract class AbstractTrie extends AbstractMap +abstract class AbstractTrie extends AbstractMap implements Trie, Serializable { - + private static final long serialVersionUID = 5826987063535505652L; // TODO Privatise fields? /** - * The {@link KeyAnalyzer} that's being used to build the + * The {@link KeyAnalyzer} that's being used to build the * PATRICIA {@link Trie}. */ protected final KeyAnalyzer keyAnalyzer; - - /** + + /** * Constructs a new {@link Trie} using the given {@link KeyAnalyzer}. */ public AbstractTrie(final KeyAnalyzer keyAnalyzer) { if (keyAnalyzer == null) { throw new NullPointerException("keyAnalyzer"); } - + this.keyAnalyzer = keyAnalyzer; } - + /** * Returns the {@link KeyAnalyzer} that constructed the {@link Trie}. */ public KeyAnalyzer getKeyAnalyzer() { return keyAnalyzer; } - + /** * {@inheritDoc} */ @@ -70,7 +70,7 @@ abstract class AbstractTrie extends AbstractMap } return entry.getKey(); } - + /** * {@inheritDoc} */ @@ -81,7 +81,7 @@ abstract class AbstractTrie extends AbstractMap } return entry.getValue(); } - + @Override public String toString() { final StringBuilder buffer = new StringBuilder(); @@ -92,7 +92,7 @@ abstract class AbstractTrie extends AbstractMap buffer.append("}\n"); return buffer.toString(); } - + /** * A utility method to cast keys. It actually doesn't * cast anything. It's just fooling the compiler! @@ -101,33 +101,33 @@ abstract class AbstractTrie extends AbstractMap final K castKey(final Object key) { return (K)key; } - + /** * Returns the length of the given key in bits - * + * * @see KeyAnalyzer#lengthInBits(Object) */ final int lengthInBits(final K key) { if (key == null) { return 0; } - + return keyAnalyzer.lengthInBits(key); } - + /** * Returns the number of bits per element in the key - * + * * @see KeyAnalyzer#bitsPerElement() */ final int bitsPerElement() { return keyAnalyzer.bitsPerElement(); } - + /** - * Returns whether or not the given bit on the + * Returns whether or not the given bit on the * key is set or false if the key is null. - * + * * @see KeyAnalyzer#isBitSet(Object, int, int) */ final boolean isBitSet(final K key, final int bitIndex, final int lengthInBits) { @@ -136,15 +136,15 @@ abstract class AbstractTrie extends AbstractMap } return keyAnalyzer.isBitSet(key, bitIndex, lengthInBits); } - + /** * Utility method for calling {@link KeyAnalyzer#bitIndex(Object, int, int, Object, int, int)} */ final int bitIndex(final K key, final K foundKey) { - return keyAnalyzer.bitIndex(key, 0, lengthInBits(key), + return keyAnalyzer.bitIndex(key, 0, lengthInBits(key), foundKey, 0, lengthInBits(foundKey)); } - + /** * An utility method for calling {@link KeyAnalyzer#compare(Object, Object)} */ @@ -154,43 +154,43 @@ abstract class AbstractTrie extends AbstractMap } else if (other == null) { return false; } - + return keyAnalyzer.compare(key, other) == 0; } - + /** * Returns true if both values are either null or equal */ static boolean compare(final Object a, final Object b) { return a == null ? b == null : a.equals(b); } - + /** * A basic implementation of {@link Entry} */ abstract static class BasicEntry implements Map.Entry, Serializable { - + private static final long serialVersionUID = -944364551314110330L; protected K key; - + protected V value; - + private final int hashCode; - + public BasicEntry(final K key) { this.key = key; this.hashCode = key != null ? key.hashCode() : 0; } - + public BasicEntry(final K key, final V value) { this.key = key; this.value = value; - + this.hashCode = (key != null ? key.hashCode() : 0) ^ (value != null ? value.hashCode() : 0); } - + /** * Replaces the current key and value with the provided * key & value @@ -199,14 +199,14 @@ abstract class AbstractTrie extends AbstractMap this.key = key; return setValue(value); } - + /** * {@inheritDoc} */ public K getKey() { return key; } - + /** * {@inheritDoc} */ @@ -222,12 +222,12 @@ abstract class AbstractTrie extends AbstractMap this.value = value; return previous; } - + @Override public int hashCode() { return hashCode; } - + @Override public boolean equals(final Object o) { if (o == this) { @@ -235,15 +235,15 @@ abstract class AbstractTrie extends AbstractMap } else if (!(o instanceof Map.Entry)) { return false; } - + final Map.Entry other = (Map.Entry)o; - if (compare(key, other.getKey()) + if (compare(key, other.getKey()) && compare(value, other.getValue())) { return true; } return false; } - + @Override public String toString() { return key + "=" + value; diff --git a/src/main/java/org/apache/commons/collections4/trie/ByteArrayKeyAnalyzer.java b/src/main/java/org/apache/commons/collections4/trie/ByteArrayKeyAnalyzer.java index 0dce8aa1b..f720b2dd8 100644 --- a/src/main/java/org/apache/commons/collections4/trie/ByteArrayKeyAnalyzer.java +++ b/src/main/java/org/apache/commons/collections4/trie/ByteArrayKeyAnalyzer.java @@ -18,49 +18,49 @@ package org.apache.commons.collections4.trie; /** * A {@link KeyAnalyzer} for byte[]s. - * + * * @since 4.0 * @version $Id$ */ public class ByteArrayKeyAnalyzer extends AbstractKeyAnalyzer { - + private static final long serialVersionUID = 7382825097492285877L; /** * A singleton instance of {@link ByteArrayKeyAnalyzer} */ - public static final ByteArrayKeyAnalyzer INSTANCE + public static final ByteArrayKeyAnalyzer INSTANCE = new ByteArrayKeyAnalyzer(Integer.MAX_VALUE); - + /** * The length of an {@link Byte} in bits */ public static final int LENGTH = Byte.SIZE; - + /** * A bit mask where the first bit is 1 and the others are zero */ private static final int MSB = 0x80; - + /** * A place holder for null */ private static final byte[] NULL = new byte[0]; - + /** * The maximum length of a key in bits */ private final int maxLengthInBits; - + public ByteArrayKeyAnalyzer(final int maxLengthInBits) { if (maxLengthInBits < 0) { throw new IllegalArgumentException( "maxLengthInBits=" + maxLengthInBits); } - + this.maxLengthInBits = maxLengthInBits; } - + /** * Returns a bit mask where the given bit is set */ @@ -75,36 +75,36 @@ public class ByteArrayKeyAnalyzer extends AbstractKeyAnalyzer { public int getMaxLengthInBits() { return maxLengthInBits; } - + /** * {@inheritDoc} */ public int bitsPerElement() { return LENGTH; } - + /** * {@inheritDoc} */ public int lengthInBits(final byte[] key) { return key != null ? key.length * bitsPerElement() : 0; } - + /** * {@inheritDoc} */ public boolean isBitSet(final byte[] key, final int bitIndex, final int lengthInBits) { - if (key == null) { + if (key == null) { return false; } - + final int prefix = maxLengthInBits - lengthInBits; final int keyBitIndex = bitIndex - prefix; - + if (keyBitIndex >= lengthInBits || keyBitIndex < 0) { return false; } - + final int index = keyBitIndex / LENGTH; final int bit = keyBitIndex % LENGTH; return (key[index] & mask(bit)) != 0; @@ -113,66 +113,66 @@ public class ByteArrayKeyAnalyzer extends AbstractKeyAnalyzer { /** * {@inheritDoc} */ - public int bitIndex(final byte[] key, final int offsetInBits, final int lengthInBits, + public int bitIndex(final byte[] key, final int offsetInBits, final int lengthInBits, byte[] other, final int otherOffsetInBits, final int otherLengthInBits) { - + if (other == null) { other = NULL; } - + boolean allNull = true; final int length = Math.max(lengthInBits, otherLengthInBits); final int prefix = maxLengthInBits - length; - + if (prefix < 0) { return KeyAnalyzer.OUT_OF_BOUNDS_BIT_KEY; } - + for (int i = 0; i < length; i++) { final int index = prefix + offsetInBits + i; final boolean value = isBitSet(key, index, lengthInBits); - + if (value) { allNull = false; } - + final int otherIndex = prefix + otherOffsetInBits + i; final boolean otherValue = isBitSet(other, otherIndex, otherLengthInBits); - + if (value != otherValue) { return index; } } - + if (allNull) { return KeyAnalyzer.NULL_BIT_KEY; } - + return KeyAnalyzer.EQUAL_BIT_KEY; } - + /** * {@inheritDoc} */ - public boolean isPrefix(final byte[] prefix, final int offsetInBits, + public boolean isPrefix(final byte[] prefix, final int offsetInBits, final int lengthInBits, final byte[] key) { - + final int keyLength = lengthInBits(key); if (lengthInBits > keyLength) { return false; } - + final int elements = lengthInBits - offsetInBits; for (int i = 0; i < elements; i++) { - if (isBitSet(prefix, i+offsetInBits, lengthInBits) + if (isBitSet(prefix, i+offsetInBits, lengthInBits) != isBitSet(key, i, keyLength)) { return false; } } - + return true; } - + /** * {@inheritDoc} */ @@ -183,11 +183,11 @@ public class ByteArrayKeyAnalyzer extends AbstractKeyAnalyzer { } else if (o2 == null) { return 1; } - + if (o1.length != o2.length) { return o1.length - o2.length; } - + for (int i = 0; i < o1.length; i++) { final int diff = (o1[i] & 0xFF) - (o2[i] & 0xFF); if (diff != 0) { diff --git a/src/main/java/org/apache/commons/collections4/trie/ByteKeyAnalyzer.java b/src/main/java/org/apache/commons/collections4/trie/ByteKeyAnalyzer.java index 1541fdca2..8e390ecb5 100644 --- a/src/main/java/org/apache/commons/collections4/trie/ByteKeyAnalyzer.java +++ b/src/main/java/org/apache/commons/collections4/trie/ByteKeyAnalyzer.java @@ -18,29 +18,29 @@ package org.apache.commons.collections4.trie; /** * A {@link KeyAnalyzer} for {@link Byte}s. - * + * * @since 4.0 * @version $Id$ */ public class ByteKeyAnalyzer extends AbstractKeyAnalyzer { - + private static final long serialVersionUID = 3395803342983289829L; /** * A singleton instance of {@link ByteKeyAnalyzer} */ public static final ByteKeyAnalyzer INSTANCE = new ByteKeyAnalyzer(); - + /** * The length of an {@link Byte} in bits */ public static final int LENGTH = Byte.SIZE; - + /** * A bit mask where the first bit is 1 and the others are zero */ private static final int MSB = 0x80; - + /** * Returns a bit mask where the given bit is set */ @@ -54,7 +54,7 @@ public class ByteKeyAnalyzer extends AbstractKeyAnalyzer { public int bitsPerElement() { return 1; } - + /** * {@inheritDoc} */ @@ -72,21 +72,21 @@ public class ByteKeyAnalyzer extends AbstractKeyAnalyzer { /** * {@inheritDoc} */ - public int bitIndex(final Byte key, final int offsetInBits, final int lengthInBits, + public int bitIndex(final Byte key, final int offsetInBits, final int lengthInBits, final Byte other, final int otherOffsetInBits, final int otherLengthInBits) { - + if (offsetInBits != 0 || otherOffsetInBits != 0) { - throw new IllegalArgumentException("offsetInBits=" + offsetInBits + throw new IllegalArgumentException("offsetInBits=" + offsetInBits + ", otherOffsetInBits=" + otherOffsetInBits); } - + final byte keyValue = key.byteValue(); if (keyValue == 0) { return NULL_BIT_KEY; } final byte otherValue = other != null ? other.byteValue() : 0; - + if (keyValue != otherValue) { final int xorValue = keyValue ^ otherValue; for (int i = 0; i < LENGTH; i++) { @@ -95,24 +95,24 @@ public class ByteKeyAnalyzer extends AbstractKeyAnalyzer { } } } - + return KeyAnalyzer.EQUAL_BIT_KEY; } - + /** * {@inheritDoc} */ - public boolean isPrefix(final Byte prefix, final int offsetInBits, + public boolean isPrefix(final Byte prefix, final int offsetInBits, final int lengthInBits, final Byte key) { - + final int value1 = prefix.byteValue() << offsetInBits; final int value2 = key.byteValue(); - + int mask = 0; for (int i = 0; i < lengthInBits; i++) { mask |= 0x1 << i; } - + return (value1 & mask) == (value2 & mask); } } diff --git a/src/main/java/org/apache/commons/collections4/trie/CharArrayKeyAnalyzer.java b/src/main/java/org/apache/commons/collections4/trie/CharArrayKeyAnalyzer.java index 23c4d8d01..2ca1b57e1 100644 --- a/src/main/java/org/apache/commons/collections4/trie/CharArrayKeyAnalyzer.java +++ b/src/main/java/org/apache/commons/collections4/trie/CharArrayKeyAnalyzer.java @@ -18,12 +18,12 @@ package org.apache.commons.collections4.trie; /** * An {@link KeyAnalyzer} for {@code char[]}s. - * + * * @since 4.0 * @version $Id$ */ public class CharArrayKeyAnalyzer extends AbstractKeyAnalyzer { - + private static final long serialVersionUID = -8167897361549463457L; /** diff --git a/src/main/java/org/apache/commons/collections4/trie/IntegerKeyAnalyzer.java b/src/main/java/org/apache/commons/collections4/trie/IntegerKeyAnalyzer.java index 6fb29ba40..76de15aa6 100644 --- a/src/main/java/org/apache/commons/collections4/trie/IntegerKeyAnalyzer.java +++ b/src/main/java/org/apache/commons/collections4/trie/IntegerKeyAnalyzer.java @@ -18,29 +18,29 @@ package org.apache.commons.collections4.trie; /** * A {@link KeyAnalyzer} for {@link Integer}s. - * + * * @since 4.0 * @version $Id$ */ public class IntegerKeyAnalyzer extends AbstractKeyAnalyzer { - + private static final long serialVersionUID = 4928508653722068982L; - + /** * A singleton instance of {@link IntegerKeyAnalyzer} */ public static final IntegerKeyAnalyzer INSTANCE = new IntegerKeyAnalyzer(); - + /** * The length of an {@link Integer} in bits */ public static final int LENGTH = Integer.SIZE; - + /** * A bit mask where the first bit is 1 and the others are zero */ private static final int MSB = 0x80000000; - + /** * Returns a bit mask where the given bit is set */ @@ -54,7 +54,7 @@ public class IntegerKeyAnalyzer extends AbstractKeyAnalyzer { public int bitsPerElement() { return 1; } - + /** * {@inheritDoc} */ @@ -72,21 +72,21 @@ public class IntegerKeyAnalyzer extends AbstractKeyAnalyzer { /** * {@inheritDoc} */ - public int bitIndex(final Integer key, final int offsetInBits, final int lengthInBits, + public int bitIndex(final Integer key, final int offsetInBits, final int lengthInBits, final Integer other, final int otherOffsetInBits, final int otherLengthInBits) { - + if (offsetInBits != 0 || otherOffsetInBits != 0) { - throw new IllegalArgumentException("offsetInBits=" + offsetInBits + throw new IllegalArgumentException("offsetInBits=" + offsetInBits + ", otherOffsetInBits=" + otherOffsetInBits); } - + final int keyValue = key.intValue(); if (keyValue == 0) { return NULL_BIT_KEY; } final int otherValue = other != null ? other.intValue() : 0; - + if (keyValue != otherValue) { final int xorValue = keyValue ^ otherValue; for (int i = 0; i < LENGTH; i++) { @@ -95,24 +95,24 @@ public class IntegerKeyAnalyzer extends AbstractKeyAnalyzer { } } } - + return KeyAnalyzer.EQUAL_BIT_KEY; } - + /** * {@inheritDoc} */ - public boolean isPrefix(final Integer prefix, final int offsetInBits, + public boolean isPrefix(final Integer prefix, final int offsetInBits, final int lengthInBits, final Integer key) { - + final int value1 = prefix.intValue() << offsetInBits; final int value2 = key.intValue(); - + int mask = 0; for (int i = 0; i < lengthInBits; i++) { mask |= 0x1 << i; } - + return (value1 & mask) == (value2 & mask); } } diff --git a/src/main/java/org/apache/commons/collections4/trie/KeyAnalyzer.java b/src/main/java/org/apache/commons/collections4/trie/KeyAnalyzer.java index 5c3a7cbbd..c1825454f 100644 --- a/src/main/java/org/apache/commons/collections4/trie/KeyAnalyzer.java +++ b/src/main/java/org/apache/commons/collections4/trie/KeyAnalyzer.java @@ -19,57 +19,57 @@ package org.apache.commons.collections4.trie; import java.io.Serializable; import java.util.Comparator; -/** - * Defines the interface to analyze {@link org.apache.commons.collections4.Trie Trie} keys on a bit level. - * {@link KeyAnalyzer}'s methods return the length of the key in bits, - * whether or not a bit is set, and bits per element in the key. +/** + * Defines the interface to analyze {@link org.apache.commons.collections4.Trie Trie} keys on a bit level. + * {@link KeyAnalyzer}'s methods return the length of the key in bits, + * whether or not a bit is set, and bits per element in the key. *

- * Additionally, a method determines if a key is a prefix of another - * key and returns the bit index where one key is different from another - * key (if the key and found key are equal than the return value is + * Additionally, a method determines if a key is a prefix of another + * key and returns the bit index where one key is different from another + * key (if the key and found key are equal than the return value is * {@link #EQUAL_BIT_KEY}). - * + * * @since 4.0 * @version $Id$ */ public interface KeyAnalyzer extends Comparator, Serializable { - - /** - * Returned by {@link #bitIndex(Object, int, int, Object, int, int)} - * if key's bits are all 0 + + /** + * Returned by {@link #bitIndex(Object, int, int, Object, int, int)} + * if key's bits are all 0 */ public static final int NULL_BIT_KEY = -1; - - /** - * Returned by {@link #bitIndex(Object, int, int, Object, int, int)} - * if key and found key are equal. This is a very very specific case + + /** + * Returned by {@link #bitIndex(Object, int, int, Object, int, int)} + * if key and found key are equal. This is a very very specific case * and shouldn't happen on a regular basis */ public static final int EQUAL_BIT_KEY = -2; - + public static final int OUT_OF_BOUNDS_BIT_KEY = -3; - + /** * Returns the number of bits per element in the key. * This is only useful for variable-length keys, such as Strings. - * + * * @return the number of bits per element */ public int bitsPerElement(); - - /** + + /** * Returns the length of the Key in bits. - * + * * @param key the key * @return the bit length of the key */ public int lengthInBits(K key); - - /** + + /** * Returns whether or not a bit is set. */ public boolean isBitSet(K key, int bitIndex, int lengthInBits); - + /** * Returns the n-th different bit between key and found. This starts the comparison in * key at 'keyStart' and goes for 'keyLength' bits, and compares to the found key starting @@ -77,7 +77,7 @@ public interface KeyAnalyzer extends Comparator, Serializable { */ public int bitIndex(K key, int offsetInBits, int lengthInBits, K other, int otherOffsetInBits, int otherLengthInBits); - + /** * Determines whether or not the given prefix (from offset to length) is a prefix of the given key. */ diff --git a/src/main/java/org/apache/commons/collections4/trie/LongKeyAnalyzer.java b/src/main/java/org/apache/commons/collections4/trie/LongKeyAnalyzer.java index b79569a6b..75f29b282 100644 --- a/src/main/java/org/apache/commons/collections4/trie/LongKeyAnalyzer.java +++ b/src/main/java/org/apache/commons/collections4/trie/LongKeyAnalyzer.java @@ -18,29 +18,29 @@ package org.apache.commons.collections4.trie; /** * A {@link KeyAnalyzer} for {@link Long}s. - * + * * @since 4.0 * @version $Id$ */ public class LongKeyAnalyzer extends AbstractKeyAnalyzer { - + private static final long serialVersionUID = -4119639247588227409L; /** * A singleton instance of {@link LongKeyAnalyzer} */ public static final LongKeyAnalyzer INSTANCE = new LongKeyAnalyzer(); - + /** * The length of an {@link Long} in bits */ public static final int LENGTH = Long.SIZE; - + /** * A bit mask where the first bit is 1 and the others are zero */ private static final long MSB = 0x8000000000000000L; - + /** * Returns a bit mask where the given bit is set */ @@ -54,7 +54,7 @@ public class LongKeyAnalyzer extends AbstractKeyAnalyzer { public int bitsPerElement() { return 1; } - + /** * {@inheritDoc} */ @@ -72,21 +72,21 @@ public class LongKeyAnalyzer extends AbstractKeyAnalyzer { /** * {@inheritDoc} */ - public int bitIndex(final Long key, final int offsetInBits, final int lengthInBits, + public int bitIndex(final Long key, final int offsetInBits, final int lengthInBits, final Long other, final int otherOffsetInBits, final int otherLengthInBits) { - + if (offsetInBits != 0 || otherOffsetInBits != 0) { - throw new IllegalArgumentException("offsetInBits=" + offsetInBits + throw new IllegalArgumentException("offsetInBits=" + offsetInBits + ", otherOffsetInBits=" + otherOffsetInBits); } - + final long keyValue = key.longValue(); if (keyValue == 0L) { return NULL_BIT_KEY; } final long otherValue = other != null ? other.longValue() : 0L; - + if (keyValue != otherValue) { final long xorValue = keyValue ^ otherValue; for (int i = 0; i < LENGTH; i++) { @@ -95,24 +95,24 @@ public class LongKeyAnalyzer extends AbstractKeyAnalyzer { } } } - + return KeyAnalyzer.EQUAL_BIT_KEY; } - + /** * {@inheritDoc} */ - public boolean isPrefix(final Long prefix, final int offsetInBits, + public boolean isPrefix(final Long prefix, final int offsetInBits, final int lengthInBits, final Long key) { - + final long value1 = prefix.longValue() << offsetInBits; final long value2 = key.longValue(); - + long mask = 0L; for (int i = 0; i < lengthInBits; i++) { mask |= 0x1L << i; } - + return (value1 & mask) == (value2 & mask); } } diff --git a/src/main/java/org/apache/commons/collections4/trie/PatriciaTrie.java b/src/main/java/org/apache/commons/collections4/trie/PatriciaTrie.java index 7e8376208..1bf86b58d 100644 --- a/src/main/java/org/apache/commons/collections4/trie/PatriciaTrie.java +++ b/src/main/java/org/apache/commons/collections4/trie/PatriciaTrie.java @@ -30,39 +30,39 @@ import org.apache.commons.collections4.Trie; /** *

PATRICIA {@link Trie}

- * + * * Practical Algorithm to Retrieve Information Coded in Alphanumeric - * - *

A PATRICIA {@link Trie} is a compressed {@link Trie}. Instead of storing - * all data at the edges of the {@link Trie} (and having empty internal nodes), - * PATRICIA stores data in every node. This allows for very efficient traversal, - * insert, delete, predecessor, successor, prefix, range, and {@link #select(Object)} - * operations. All operations are performed at worst in O(K) time, where K - * is the number of bits in the largest item in the tree. In practice, - * operations actually take O(A(K)) time, where A(K) is the average number of + * + *

A PATRICIA {@link Trie} is a compressed {@link Trie}. Instead of storing + * all data at the edges of the {@link Trie} (and having empty internal nodes), + * PATRICIA stores data in every node. This allows for very efficient traversal, + * insert, delete, predecessor, successor, prefix, range, and {@link #select(Object)} + * operations. All operations are performed at worst in O(K) time, where K + * is the number of bits in the largest item in the tree. In practice, + * operations actually take O(A(K)) time, where A(K) is the average number of * bits of all items in the tree. - * + * *

Most importantly, PATRICIA requires very few comparisons to keys while - * doing any operation. While performing a lookup, each comparison (at most - * K of them, described above) will perform a single bit comparison against + * doing any operation. While performing a lookup, each comparison (at most + * K of them, described above) will perform a single bit comparison against * the given key, instead of comparing the entire key to another key. - * - *

The {@link Trie} can return operations in lexicographical order using the - * {@link #traverse(Cursor)}, 'prefix', 'submap', or 'iterator' methods. The - * {@link Trie} can also scan for items that are 'bitwise' (using an XOR - * metric) by the 'select' method. Bitwise closeness is determined by the - * {@link KeyAnalyzer} returning true or false for a bit being set or not in + * + *

The {@link Trie} can return operations in lexicographical order using the + * {@link #traverse(Cursor)}, 'prefix', 'submap', or 'iterator' methods. The + * {@link Trie} can also scan for items that are 'bitwise' (using an XOR + * metric) by the 'select' method. Bitwise closeness is determined by the + * {@link KeyAnalyzer} returning true or false for a bit being set or not in * a given key. - * - *

This PATRICIA {@link Trie} supports both variable length & fixed length - * keys. Some methods, such as {@link #getPrefixedBy(Object)} are suited only - * to variable length keys, whereas {@link #getPrefixedByBits(Object, int)} is + * + *

This PATRICIA {@link Trie} supports both variable length & fixed length + * keys. Some methods, such as {@link #getPrefixedBy(Object)} are suited only + * to variable length keys, whereas {@link #getPrefixedByBits(Object, int)} is * suited to fixed-size keys. - * - *

Any methods here that take an {@link Object} argument may throw a - * {@link ClassCastException} if the method is expecting an instance of K + * + *

Any methods here that take an {@link Object} argument may throw a + * {@link ClassCastException} if the method is expecting an instance of K * and it isn't K. - * + * * @see Radix Tree * @see PATRICIA * @see Crit-Bit Tree @@ -70,7 +70,7 @@ import org.apache.commons.collections4.Trie; * @version $Id$ */ public class PatriciaTrie extends PatriciaTrieBase implements Trie { - + private static final long serialVersionUID = 4446367780901817838L; public PatriciaTrie(final KeyAnalyzer keyAnalyzer) { @@ -81,14 +81,14 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie m) { super(keyAnalyzer, m); } - + /** * {@inheritDoc} */ public Comparator comparator() { return keyAnalyzer; } - + /** * {@inheritDoc} */ @@ -117,7 +117,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie getPrefixedByBits(final K key, final int lengthInBits) { return getPrefixedByBits(key, 0, lengthInBits); } - + /** * {@inheritDoc} */ @@ -135,36 +135,36 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie getPrefixedByBits(final K key, final int offsetInBits, final int lengthInBits) { - + final int offsetLength = offsetInBits + lengthInBits; if (offsetLength > lengthInBits(key)) { - throw new IllegalArgumentException(offsetInBits + " + " + throw new IllegalArgumentException(offsetInBits + " + " + lengthInBits + " > " + lengthInBits(key)); } - + if (offsetLength == 0) { return this; } - + return new PrefixRangeMap(key, offsetInBits, lengthInBits); } - + /** * {@inheritDoc} */ @@ -184,18 +184,18 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie tailMap(final K fromKey) { return new RangeEntryMap(fromKey, null); - } - + } + /** * Returns an entry strictly higher than the given key, * or null if no such entry exists. */ TrieEntry higherEntry(final K key) { // TODO: Cleanup so that we don't actually have to add/remove from the - // tree. (We do it here because there are other well-defined + // tree. (We do it here because there are other well-defined // functions to perform the search.) final int lengthInBits = lengthInBits(key); - + if (lengthInBits == 0) { if (!root.isEmpty()) { // If data in root, and more after -- return it. @@ -209,12 +209,12 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie found = getNearestEntryForKey(key, lengthInBits); if (compareKeys(key, found.key)) { return nextEntry(found); } - + final int bitIndex = bitIndex(key, found.key); if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) { final TrieEntry added = new TrieEntry(key, null, bitIndex); @@ -239,7 +239,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie found = getNearestEntryForKey(key, lengthInBits); if (compareKeys(key, found.key)) { return found; } - + final int bitIndex = bitIndex(key, found.key); if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) { final TrieEntry added = new TrieEntry(key, null, bitIndex); @@ -300,7 +300,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie found = getNearestEntryForKey(key, lengthInBits); if (compareKeys(key, found.key)) { return previousEntry(found); } - + final int bitIndex = bitIndex(key, found.key); if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) { final TrieEntry added = new TrieEntry(key, null, bitIndex); @@ -352,17 +352,17 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie floorEntry(final K key) { + TrieEntry floorEntry(final K key) { // TODO: Cleanup so that we don't actually have to add/remove from the - // tree. (We do it here because there are other well-defined + // tree. (We do it here because there are other well-defined // functions to perform the search.) final int lengthInBits = lengthInBits(key); - + if (lengthInBits == 0) { if (!root.isEmpty()) { return root; @@ -370,12 +370,12 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie found = getNearestEntryForKey(key, lengthInBits); if (compareKeys(key, found.key)) { return found; } - + final int bitIndex = bitIndex(key, found.key); if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) { final TrieEntry added = new TrieEntry(key, null, bitIndex); @@ -398,10 +398,10 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie lengthInBits. */ @@ -409,30 +409,30 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie current = root.left; TrieEntry path = root; while(true) { - if (current.bitIndex <= path.bitIndex + if (current.bitIndex <= path.bitIndex || lengthInBits < current.bitIndex) { break; } - + path = current; - if (!isBitSet(prefix, offsetInBits + current.bitIndex, + if (!isBitSet(prefix, offsetInBits + current.bitIndex, offsetInBits + lengthInBits)) { current = current.left; } else { current = current.right; } - } + } // Make sure the entry is valid for a subtree. final TrieEntry entry = current.isEmpty() ? path : current; - + // If entry is root, it can't be empty. if (entry.isEmpty()) { return null; } - + final int endIndexInBits = offsetInBits + lengthInBits; - + // if root && length of root is less than length of lookup, // there's nothing. // (this prevents returning the whole subtree if root has an empty @@ -440,35 +440,35 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie= 0 && bitIndex < lengthInBits) { return null; } - + return entry; } - + /** * Returns the last entry the {@link Trie} is storing. - * + * *

This is implemented by going always to the right until * we encounter a valid uplink. That uplink is the last key. */ TrieEntry lastEntry() { return followRight(root.left); } - + /** * Traverses down the right path until it finds an uplink. */ @@ -477,39 +477,39 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie node.bitIndex) { node = node.right; } - + return node.right; } - + /** * Returns the node lexicographically before the given node (or null if none). - * + * * This follows four simple branches: * - If the uplink that returned us was a right uplink: * - If predecessor's left is a valid uplink from predecessor, return it. * - Else, follow the right path from the predecessor's left. * - If the uplink that returned us was a left uplink: - * - Loop back through parents until we encounter a node where + * - Loop back through parents until we encounter a node where * node != node.parent.left. * - If node.parent.left is uplink from node.parent: * - If node.parent.left is not root, return it. * - If it is root & root isEmpty, return null. * - If it is root & root !isEmpty, return root. * - If node.parent.left is not uplink from node.parent: - * - Follow right path for first right child from node.parent.left - * + * - Follow right path for first right child from node.parent.left + * * @param start */ TrieEntry previousEntry(final TrieEntry start) { if (start.predecessor == null) { throw new IllegalArgumentException("must have come from somewhere!"); } - + if (start.predecessor.right == start) { if (isValidUplink(start.predecessor.left, start.predecessor)) { return start.predecessor.left; @@ -521,11 +521,11 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie nextEntryInSubtree(final TrieEntry node, + TrieEntry nextEntryInSubtree(final TrieEntry node, final TrieEntry parentOfSubtree) { if (node == null) { return firstEntry(); @@ -558,11 +558,11 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie + private abstract class RangeMap extends AbstractMap implements SortedMap { /** @@ -571,7 +571,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie> entrySet; /** - * Creates and returns an {@link #entrySet()} + * Creates and returns an {@link #entrySet()} * view of the {@link RangeMap} */ protected abstract Set> createEntrySet(); @@ -580,22 +580,22 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie createRangeMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive); } - + /** * A {@link RangeMap} that deals with {@link Entry}s */ private class RangeEntryMap extends RangeMap { - - /** - * The key to start from, null if the beginning. + + /** + * The key to start from, null if the beginning. */ private final K fromKey; - - /** - * The key to end at, null if till the end. + + /** + * The key to end at, null if till the end. */ private final K toKey; - - /** - * Whether or not the 'from' is inclusive. + + /** + * Whether or not the 'from' is inclusive. */ private final boolean fromInclusive; - - /** - * Whether or not the 'to' is inclusive. + + /** + * Whether or not the 'to' is inclusive. */ private final boolean toInclusive; - + /** * Creates a {@link RangeEntryMap} with the fromKey included and * the toKey excluded from the range @@ -805,28 +805,28 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie 0) { throw new IllegalArgumentException("fromKey > toKey"); } - + this.fromKey = fromKey; this.fromInclusive = fromInclusive; this.toKey = toKey; this.toInclusive = toInclusive; } - + /** * {@inheritDoc} */ @@ -841,7 +841,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie> createEntrySet() { return new RangeEntrySet(this); } - + /** * {@inheritDoc} */ @@ -920,7 +920,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie> { - + private final K excludedKey; /** * Creates a {@link EntryIterator} */ private EntryIterator( - final TrieEntry first, + final TrieEntry first, final TrieEntry last) { super(first); - + this.excludedKey = last != null ? last.getKey() : null; } @@ -1068,31 +1068,31 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie> it = entrySet().iterator(); size = 0; - + Map.Entry entry = null; if (it.hasNext()) { entry = it.next(); size = 1; } - + fromKey = entry == null ? null : entry.getKey(); if (fromKey != null) { final TrieEntry prior = previousEntry((TrieEntry)entry); fromKey = prior == null ? null : prior.getKey(); } - + toKey = fromKey; - + while (it.hasNext()) { ++size; entry = it.next(); } - + toKey = entry == null ? null : entry.getKey(); - + if (toKey != null) { entry = nextEntry((TrieEntry)entry); toKey = entry == null ? null : entry.getKey(); } - + expectedModCount = PatriciaTrie.this.modCount; } - + return size; } - + /** * {@inheritDoc} */ public K firstKey() { fixup(); - + Map.Entry e = null; if (fromKey == null) { e = firstEntry(); } else { e = higherEntry(fromKey); } - + final K first = e != null ? e.getKey() : null; - if (e == null || !keyAnalyzer.isPrefix(prefix, + if (e == null || !keyAnalyzer.isPrefix(prefix, offsetInBits, lengthInBits, first)) { throw new NoSuchElementException(); } - + return first; } @@ -1174,23 +1174,23 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie e = null; if (toKey == null) { e = lastEntry(); } else { e = lowerEntry(toKey); } - + final K last = e != null ? e.getKey() : null; - if (e == null || !keyAnalyzer.isPrefix(prefix, + if (e == null || !keyAnalyzer.isPrefix(prefix, offsetInBits, lengthInBits, last)) { throw new NoSuchElementException(); } - + return last; } - + /** * Returns true if this {@link PrefixRangeMap}'s key is a prefix * of the provided key. @@ -1207,7 +1207,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie prefixStart; - + private int expectedModCount = 0; - + /** * Creates a {@link PrefixRangeEntrySet} */ @@ -1295,7 +1295,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie> empty = Collections.emptySet(); return empty.iterator(); @@ -1323,20 +1323,20 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie> { - + private final TrieEntry entry; - + private int hit = 0; - + public SingletonIterator(final TrieEntry entry) { this.entry = entry; } - + /** * {@inheritDoc} */ @@ -1351,7 +1351,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie> { - + // values to reset the subtree if we remove it. - private final K prefix; + private final K prefix; private final int offset; private final int lengthInBits; private boolean lastOne; - + private TrieEntry subtree; // the subtree to search within - + /** - * Starts iteration at the given entry & search only + * Starts iteration at the given entry & search only * within the given subtree. */ - EntryIterator(final TrieEntry startScan, final K prefix, + EntryIterator(final TrieEntry startScan, final K prefix, final int offset, final int lengthInBits) { subtree = startScan; next = PatriciaTrie.this.followLeft(startScan); @@ -1405,7 +1405,7 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends PatriciaTrieBase implements Trie findNext(final TrieEntry prior) { return PatriciaTrie.this.nextEntryInSubtree(prior, subtree); } - + /** * {@inheritDoc} */ @@ -1426,15 +1426,15 @@ public class PatriciaTrie extends PatriciaTrieBase implements Trie extends AbstractTrie { - + private static final long serialVersionUID = 5155253417231339498L; /** - * The root node of the {@link Trie}. + * The root node of the {@link Trie}. */ final TrieEntry root = new TrieEntry(null, null, -1); - + /** * Each of these fields are initialized to contain an instance of the * appropriate view the first time this view is requested. The views are @@ -51,39 +51,39 @@ abstract class PatriciaTrieBase extends AbstractTrie { private transient volatile Set keySet; private transient volatile Collection values; private transient volatile Set> entrySet; - + /** * The current size of the {@link Trie} */ private int size = 0; - + /** * The number of times this {@link Trie} has been modified. * It's used to detect concurrent modifications and fail-fast * the {@link Iterator}s. */ transient int modCount = 0; - + public PatriciaTrieBase(final KeyAnalyzer keyAnalyzer) { super(keyAnalyzer); } - + /** - * Constructs a new {@link org.apache.commons.collections4.Trie Trie} using the given {@link KeyAnalyzer} - * and initializes the {@link org.apache.commons.collections4.Trie Trie} with the values from the + * Constructs a new {@link org.apache.commons.collections4.Trie Trie} using the given {@link KeyAnalyzer} + * and initializes the {@link org.apache.commons.collections4.Trie Trie} with the values from the * provided {@link Map}. */ - public PatriciaTrieBase(final KeyAnalyzer keyAnalyzer, + public PatriciaTrieBase(final KeyAnalyzer keyAnalyzer, final Map m) { super(keyAnalyzer); - + if (m == null) { throw new NullPointerException("m"); } - + putAll(m); } - + /** * {@inheritDoc} */ @@ -92,16 +92,16 @@ abstract class PatriciaTrieBase extends AbstractTrie { root.key = null; root.bitIndex = -1; root.value = null; - + root.parent = null; root.left = root; root.right = null; root.predecessor = root; - + size = 0; incrementModCount(); } - + /** * {@inheritDoc} */ @@ -109,7 +109,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public int size() { return size; } - + /** * A helper method to increment the {@link Trie} size * and the modification counter. @@ -118,7 +118,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { size++; incrementModCount(); } - + /** * A helper method to decrement the {@link Trie} size * and increment the modification counter. @@ -127,14 +127,14 @@ abstract class PatriciaTrieBase extends AbstractTrie { size--; incrementModCount(); } - + /** * A helper method to increment the modification counter. */ private void incrementModCount() { ++modCount; } - + /** * {@inheritDoc} */ @@ -143,9 +143,9 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (key == null) { throw new NullPointerException("Key cannot be null"); } - + final int lengthInBits = lengthInBits(key); - + // The only place to store a key with a length // of zero bits is the root node if (lengthInBits == 0) { @@ -156,7 +156,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { } return root.setKeyValue(key, value); } - + final TrieEntry found = getNearestEntryForKey(key, lengthInBits); if (compareKeys(key, found.key)) { if (found.isEmpty()) { // <- must be the root @@ -166,7 +166,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { } return found.setKeyValue(key, value); } - + final int bitIndex = bitIndex(key, found.key); if (!AbstractKeyAnalyzer.isOutOfBoundsIndex(bitIndex)) { if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) { // in 99.999...9% the case @@ -178,7 +178,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { } else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) { // A bits of the Key are zero. The only place to // store such a Key is the root Node! - + /* NULL BIT KEY */ if (root.isEmpty()) { incrementSize(); @@ -186,10 +186,10 @@ abstract class PatriciaTrieBase extends AbstractTrie { incrementModCount(); } return root.setKeyValue(key, value); - + } else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) { // This is a very special and rare case. - + /* REPLACE OLD KEY+VALUE */ if (found != root) { incrementModCount(); @@ -197,10 +197,10 @@ abstract class PatriciaTrieBase extends AbstractTrie { } } } - + throw new IndexOutOfBoundsException("Failed to put: " + key + " -> " + value + ", " + bitIndex); } - + /** * Adds the given {@link TrieEntry} to the {@link Trie} */ @@ -208,10 +208,10 @@ abstract class PatriciaTrieBase extends AbstractTrie { TrieEntry current = root.left; TrieEntry path = root; while(true) { - if (current.bitIndex >= entry.bitIndex + if (current.bitIndex >= entry.bitIndex || current.bitIndex <= path.bitIndex) { entry.predecessor = entry; - + if (!isBitSet(entry.key, entry.bitIndex, lengthInBits)) { entry.left = entry; entry.right = current; @@ -219,28 +219,28 @@ abstract class PatriciaTrieBase extends AbstractTrie { entry.left = current; entry.right = entry; } - + entry.parent = path; if (current.bitIndex >= entry.bitIndex) { current.parent = entry; } - + // if we inserted an uplink, set the predecessor on it if (current.bitIndex <= path.bitIndex) { current.predecessor = entry; } - + if (path == root || !isBitSet(entry.key, path.bitIndex, lengthInBits)) { path.left = entry; } else { path.right = entry; } - + return entry; } - + path = current; - + if (!isBitSet(entry.key, current.bitIndex, lengthInBits)) { current = current.left; } else { @@ -248,7 +248,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { } } } - + /** * {@inheritDoc} */ @@ -262,7 +262,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { * Returns the entry associated with the specified key in the * PatriciaTrieBase. Returns null if the map contains no mapping * for this key. - * + * * This may throw ClassCastException if the object is not of type K. */ TrieEntry getEntry(final Object k) { @@ -270,46 +270,46 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (key == null) { return null; } - + final int lengthInBits = lengthInBits(key); final TrieEntry entry = getNearestEntryForKey(key, lengthInBits); return !entry.isEmpty() && compareKeys(key, entry.key) ? entry : null; } - + /** * {@inheritDoc} */ public Map.Entry select(final K key) { final int lengthInBits = lengthInBits(key); - final Reference> reference + final Reference> reference = new Reference>(); if (!selectR(root.left, -1, key, lengthInBits, reference)) { return reference.get(); } return null; } - + /** * {@inheritDoc} */ public Map.Entry select(final K key, final Cursor cursor) { final int lengthInBits = lengthInBits(key); - final Reference> reference + final Reference> reference = new Reference>(); selectR(root.left, -1, key, lengthInBits, cursor, reference); return reference.get(); } /** - * This is equivalent to the other {@link #selectR(TrieEntry, int, - * Object, int, Cursor, Reference)} method but without its overhead - * because we're selecting only one best matching Entry from the + * This is equivalent to the other {@link #selectR(TrieEntry, int, + * Object, int, Cursor, Reference)} method but without its overhead + * because we're selecting only one best matching Entry from the * {@link Trie}. */ - private boolean selectR(final TrieEntry h, final int bitIndex, - final K key, final int lengthInBits, + private boolean selectR(final TrieEntry h, final int bitIndex, + final K key, final int lengthInBits, final Reference> reference) { - + if (h.bitIndex <= bitIndex) { // If we hit the root Node and it is empty // we have to look for an alternative best @@ -332,12 +332,12 @@ abstract class PatriciaTrieBase extends AbstractTrie { } return false; } - + /** - * + * */ - private boolean selectR(final TrieEntry h, final int bitIndex, - final K key, + private boolean selectR(final TrieEntry h, final int bitIndex, + final K key, final int lengthInBits, final Cursor cursor, final Reference> reference) { @@ -375,7 +375,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { return selectR(h.left, h.bitIndex, key, lengthInBits, cursor, reference); } } - + return false; } @@ -386,10 +386,10 @@ abstract class PatriciaTrieBase extends AbstractTrie { TrieEntry entry = nextEntry(null); while (entry != null) { final TrieEntry current = entry; - + final Decision decision = cursor.select(current); entry = nextEntry(current); - + switch(decision) { case EXIT: return current; @@ -406,10 +406,10 @@ abstract class PatriciaTrieBase extends AbstractTrie { break; } } - + return null; } - + /** * {@inheritDoc} */ @@ -418,13 +418,13 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (k == null) { return false; } - + final K key = castKey(k); final int lengthInBits = lengthInBits(key); final TrieEntry entry = getNearestEntryForKey(key, lengthInBits); return !entry.isEmpty() && compareKeys(key, entry.key); } - + /** * {@inheritDoc} */ @@ -435,7 +435,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { } return entrySet; } - + /** * {@inheritDoc} */ @@ -446,7 +446,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { } return keySet; } - + /** * {@inheritDoc} */ @@ -457,20 +457,20 @@ abstract class PatriciaTrieBase extends AbstractTrie { } return values; } - + /** * {@inheritDoc} - * - * @throws ClassCastException if provided key is of an incompatible type + * + * @throws ClassCastException if provided key is of an incompatible type */ @Override public V remove(final Object k) { if (k == null) { return null; } - + final K key = castKey(k); - final int lengthInBits = lengthInBits(key); + final int lengthInBits = lengthInBits(key); TrieEntry current = root.left; TrieEntry path = root; while (true) { @@ -481,9 +481,9 @@ abstract class PatriciaTrieBase extends AbstractTrie { return null; } } - + path = current; - + if (!isBitSet(key, current.bitIndex, lengthInBits)) { current = current.left; } else { @@ -491,12 +491,12 @@ abstract class PatriciaTrieBase extends AbstractTrie { } } } - + /** * Returns the nearest entry for a given key. This is useful * for finding knowing if a given key exists (and finding the value * for it), or for inserting the key. - * + * * The actual get implementation. This is very similar to * selectR but with the exception that it might return the * root Entry even if it's empty. @@ -508,7 +508,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (current.bitIndex <= path.bitIndex) { return current; } - + path = current; if (!isBitSet(key, current.bitIndex, lengthInBits)) { current = current.left; @@ -517,12 +517,12 @@ abstract class PatriciaTrieBase extends AbstractTrie { } } } - + /** * Removes a single entry from the {@link Trie}. - * + * * If we found a Key (Entry h) then figure out if it's - * an internal (hard to remove) or external Entry (easy + * an internal (hard to remove) or external Entry (easy * to remove) */ V removeEntry(final TrieEntry h) { @@ -533,14 +533,14 @@ abstract class PatriciaTrieBase extends AbstractTrie { removeExternalEntry(h); } } - + decrementSize(); return h.setKeyValue(null, null); } - + /** * Removes an external entry from the {@link Trie}. - * + * * If it's an external Entry then just remove it. * This is very easy and straight forward. */ @@ -549,29 +549,29 @@ abstract class PatriciaTrieBase extends AbstractTrie { throw new IllegalArgumentException("Cannot delete root Entry!"); } else if (!h.isExternalNode()) { throw new IllegalArgumentException(h + " is not an external Entry!"); - } - + } + final TrieEntry parent = h.parent; final TrieEntry child = h.left == h ? h.right : h.left; - + if (parent.left == h) { parent.left = child; } else { parent.right = child; } - + // either the parent is changing, or the predecessor is changing. if (child.bitIndex > parent.bitIndex) { child.parent = parent; } else { child.predecessor = parent; } - + } - + /** * Removes an internal entry from the {@link Trie}. - * + * * If it's an internal Entry then "good luck" with understanding * this code. The Idea is essentially that Entry p takes Entry h's * place in the trie which requires some re-wiring. @@ -581,18 +581,18 @@ abstract class PatriciaTrieBase extends AbstractTrie { throw new IllegalArgumentException("Cannot delete root Entry!"); } else if (!h.isInternalNode()) { throw new IllegalArgumentException(h + " is not an internal Entry!"); - } - + } + final TrieEntry p = h.predecessor; - + // Set P's bitIndex p.bitIndex = h.bitIndex; - + // Fix P's parent, predecessor and child Nodes { final TrieEntry parent = p.parent; final TrieEntry child = p.left == h ? p.right : p.left; - + // if it was looping to itself previously, // it will now be pointed from it's parent // (if we aren't removing it's parent -- @@ -602,30 +602,30 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (p.predecessor == p && p.parent != h) { p.predecessor = p.parent; } - + if (parent.left == p) { parent.left = child; } else { parent.right = child; } - + if (child.bitIndex > parent.bitIndex) { child.parent = parent; } } - + // Fix H's parent and child Nodes - { - // If H is a parent of its left and right child + { + // If H is a parent of its left and right child // then change them to P if (h.left.parent == h) { h.left.parent = p; } - + if (h.right.parent == h) { h.right.parent = p; } - + // Change H's parent if (h.parent.left == h) { h.parent.left = p; @@ -633,24 +633,24 @@ abstract class PatriciaTrieBase extends AbstractTrie { h.parent.right = p; } } - + // Copy the remaining fields from H to P //p.bitIndex = h.bitIndex; p.parent = h.parent; p.left = h.left; p.right = h.right; - + // Make sure that if h was pointing to any uplinks, // p now points to them. if (isValidUplink(p.left, p)) { p.left.predecessor = p; } - + if (isValidUplink(p.right, p)) { p.right.predecessor = p; - } + } } - + /** * Returns the entry lexicographically after the given entry. * If the given entry is null, returns the first node. @@ -662,43 +662,43 @@ abstract class PatriciaTrieBase extends AbstractTrie { return nextEntryImpl(node.predecessor, node, null); } } - + /** * Scans for the next node, starting at the specified point, and using 'previous' * as a hint that the last node we returned was 'previous' (so we know not to return * it again). If 'tree' is non-null, this will limit the search to the given tree. - * + * * The basic premise is that each iteration can follow the following steps: - * + * * 1) Scan all the way to the left. * a) If we already started from this node last time, proceed to Step 2. * b) If a valid uplink is found, use it. * c) If the result is an empty node (root not set), break the scan. * d) If we already returned the left node, break the scan. - * + * * 2) Check the right. * a) If we already returned the right node, proceed to Step 3. * b) If it is a valid uplink, use it. * c) Do Step 1 from the right node. - * + * * 3) Back up through the parents until we encounter find a parent * that we're not the right child of. - * + * * 4) If there's no right child of that parent, the iteration is finished. * Otherwise continue to Step 5. - * + * * 5) Check to see if the right child is a valid uplink. * a) If we already returned that child, proceed to Step 6. * Otherwise, use it. - * + * * 6) If the right child of the parent is the parent itself, we've * already found & returned the end of the Trie, so exit. - * + * * 7) Do Step 1 on the parent's right child. */ - TrieEntry nextEntryImpl(final TrieEntry start, + TrieEntry nextEntryImpl(final TrieEntry start, final TrieEntry previous, final TrieEntry tree) { - + TrieEntry current = start; // Only look at the left if this was a recursive or @@ -711,20 +711,20 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (previous == current.left) { break; } - + if (isValidUplink(current.left, current)) { return current.left; } - + current = current.left; } } - + // If there's no data at all, exit. if (current.isEmpty()) { return null; } - + // If we've already returned the left, // and the immediate right is null, // there's only one entry in the Trie @@ -737,18 +737,18 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (current.right == null) { return null; } - + // If nothing valid on the left, try the right. if (previous != current.right) { // See if it immediately is valid. if (isValidUplink(current.right, current)) { return current.right; } - + // Must search on the right's side if it wasn't initially valid. return nextEntryImpl(current.right, previous, tree); } - + // Neither left nor right are valid, find the first parent // whose child did not come from the right & traverse it. while (current == current.parent.right) { @@ -756,7 +756,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (current == tree) { return null; } - + current = current.parent; } @@ -764,30 +764,30 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (current == tree) { return null; } - + // If there's no right, the parent must be root, so we're done. if (current.parent.right == null) { return null; } - + // If the parent's right points to itself, we've found one. - if (previous != current.parent.right + if (previous != current.parent.right && isValidUplink(current.parent.right, current.parent)) { return current.parent.right; } - + // If the parent's right is itself, there can't be any more nodes. if (current.parent.right == current.parent) { return null; } - + // We need to traverse down the parent's right's path. return nextEntryImpl(current.parent.right, previous, tree); } - + /** * Returns the first entry the {@link Trie} is storing. - * + * * This is implemented by going always to the left until * we encounter a valid uplink. That uplink is the first key. */ @@ -796,12 +796,12 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (isEmpty()) { return null; } - + return followLeft(root); } - - /** - * Goes left through the tree until it finds a valid node. + + /** + * Goes left through the tree until it finds a valid node. */ TrieEntry followLeft(TrieEntry node) { while(true) { @@ -810,75 +810,75 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (child.isEmpty()) { child = node.right; } - + if (child.bitIndex <= node.bitIndex) { return child; } - + node = child; } } - - /** - * Returns true if 'next' is a valid uplink coming from 'from'. + + /** + * Returns true if 'next' is a valid uplink coming from 'from'. */ - static boolean isValidUplink(final TrieEntry next, final TrieEntry from) { + static boolean isValidUplink(final TrieEntry next, final TrieEntry from) { return next != null && next.bitIndex <= from.bitIndex && !next.isEmpty(); } - + /** - * A {@link Reference} allows us to return something through a Method's - * argument list. An alternative would be to an Array with a length of + * A {@link Reference} allows us to return something through a Method's + * argument list. An alternative would be to an Array with a length of * one (1) but that leads to compiler warnings. Computationally and memory - * wise there's no difference (except for the need to load the + * wise there's no difference (except for the need to load the * {@link Reference} Class but that happens only once). */ private static class Reference { - + private E item; - + public void set(final E item) { this.item = item; } - + public E get() { return item; } } - + /** * A {@link Trie} is a set of {@link TrieEntry} nodes */ static class TrieEntry extends BasicEntry { - + private static final long serialVersionUID = 4596023148184140013L; - + /** The index this entry is comparing. */ protected int bitIndex; - + /** The parent of this entry. */ protected TrieEntry parent; - + /** The left child of this entry. */ protected TrieEntry left; - + /** The right child of this entry. */ protected TrieEntry right; - - /** The entry who uplinks to this entry. */ + + /** The entry who uplinks to this entry. */ protected TrieEntry predecessor; - + public TrieEntry(final K key, final V value, final int bitIndex) { super(key, value); - + this.bitIndex = bitIndex; - + this.parent = null; this.left = this; this.right = null; this.predecessor = this; } - + /** * Whether or not the entry is storing a key. * Only the root can potentially be empty, all other @@ -887,16 +887,16 @@ abstract class PatriciaTrieBase extends AbstractTrie { public boolean isEmpty() { return key == null; } - - /** - * Neither the left nor right child is a loopback + + /** + * Neither the left nor right child is a loopback */ public boolean isInternalNode() { return left != this && right != this; } - - /** - * Either the left or right child is a loopback + + /** + * Either the left or right child is a loopback */ public boolean isExternalNode() { return !isInternalNode(); @@ -908,17 +908,17 @@ abstract class PatriciaTrieBase extends AbstractTrie { @Override public String toString() { final StringBuilder buffer = new StringBuilder(); - + if (bitIndex == -1) { buffer.append("RootEntry("); } else { buffer.append("Entry("); } - + buffer.append("key=").append(getKey()).append(" [").append(bitIndex).append("], "); buffer.append("value=").append(getValue()).append(", "); //buffer.append("bitIndex=").append(bitIndex).append(", "); - + if (parent != null) { if (parent.bitIndex == -1) { buffer.append("parent=").append("ROOT"); @@ -929,7 +929,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { buffer.append("parent=").append("null"); } buffer.append(", "); - + if (left != null) { if (left.bitIndex == -1) { buffer.append("left=").append("ROOT"); @@ -940,7 +940,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { buffer.append("left=").append("null"); } buffer.append(", "); - + if (right != null) { if (right.bitIndex == -1) { buffer.append("right=").append("ROOT"); @@ -951,7 +951,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { buffer.append("right=").append("null"); } buffer.append(", "); - + if (predecessor != null) { if(predecessor.bitIndex == -1) { buffer.append("predecessor=").append("ROOT"); @@ -960,19 +960,19 @@ abstract class PatriciaTrieBase extends AbstractTrie { append(predecessor.bitIndex).append("]"); } } - + buffer.append(")"); return buffer.toString(); } } - + /** - * This is a entry set view of the {@link Trie} as returned + * This is a entry set view of the {@link Trie} as returned * by {@link Map#entrySet()} */ private class EntrySet extends AbstractSet> { - + /** * {@inheritDoc} */ @@ -980,7 +980,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public Iterator> iterator() { return new EntryIterator(); } - + /** * {@inheritDoc} */ @@ -989,11 +989,11 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (!(o instanceof Map.Entry)) { return false; } - + final TrieEntry candidate = getEntry(((Map.Entry)o).getKey()); return candidate != null && candidate.equals(o); } - + /** * {@inheritDoc} */ @@ -1003,7 +1003,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { PatriciaTrieBase.this.remove(o); return size != size(); } - + /** * {@inheritDoc} */ @@ -1011,7 +1011,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public int size() { return PatriciaTrieBase.this.size(); } - + /** * {@inheritDoc} */ @@ -1019,7 +1019,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public void clear() { PatriciaTrieBase.this.clear(); } - + /** * An {@link Iterator} that returns {@link Entry} Objects */ @@ -1029,13 +1029,13 @@ abstract class PatriciaTrieBase extends AbstractTrie { } } } - + /** - * This is a key set view of the {@link Trie} as returned + * This is a key set view of the {@link Trie} as returned * by {@link Map#keySet()} */ private class KeySet extends AbstractSet { - + /** * {@inheritDoc} */ @@ -1043,7 +1043,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public Iterator iterator() { return new KeyIterator(); } - + /** * {@inheritDoc} */ @@ -1051,7 +1051,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public int size() { return PatriciaTrieBase.this.size(); } - + /** * {@inheritDoc} */ @@ -1059,7 +1059,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public boolean contains(final Object o) { return containsKey(o); } - + /** * {@inheritDoc} */ @@ -1069,7 +1069,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { PatriciaTrieBase.this.remove(o); return size != size(); } - + /** * {@inheritDoc} */ @@ -1077,7 +1077,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public void clear() { PatriciaTrieBase.this.clear(); } - + /** * An {@link Iterator} that returns Key Objects */ @@ -1087,13 +1087,13 @@ abstract class PatriciaTrieBase extends AbstractTrie { } } } - + /** - * This is a value view of the {@link Trie} as returned + * This is a value view of the {@link Trie} as returned * by {@link Map#values()} */ private class Values extends AbstractCollection { - + /** * {@inheritDoc} */ @@ -1101,7 +1101,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public Iterator iterator() { return new ValueIterator(); } - + /** * {@inheritDoc} */ @@ -1109,7 +1109,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public int size() { return PatriciaTrieBase.this.size(); } - + /** * {@inheritDoc} */ @@ -1117,7 +1117,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public boolean contains(final Object o) { return containsValue(o); } - + /** * {@inheritDoc} */ @@ -1125,7 +1125,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { public void clear() { PatriciaTrieBase.this.clear(); } - + /** * {@inheritDoc} */ @@ -1140,7 +1140,7 @@ abstract class PatriciaTrieBase extends AbstractTrie { } return false; } - + /** * An {@link Iterator} that returns Value Objects */ @@ -1150,66 +1150,66 @@ abstract class PatriciaTrieBase extends AbstractTrie { } } } - - /** - * An iterator for the entries. + + /** + * An iterator for the entries. */ abstract class TrieIterator implements Iterator { - + /** * For fast-fail */ protected int expectedModCount = PatriciaTrieBase.this.modCount; - + protected TrieEntry next; // the next node to return protected TrieEntry current; // the current entry we're on - + /** * Starts iteration from the root */ protected TrieIterator() { next = PatriciaTrieBase.this.nextEntry(null); } - + /** * Starts iteration at the given entry */ protected TrieIterator(final TrieEntry firstEntry) { next = firstEntry; } - + /** * Returns the next {@link TrieEntry} */ - protected TrieEntry nextEntry() { + protected TrieEntry nextEntry() { if (expectedModCount != PatriciaTrieBase.this.modCount) { throw new ConcurrentModificationException(); } - + final TrieEntry e = next; if (e == null) { throw new NoSuchElementException(); } - + next = findNext(e); current = e; return e; } - + /** * @see PatriciaTrie#nextEntry(TrieEntry) */ protected TrieEntry findNext(final TrieEntry prior) { return PatriciaTrieBase.this.nextEntry(prior); } - + /** * {@inheritDoc} */ public boolean hasNext() { return next != null; } - + /** * {@inheritDoc} */ @@ -1217,15 +1217,15 @@ abstract class PatriciaTrieBase extends AbstractTrie { if (current == null) { throw new IllegalStateException(); } - + if (expectedModCount != PatriciaTrieBase.this.modCount) { throw new ConcurrentModificationException(); } - + final TrieEntry node = current; current = null; PatriciaTrieBase.this.removeEntry(node); - + expectedModCount = PatriciaTrieBase.this.modCount; } } diff --git a/src/main/java/org/apache/commons/collections4/trie/ShortKeyAnalyzer.java b/src/main/java/org/apache/commons/collections4/trie/ShortKeyAnalyzer.java index b2debe10d..9e923c040 100644 --- a/src/main/java/org/apache/commons/collections4/trie/ShortKeyAnalyzer.java +++ b/src/main/java/org/apache/commons/collections4/trie/ShortKeyAnalyzer.java @@ -18,29 +18,29 @@ package org.apache.commons.collections4.trie; /** * A {@link KeyAnalyzer} for {@link Short}s. - * + * * @since 4.0 * @version $Id$ */ public class ShortKeyAnalyzer implements KeyAnalyzer { - + private static final long serialVersionUID = -8631376733513512017L; /** * A singleton instance of {@link ShortKeyAnalyzer} */ public static final ShortKeyAnalyzer INSTANCE = new ShortKeyAnalyzer(); - + /** * The length of an {@link Short} in bits */ public static final int LENGTH = Short.SIZE; - + /** * A bit mask where the first bit is 1 and the others are zero */ private static final int MSB = 0x8000; - + /** * Returns a bit mask where the given bit is set */ @@ -54,7 +54,7 @@ public class ShortKeyAnalyzer implements KeyAnalyzer { public int bitsPerElement() { return 1; } - + /** * {@inheritDoc} */ @@ -72,21 +72,21 @@ public class ShortKeyAnalyzer implements KeyAnalyzer { /** * {@inheritDoc} */ - public int bitIndex(final Short key, final int offsetInBits, final int lengthInBits, + public int bitIndex(final Short key, final int offsetInBits, final int lengthInBits, final Short other, final int otherOffsetInBits, final int otherLengthInBits) { - + if (offsetInBits != 0 || otherOffsetInBits != 0) { - throw new IllegalArgumentException("offsetInBits=" + offsetInBits + throw new IllegalArgumentException("offsetInBits=" + offsetInBits + ", otherOffsetInBits=" + otherOffsetInBits); } - + final int keyValue = key.shortValue(); if (keyValue == 0) { return NULL_BIT_KEY; } final int otherValue = other != null ? other.shortValue() : 0; - + if (keyValue != otherValue) { final int xorValue = keyValue ^ otherValue; for (int i = 0; i < LENGTH; i++) { @@ -95,7 +95,7 @@ public class ShortKeyAnalyzer implements KeyAnalyzer { } } } - + return KeyAnalyzer.EQUAL_BIT_KEY; } @@ -105,21 +105,21 @@ public class ShortKeyAnalyzer implements KeyAnalyzer { public int compare(final Short o1, final Short o2) { return o1.compareTo(o2); } - + /** * {@inheritDoc} */ - public boolean isPrefix(final Short prefix, final int offsetInBits, + public boolean isPrefix(final Short prefix, final int offsetInBits, final int lengthInBits, final Short key) { - + final int value1 = prefix.shortValue() << offsetInBits; final int value2 = key.shortValue(); - + int mask = 0; for (int i = 0; i < lengthInBits; i++) { mask |= 0x1 << i; } - + return (value1 & mask) == (value2 & mask); } } diff --git a/src/main/java/org/apache/commons/collections4/trie/StringKeyAnalyzer.java b/src/main/java/org/apache/commons/collections4/trie/StringKeyAnalyzer.java index eac7a12b4..206238efb 100644 --- a/src/main/java/org/apache/commons/collections4/trie/StringKeyAnalyzer.java +++ b/src/main/java/org/apache/commons/collections4/trie/StringKeyAnalyzer.java @@ -18,72 +18,72 @@ package org.apache.commons.collections4.trie; /** * An {@link KeyAnalyzer} for {@link String}s. - * + * * @since 4.0 * @version $Id$ */ public class StringKeyAnalyzer extends AbstractKeyAnalyzer { - + private static final long serialVersionUID = -7032449491269434877L; - + /** * A singleton instance of {@link StringKeyAnalyzer} */ public static final StringKeyAnalyzer INSTANCE = new StringKeyAnalyzer(); - + /** * The number of bits per {@link Character} */ public static final int LENGTH = Character.SIZE; - + /** * A bit mask where the first bit is 1 and the others are zero */ private static final int MSB = 0x8000; - + /** * Returns a bit mask where the given bit is set */ private static int mask(final int bit) { return MSB >>> bit; } - + /** * {@inheritDoc} */ public int bitsPerElement() { return LENGTH; } - + /** * {@inheritDoc} */ public int lengthInBits(final String key) { return key != null ? key.length() * LENGTH : 0; } - + /** * {@inheritDoc} */ public int bitIndex(final String key, final int offsetInBits, final int lengthInBits, final String other, final int otherOffsetInBits, final int otherLengthInBits) { boolean allNull = true; - - if (offsetInBits % LENGTH != 0 || otherOffsetInBits % LENGTH != 0 + + if (offsetInBits % LENGTH != 0 || otherOffsetInBits % LENGTH != 0 || lengthInBits % LENGTH != 0 || otherLengthInBits % LENGTH != 0) { throw new IllegalArgumentException( "The offsets and lengths must be at Character boundaries"); } - - + + final int beginIndex1 = offsetInBits / LENGTH; final int beginIndex2 = otherOffsetInBits / LENGTH; - + final int endIndex1 = beginIndex1 + lengthInBits / LENGTH; final int endIndex2 = beginIndex2 + otherLengthInBits / LENGTH; - + final int length = Math.max(endIndex1, endIndex2); - + // Look at each character, and if they're different // then figure out which bit makes the difference // and return it. @@ -91,38 +91,38 @@ public class StringKeyAnalyzer extends AbstractKeyAnalyzer { for(int i = 0; i < length; i++) { final int index1 = beginIndex1 + i; final int index2 = beginIndex2 + i; - + if (index1 >= endIndex1) { k = 0; } else { k = key.charAt(index1); } - + if (other == null || index2 >= endIndex2) { f = 0; } else { f = other.charAt(index2); } - + if (k != f) { final int x = k ^ f; return i * LENGTH + Integer.numberOfLeadingZeros(x) - LENGTH; } - + if (k != 0) { allNull = false; } } - + // All bits are 0 if (allNull) { return KeyAnalyzer.NULL_BIT_KEY; } - + // Both keys are equal return KeyAnalyzer.EQUAL_BIT_KEY; } - + /** * {@inheritDoc} */ @@ -130,23 +130,23 @@ public class StringKeyAnalyzer extends AbstractKeyAnalyzer { if (key == null || bitIndex >= lengthInBits) { return false; } - + final int index = bitIndex / LENGTH; final int bit = bitIndex % LENGTH; - + return (key.charAt(index) & mask(bit)) != 0; } - + /** * {@inheritDoc} */ - public boolean isPrefix(final String prefix, final int offsetInBits, + public boolean isPrefix(final String prefix, final int offsetInBits, final int lengthInBits, final String key) { if (offsetInBits % LENGTH != 0 || lengthInBits % LENGTH != 0) { throw new IllegalArgumentException( "Cannot determine prefix outside of Character boundaries"); } - + final String s1 = prefix.substring(offsetInBits / LENGTH, lengthInBits / LENGTH); return key.startsWith(s1); } diff --git a/src/main/java/org/apache/commons/collections4/trie/SynchronizedTrie.java b/src/main/java/org/apache/commons/collections4/trie/SynchronizedTrie.java index 7394f768c..8fdd259d1 100644 --- a/src/main/java/org/apache/commons/collections4/trie/SynchronizedTrie.java +++ b/src/main/java/org/apache/commons/collections4/trie/SynchronizedTrie.java @@ -29,19 +29,19 @@ import org.apache.commons.collections4.collection.SynchronizedCollection; /** * A synchronized {@link Trie}. - * + * * @since 4.0 * @version $Id$ */ public class SynchronizedTrie implements Trie, Serializable { - + private static final long serialVersionUID = 3121878833178676939L; - + private final Trie delegate; - + /** * Factory method to create a synchronized trie. - * + * * @param the key type * @param the value type * @param trie the trie to decorate, must not be null @@ -55,7 +55,7 @@ public class SynchronizedTrie implements Trie, Serializable { //----------------------------------------------------------------------- /** * Constructor that wraps (not copies). - * + * * @param trie the trie to decorate, must not be null * @throws IllegalArgumentException if set is null */ @@ -85,7 +85,7 @@ public class SynchronizedTrie implements Trie, Serializable { public synchronized Entry traverse(final Cursor cursor) { return delegate.traverse(cursor); } - + public synchronized Set> entrySet() { return Collections.synchronizedSet(delegate.entrySet()); } @@ -129,7 +129,7 @@ public class SynchronizedTrie implements Trie, Serializable { public synchronized V remove(final Object key) { return delegate.remove(key); } - + public synchronized K lastKey() { return delegate.lastKey(); } @@ -141,7 +141,7 @@ public class SynchronizedTrie implements Trie, Serializable { public synchronized SortedMap tailMap(final K fromKey) { return Collections.synchronizedSortedMap(delegate.tailMap(fromKey)); } - + public synchronized Comparator comparator() { return delegate.comparator(); } @@ -153,7 +153,7 @@ public class SynchronizedTrie implements Trie, Serializable { public synchronized SortedMap headMap(final K toKey) { return Collections.synchronizedSortedMap(delegate.headMap(toKey)); } - + public synchronized SortedMap getPrefixedBy(final K key, final int offset, final int length) { return Collections.synchronizedSortedMap(delegate.getPrefixedBy(key, offset, length)); } @@ -170,7 +170,7 @@ public class SynchronizedTrie implements Trie, Serializable { return Collections.synchronizedSortedMap(delegate.getPrefixedByBits(key, lengthInBits)); } - public synchronized SortedMap getPrefixedByBits(final K key, + public synchronized SortedMap getPrefixedByBits(final K key, final int offsetInBits, final int lengthInBits) { return Collections.synchronizedSortedMap(delegate.getPrefixedByBits(key, offsetInBits, lengthInBits)); } @@ -183,12 +183,12 @@ public class SynchronizedTrie implements Trie, Serializable { public synchronized int hashCode() { return delegate.hashCode(); } - + @Override public synchronized boolean equals(final Object obj) { return delegate.equals(obj); } - + @Override public synchronized String toString() { return delegate.toString(); diff --git a/src/main/java/org/apache/commons/collections4/trie/UnmodifiableTrie.java b/src/main/java/org/apache/commons/collections4/trie/UnmodifiableTrie.java index 992e35e5e..f5c0ba94c 100644 --- a/src/main/java/org/apache/commons/collections4/trie/UnmodifiableTrie.java +++ b/src/main/java/org/apache/commons/collections4/trie/UnmodifiableTrie.java @@ -29,19 +29,19 @@ import org.apache.commons.collections4.Unmodifiable; /** * An unmodifiable {@link Trie}. - * + * * @since 4.0 * @version $Id$ */ public class UnmodifiableTrie implements Trie, Serializable, Unmodifiable { - + private static final long serialVersionUID = -7156426030315945159L; - + private final Trie delegate; - + /** * Factory method to create a unmodifiable trie. - * + * * @param the key type * @param the value type * @param trie the trie to decorate, must not be null @@ -55,7 +55,7 @@ public class UnmodifiableTrie implements Trie, Serializable, Unmodif //----------------------------------------------------------------------- /** * Constructor that wraps (not copies). - * + * * @param trie the trie to decorate, must not be null * @throws IllegalArgumentException if trie is null */ @@ -65,7 +65,7 @@ public class UnmodifiableTrie implements Trie, Serializable, Unmodif } this.delegate = trie; } - + public Entry select(final K key, final Cursor cursor) { final Cursor c = new Cursor() { public Decision select(final Map.Entry entry) { @@ -78,11 +78,11 @@ public class UnmodifiableTrie implements Trie, Serializable, Unmodif // other decisions are fine break; } - + return decision; } }; - + return delegate.select(key, c); } @@ -110,18 +110,18 @@ public class UnmodifiableTrie implements Trie, Serializable, Unmodif // other decisions are fine break; } - + return decision; } }; - + return delegate.traverse(c); } public Set> entrySet() { return Collections.unmodifiableSet(delegate.entrySet()); } - + public Set keySet() { return Collections.unmodifiableSet(delegate.keySet()); } @@ -182,7 +182,7 @@ public class UnmodifiableTrie implements Trie, Serializable, Unmodif public SortedMap tailMap(final K fromKey) { return Collections.unmodifiableSortedMap(delegate.tailMap(fromKey)); } - + public SortedMap getPrefixedBy(final K key, final int offset, final int length) { return Collections.unmodifiableSortedMap( delegate.getPrefixedBy(key, offset, length)); @@ -202,7 +202,7 @@ public class UnmodifiableTrie implements Trie, Serializable, Unmodif return Collections.unmodifiableSortedMap( delegate.getPrefixedByBits(key, lengthInBits)); } - + public SortedMap getPrefixedByBits(final K key, final int offsetInBits, final int lengthInBits) { return Collections.unmodifiableSortedMap(delegate.getPrefixedByBits(key, offsetInBits, lengthInBits)); } @@ -210,21 +210,21 @@ public class UnmodifiableTrie implements Trie, Serializable, Unmodif public Comparator comparator() { return delegate.comparator(); } - + public int size() { return delegate.size(); } - + @Override public int hashCode() { return delegate.hashCode(); } - + @Override public boolean equals(final Object obj) { return delegate.equals(obj); } - + @Override public String toString() { return delegate.toString();