Cleanup of trie package.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1491615 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas Neidhart 2013-06-10 21:46:19 +00:00
parent edd64cfd82
commit 467d516b9c
16 changed files with 300 additions and 782 deletions

View File

@ -1,72 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
/**
* TODO: add javadoc
*
* @since 4.0
* @version $Id$
*/
public abstract class AbstractKeyAnalyzer<K> implements KeyAnalyzer<K> {
private static final long serialVersionUID = -20497563720380683L;
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public int compare(final K o1, final K o2) {
if (o1 == null) {
return o2 == null ? 0 : -1;
} else if (o2 == null) {
return 1;
}
return ((Comparable<K>)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}
*/
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
* {@link Integer#MAX_VALUE}
*/
static boolean isValidBitIndex(final int bitIndex) {
return bitIndex >= 0;
}
}

View File

@ -60,9 +60,6 @@ abstract class AbstractTrie<K, V> extends AbstractMap<K, V>
return keyAnalyzer;
}
/**
* {@inheritDoc}
*/
public K selectKey(final K key) {
final Map.Entry<K, V> entry = select(key);
if (entry == null) {
@ -71,9 +68,6 @@ abstract class AbstractTrie<K, V> extends AbstractMap<K, V>
return entry.getKey();
}
/**
* {@inheritDoc}
*/
public V selectValue(final K key) {
final Map.Entry<K, V> entry = select(key);
if (entry == null) {
@ -94,12 +88,11 @@ abstract class AbstractTrie<K, V> extends AbstractMap<K, V>
}
/**
* A utility method to cast keys. It actually doesn't
* cast anything. It's just fooling the compiler!
* A utility method to cast keys. It actually doesn't cast anything. It's just fooling the compiler!
*/
@SuppressWarnings("unchecked")
final K castKey(final Object key) {
return (K)key;
return (K) key;
}
/**
@ -125,8 +118,7 @@ abstract class AbstractTrie<K, V> extends AbstractMap<K, V>
}
/**
* Returns whether or not the given bit on the
* key is set or false if the key is null.
* 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)
*/
@ -138,11 +130,10 @@ abstract class AbstractTrie<K, V> extends AbstractMap<K, V>
}
/**
* Utility method for calling {@link KeyAnalyzer#bitIndex(Object, int, int, Object, int, int)}
* 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),
foundKey, 0, lengthInBits(foundKey));
return keyAnalyzer.bitIndex(key, 0, lengthInBits(key), foundKey, 0, lengthInBits(foundKey));
}
/**
@ -159,14 +150,14 @@ abstract class AbstractTrie<K, V> extends AbstractMap<K, V>
}
/**
* Returns true if both values are either null or equal
* 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}
* A basic implementation of {@link Entry}.
*/
abstract static class BasicEntry<K, V> implements Map.Entry<K, V>, Serializable {
@ -186,37 +177,25 @@ abstract class AbstractTrie<K, V> extends AbstractMap<K, V>
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);
this.hashCode = (key != null ? key.hashCode() : 0) ^ (value != null ? value.hashCode() : 0);
}
/**
* Replaces the current key and value with the provided
* key &amp; value
* Replaces the current key and value with the provided key &amp; value.
*/
public V setKeyValue(final K key, final V value) {
this.key = key;
return setValue(value);
}
/**
* {@inheritDoc}
*/
public K getKey() {
return key;
}
/**
* {@inheritDoc}
*/
public V getValue() {
return value;
}
/**
* {@inheritDoc}
*/
public V setValue(final V value) {
final V previous = this.value;
this.value = value;

View File

@ -32,7 +32,10 @@ import java.util.Comparator;
* @since 4.0
* @version $Id$
*/
public interface KeyAnalyzer<K> extends Comparator<K>, Serializable {
public abstract class KeyAnalyzer<K> implements Comparator<K>, Serializable {
/** Serialization version */
private static final long serialVersionUID = -20497563720380683L;
/**
* Returned by {@link #bitIndex(Object, int, int, Object, int, int)}
@ -49,13 +52,43 @@ public interface KeyAnalyzer<K> extends Comparator<K>, Serializable {
public static final int OUT_OF_BOUNDS_BIT_KEY = -3;
/**
* 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}
*/
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
* {@link Integer#MAX_VALUE}
*/
static boolean isValidBitIndex(final int bitIndex) {
return bitIndex >= 0;
}
/**
* 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();
public abstract int bitsPerElement();
/**
* Returns the length of the Key in bits.
@ -63,23 +96,55 @@ public interface KeyAnalyzer<K> extends Comparator<K>, Serializable {
* @param key the key
* @return the bit length of the key
*/
public int lengthInBits(K key);
public abstract int lengthInBits(K key);
/**
* Returns whether or not a bit is set.
*
* @param key the key to check, may not be null
* @param bitIndex the bit index to check
* @param lengthInBits the maximum key length in bits to check
* @return {@code true} if the bit is set in the given key and
* {@code bitIndex} &lt; {@code lengthInBits}, {@code false} otherwise.
*/
public boolean isBitSet(K key, int bitIndex, int lengthInBits);
public abstract 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
* at 'foundStart' and going for 'foundLength' bits.
* Returns the n-th different bit between key and other. This starts the comparison in
* key at 'offsetInBits' and goes for 'lengthInBits' bits, and compares to the other key starting
* at 'otherOffsetInBits' and going for 'otherLengthInBits' bits.
*
* @param key the key to use
* @param offsetInBits the bit offset in the key
* @param lengthInBits the maximum key length in bits to use
* @param other the other key to use
* @param otherOffsetInBits the bit offset in the other key
* @param otherLengthInBits the maximum key length in bits for the other key
* @return the bit index where the key and other first differ
*/
public int bitIndex(K key, int offsetInBits, int lengthInBits,
K other, int otherOffsetInBits, int otherLengthInBits);
public abstract 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.
*
* @param prefix the prefix to check
* @param offsetInBits the bit offset in the key
* @param lengthInBits the maximum key length in bits to use
* @param key the key to check
* @return {@code true} if this is a valid prefix for the given key
*/
public boolean isPrefix(K prefix, int offsetInBits, int lengthInBits, K key);
public abstract boolean isPrefix(K prefix, int offsetInBits, int lengthInBits, K key);
@SuppressWarnings("unchecked")
public int compare(final K o1, final K o2) {
if (o1 == null) {
return o2 == null ? 0 : -1;
} else if (o2 == null) {
return 1;
}
return ((Comparable<K>) o1).compareTo(o2);
}
}

View File

@ -77,57 +77,35 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
super(keyAnalyzer);
}
public PatriciaTrie(final KeyAnalyzer<? super K> keyAnalyzer,
final Map<? extends K, ? extends V> m) {
public PatriciaTrie(final KeyAnalyzer<? super K> keyAnalyzer, final Map<? extends K, ? extends V> m) {
super(keyAnalyzer, m);
}
/**
* {@inheritDoc}
*/
public Comparator<? super K> comparator() {
return keyAnalyzer;
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> getPrefixedBy(final K key) {
return getPrefixedByBits(key, 0, lengthInBits(key));
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> getPrefixedBy(final K key, final int length) {
return getPrefixedByBits(key, 0, length * bitsPerElement());
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> getPrefixedBy(final K key, final int offset, final int length) {
final int bitsPerElement = bitsPerElement();
return getPrefixedByBits(key, offset*bitsPerElement, length*bitsPerElement);
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> getPrefixedByBits(final K key, final int lengthInBits) {
return getPrefixedByBits(key, 0, lengthInBits);
}
/**
* {@inheritDoc}
*/
public K firstKey() {
return firstEntry().getKey();
}
/**
* {@inheritDoc}
*/
public K lastKey() {
final TrieEntry<K, V> entry = lastEntry();
if (entry != null) {
@ -165,23 +143,14 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return new PrefixRangeMap(key, offsetInBits, lengthInBits);
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> headMap(final K toKey) {
return new RangeEntryMap(null, toKey);
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
return new RangeEntryMap(fromKey, toKey);
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> tailMap(final K fromKey) {
return new RangeEntryMap(fromKey, null);
}
@ -216,7 +185,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
final int bitIndex = bitIndex(key, found.key);
if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) {
if (KeyAnalyzer.isValidBitIndex(bitIndex)) {
final TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
addEntry(added, lengthInBits);
incrementSize(); // must increment because remove will decrement
@ -224,7 +193,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
removeEntry(added);
modCount -= 2; // we didn't really modify it.
return ceil;
} else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) {
} else if (KeyAnalyzer.isNullBitKey(bitIndex)) {
if (!root.isEmpty()) {
return firstEntry();
} else if (size() > 1) {
@ -232,7 +201,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
} else {
return null;
}
} else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) {
} else if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
return nextEntry(found);
}
@ -279,7 +248,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
final int bitIndex = bitIndex(key, found.key);
if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) {
if (KeyAnalyzer.isValidBitIndex(bitIndex)) {
final TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
addEntry(added, lengthInBits);
incrementSize(); // must increment because remove will decrement
@ -287,13 +256,13 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
removeEntry(added);
modCount -= 2; // we didn't really modify it.
return ceil;
} else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) {
} else if (KeyAnalyzer.isNullBitKey(bitIndex)) {
if (!root.isEmpty()) {
return root;
} else {
return firstEntry();
}
} else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) {
} else if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
return found;
}
@ -335,7 +304,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
final int bitIndex = bitIndex(key, found.key);
if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) {
if (KeyAnalyzer.isValidBitIndex(bitIndex)) {
final TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
addEntry(added, lengthInBits);
incrementSize(); // must increment because remove will decrement
@ -343,9 +312,9 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
removeEntry(added);
modCount -= 2; // we didn't really modify it.
return prior;
} else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) {
} else if (KeyAnalyzer.isNullBitKey(bitIndex)) {
return null;
} else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) {
} else if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
return previousEntry(found);
}
@ -377,7 +346,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
final int bitIndex = bitIndex(key, found.key);
if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) {
if (KeyAnalyzer.isValidBitIndex(bitIndex)) {
final TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
addEntry(added, lengthInBits);
incrementSize(); // must increment because remove will decrement
@ -385,13 +354,13 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
removeEntry(added);
modCount -= 2; // we didn't really modify it.
return floor;
} else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) {
} else if (KeyAnalyzer.isNullBitKey(bitIndex)) {
if (!root.isEmpty()) {
return root;
} else {
return null;
}
} else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) {
} else if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
return found;
}
@ -409,14 +378,12 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
TrieEntry<K, V> current = root.left;
TrieEntry<K, V> path = root;
while(true) {
if (current.bitIndex <= path.bitIndex
|| lengthInBits < current.bitIndex) {
if (current.bitIndex <= path.bitIndex || lengthInBits < current.bitIndex) {
break;
}
path = current;
if (!isBitSet(prefix, offsetInBits + current.bitIndex,
offsetInBits + lengthInBits)) {
if (!isBitSet(prefix, offsetInBits + current.bitIndex, offsetInBits + lengthInBits)) {
current = current.left;
} else {
current = current.right;
@ -503,7 +470,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
* - If node.parent.left is not uplink from node.parent:
* - Follow right path for first right child from node.parent.left
*
* @param start
* @param start the start entry
*/
TrieEntry<K, V> previousEntry(final TrieEntry<K, V> start) {
if (start.predecessor == null) {
@ -560,52 +527,43 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
/**
* A range view of the {@link Trie}
* A range view of the {@link Trie}.
*/
private abstract class RangeMap extends AbstractMap<K, V>
implements SortedMap<K, V> {
/**
* The {@link #entrySet()} view
*/
/** The {@link #entrySet()} view. */
private transient volatile Set<Map.Entry<K, V>> entrySet;
/**
* Creates and returns an {@link #entrySet()}
* view of the {@link RangeMap}
* Creates and returns an {@link #entrySet()} view of the {@link RangeMap}.
*/
protected abstract Set<Map.Entry<K, V>> createEntrySet();
/**
* Returns the FROM Key
* Returns the FROM Key.
*/
protected abstract K getFromKey();
/**
* Whether or not the {@link #getFromKey()} is in the range
* Whether or not the {@link #getFromKey()} is in the range.
*/
protected abstract boolean isFromInclusive();
/**
* Returns the TO Key
* Returns the TO Key.
*/
protected abstract K getToKey();
/**
* Whether or not the {@link #getToKey()} is in the range
* Whether or not the {@link #getToKey()} is in the range.
*/
protected abstract boolean isToInclusive();
/**
* {@inheritDoc}
*/
public Comparator<? super K> comparator() {
return PatriciaTrie.this.comparator();
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsKey(final Object key) {
if (!inRange(castKey(key))) {
@ -615,9 +573,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return PatriciaTrie.this.containsKey(key);
}
/**
* {@inheritDoc}
*/
@Override
public V remove(final Object key) {
if (!inRange(castKey(key))) {
@ -627,9 +582,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return PatriciaTrie.this.remove(key);
}
/**
* {@inheritDoc}
*/
@Override
public V get(final Object key) {
if (!inRange(castKey(key))) {
@ -639,22 +591,14 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return PatriciaTrie.this.get(key);
}
/**
* {@inheritDoc}
*/
@Override
public V put(final K key, final V value) {
if (!inRange(key)) {
throw new IllegalArgumentException(
"Key is out of range: " + key);
throw new IllegalArgumentException("Key is out of range: " + key);
}
return PatriciaTrie.this.put(key, value);
}
/**
* {@inheritDoc}
*/
@Override
public Set<Map.Entry<K, V>> entrySet() {
if (entrySet == null) {
@ -663,81 +607,56 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return entrySet;
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
if (!inRange2(fromKey)) {
throw new IllegalArgumentException(
"FromKey is out of range: " + fromKey);
throw new IllegalArgumentException("FromKey is out of range: " + fromKey);
}
if (!inRange2(toKey)) {
throw new IllegalArgumentException(
"ToKey is out of range: " + toKey);
throw new IllegalArgumentException("ToKey is out of range: " + toKey);
}
return createRangeMap(fromKey, isFromInclusive(),
toKey, isToInclusive());
return createRangeMap(fromKey, isFromInclusive(), toKey, isToInclusive());
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> headMap(final K toKey) {
if (!inRange2(toKey)) {
throw new IllegalArgumentException(
"ToKey is out of range: " + toKey);
throw new IllegalArgumentException("ToKey is out of range: " + toKey);
}
return createRangeMap(getFromKey(), isFromInclusive(),
toKey, isToInclusive());
return createRangeMap(getFromKey(), isFromInclusive(), toKey, isToInclusive());
}
/**
* {@inheritDoc}
*/
public SortedMap<K, V> tailMap(final K fromKey) {
if (!inRange2(fromKey)) {
throw new IllegalArgumentException(
"FromKey is out of range: " + fromKey);
throw new IllegalArgumentException("FromKey is out of range: " + fromKey);
}
return createRangeMap(fromKey, isFromInclusive(),
getToKey(), isToInclusive());
return createRangeMap(fromKey, isFromInclusive(), getToKey(), isToInclusive());
}
/**
* Returns true if the provided key is greater than TO and
* less than FROM
* Returns true if the provided key is greater than TO and less than FROM.
*/
protected boolean inRange(final K key) {
final K fromKey = getFromKey();
final K toKey = getToKey();
return (fromKey == null || inFromRange(key, false))
&& (toKey == null || inToRange(key, false));
return (fromKey == null || inFromRange(key, false)) && (toKey == null || inToRange(key, false));
}
/**
* This form allows the high endpoint (as well as all legit keys)
* This form allows the high endpoint (as well as all legit keys).
*/
protected boolean inRange2(final K key) {
final K fromKey = getFromKey();
final K toKey = getToKey();
return (fromKey == null || inFromRange(key, false))
&& (toKey == null || inToRange(key, true));
return (fromKey == null || inFromRange(key, false)) && (toKey == null || inToRange(key, true));
}
/**
* Returns true if the provided key is in the FROM range
* of the {@link RangeMap}
* Returns true if the provided key is in the FROM range of the {@link RangeMap}.
*/
protected boolean inFromRange(final K key, final boolean forceInclusive) {
final K fromKey = getFromKey();
final boolean fromInclusive = isFromInclusive();
@ -750,11 +669,9 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
/**
* Returns true if the provided key is in the TO range
* of the {@link RangeMap}
* Returns true if the provided key is in the TO range of the {@link RangeMap}.
*/
protected boolean inToRange(final K key, final boolean forceInclusive) {
final K toKey = getToKey();
final boolean toInclusive = isToInclusive();
@ -767,50 +684,42 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
/**
* Creates and returns a sub-range view of the current {@link RangeMap}
* Creates and returns a sub-range view of the current {@link RangeMap}.
*/
protected abstract SortedMap<K, V> createRangeMap(K fromKey,
boolean fromInclusive, K toKey, boolean toInclusive);
protected abstract SortedMap<K, V> createRangeMap(K fromKey, boolean fromInclusive,
K toKey, boolean toInclusive);
}
/**
* A {@link RangeMap} that deals with {@link Entry}s
* 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
* the toKey excluded from the range.
*/
protected RangeEntryMap(final K fromKey, final K toKey) {
this(fromKey, true, toKey, false);
}
/**
* Creates a {@link RangeEntryMap}
* Creates a {@link RangeEntryMap}.
*/
protected RangeEntryMap(final K fromKey, final boolean fromInclusive,
final K toKey, final boolean toInclusive) {
final K toKey, final boolean toInclusive) {
if (fromKey == null && toKey == null) {
throw new IllegalArgumentException("must have a from or to!");
@ -827,9 +736,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
this.toInclusive = toInclusive;
}
/**
* {@inheritDoc}
*/
public K firstKey() {
Map.Entry<K,V> e = null;
if (fromKey == null) {
@ -849,9 +755,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return first;
}
/**
* {@inheritDoc}
*/
public K lastKey() {
Map.Entry<K,V> e;
if (toKey == null) {
@ -871,49 +774,31 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return last;
}
/**
* {@inheritDoc}
*/
@Override
protected Set<Entry<K, V>> createEntrySet() {
return new RangeEntrySet(this);
}
/**
* {@inheritDoc}
*/
@Override
public K getFromKey() {
return fromKey;
}
/**
* {@inheritDoc}
*/
@Override
public K getToKey() {
return toKey;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isFromInclusive() {
return fromInclusive;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isToInclusive() {
return toInclusive;
}
/**
* {@inheritDoc}
*/
@Override
protected SortedMap<K, V> createRangeMap(final K fromKey, final boolean fromInclusive,
final K toKey, final boolean toInclusive) {
@ -922,7 +807,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
/**
* A {@link Set} view of a {@link RangeMap}
* A {@link Set} view of a {@link RangeMap}.
*/
private class RangeEntrySet extends AbstractSet<Map.Entry<K, V>> {
@ -933,7 +818,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
private transient int expectedModCount;
/**
* Creates a {@link RangeEntrySet}
* Creates a {@link RangeEntrySet}.
*/
public RangeEntrySet(final RangeMap delegate) {
if (delegate == null) {
@ -943,9 +828,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
this.delegate = delegate;
}
/**
* {@inheritDoc}
*/
@Override
public Iterator<Map.Entry<K, V>> iterator() {
final K fromKey = delegate.getFromKey();
@ -966,9 +848,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return new EntryIterator(first, last);
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
if (size == -1 || expectedModCount != PatriciaTrie.this.modCount) {
@ -983,17 +862,11 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return size;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEmpty() {
return !iterator().hasNext();
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean contains(final Object o) {
@ -1011,9 +884,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return node != null && compare(node.getValue(), entry.getValue());
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public boolean remove(final Object o) {
@ -1043,32 +913,22 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
private final K excludedKey;
/**
* Creates a {@link EntryIterator}
* Creates a {@link EntryIterator}.
*/
private EntryIterator(
final TrieEntry<K,V> first,
final TrieEntry<K,V> last) {
private EntryIterator(final TrieEntry<K,V> first, final TrieEntry<K,V> last) {
super(first);
this.excludedKey = last != null ? last.getKey() : null;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNext() {
return next != null && !compare(next.key, excludedKey);
}
/**
* {@inheritDoc}
*/
public Map.Entry<K,V> next() {
if (next == null || compare(next.key, excludedKey)) {
throw new NoSuchElementException();
}
return nextEntry();
}
}
@ -1094,7 +954,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
private int size = -1;
/**
* Creates a {@link PrefixRangeMap}
* Creates a {@link PrefixRangeMap}.
*/
private PrefixRangeMap(final K prefix, final int offsetInBits, final int lengthInBits) {
this.prefix = prefix;
@ -1147,9 +1007,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return size;
}
/**
* {@inheritDoc}
*/
public K firstKey() {
fixup();
@ -1169,9 +1026,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return first;
}
/**
* {@inheritDoc}
*/
public K lastKey() {
fixup();
@ -1192,8 +1046,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
/**
* Returns true if this {@link PrefixRangeMap}'s key is a prefix
* of the provided key.
* Returns true if this {@link PrefixRangeMap}'s key is a prefix of the provided key.
*/
@Override
protected boolean inRange(final K key) {
@ -1201,7 +1054,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
/**
* Same as {@link #inRange(Object)}
* Same as {@link #inRange(Object)}.
*/
@Override
protected boolean inRange2(final K key) {
@ -1209,8 +1062,7 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
/**
* Returns true if the provided Key is in the FROM range
* of the {@link PrefixRangeMap}
* Returns true if the provided Key is in the FROM range of the {@link PrefixRangeMap}.
*/
@Override
protected boolean inFromRange(final K key, final boolean forceInclusive) {
@ -1218,67 +1070,47 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
}
/**
* Returns true if the provided Key is in the TO range
* of the {@link PrefixRangeMap}
* Returns true if the provided Key is in the TO range of the {@link PrefixRangeMap}.
*/
@Override
protected boolean inToRange(final K key, final boolean forceInclusive) {
return keyAnalyzer.isPrefix(prefix, offsetInBits, lengthInBits, key);
}
/**
* {@inheritDoc}
*/
@Override
protected Set<Map.Entry<K, V>> createEntrySet() {
return new PrefixRangeEntrySet(this);
}
/**
* {@inheritDoc}
*/
@Override
public K getFromKey() {
return fromKey;
}
/**
* {@inheritDoc}
*/
@Override
public K getToKey() {
return toKey;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isFromInclusive() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isToInclusive() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
protected SortedMap<K, V> createRangeMap(
final K fromKey, final boolean fromInclusive,
final K toKey, final boolean toInclusive) {
protected SortedMap<K, V> createRangeMap(final K fromKey, final boolean fromInclusive,
final K toKey, final boolean toInclusive) {
return new RangeEntryMap(fromKey, fromInclusive, toKey, toInclusive);
}
}
/**
* A prefix {@link RangeEntrySet} view of the {@link Trie}
* A prefix {@link RangeEntrySet} view of the {@link Trie}.
*/
private final class PrefixRangeEntrySet extends RangeEntrySet {
@ -1289,24 +1121,18 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
private int expectedModCount = 0;
/**
* Creates a {@link PrefixRangeEntrySet}
* Creates a {@link PrefixRangeEntrySet}.
*/
public PrefixRangeEntrySet(final PrefixRangeMap delegate) {
super(delegate);
this.delegate = delegate;
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return delegate.fixup();
}
/**
* {@inheritDoc}
*/
@Override
public Iterator<Map.Entry<K,V>> iterator() {
if (PatriciaTrie.this.modCount != expectedModCount) {
@ -1337,16 +1163,10 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
this.entry = entry;
}
/**
* {@inheritDoc}
*/
public boolean hasNext() {
return hit == 0;
}
/**
* {@inheritDoc}
*/
public Map.Entry<K, V> next() {
if (hit != 0) {
throw new NoSuchElementException();
@ -1356,9 +1176,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return entry;
}
/**
* {@inheritDoc}
*/
public void remove() {
if (hit != 1) {
throw new IllegalStateException();
@ -1395,9 +1212,6 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
this.lengthInBits = lengthInBits;
}
/**
* {@inheritDoc}
*/
public Map.Entry<K,V> next() {
final Map.Entry<K, V> entry = nextEntry();
if (lastOne) {
@ -1406,17 +1220,11 @@ public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K
return entry;
}
/**
* {@inheritDoc}
*/
@Override
protected TrieEntry<K, V> findNext(final TrieEntry<K, V> prior) {
return PatriciaTrie.this.nextEntryInSubtree(prior, subtree);
}
/**
* {@inheritDoc}
*/
@Override
public void remove() {
// If the current entry we're removing is the subtree

View File

@ -52,41 +52,29 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
private transient volatile Collection<V> values;
private transient volatile Set<Map.Entry<K,V>> entrySet;
/**
* The current size of the {@link Trie}
*/
/** 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.
* It's used to detect concurrent modifications and fail-fast the {@link Iterator}s.
*/
transient int modCount = 0;
protected transient int modCount = 0;
public PatriciaTrieBase(final KeyAnalyzer<? super K> 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
* provided {@link Map}.
* 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<? super K> keyAnalyzer,
final Map<? extends K, ? extends V> m) {
public PatriciaTrieBase(final KeyAnalyzer<? super K> keyAnalyzer, final Map<? extends K, ? extends V> m) {
super(keyAnalyzer);
if (m == null) {
throw new NullPointerException("m");
}
putAll(m);
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
root.key = null;
@ -102,17 +90,13 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
incrementModCount();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return size;
}
/**
* A helper method to increment the {@link Trie} size
* and the modification counter.
* A helper method to increment the {@link Trie} size and the modification counter.
*/
void incrementSize() {
size++;
@ -120,8 +104,7 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
/**
* A helper method to decrement the {@link Trie} size
* and increment the modification counter.
* A helper method to decrement the {@link Trie} size and increment the modification counter.
*/
void decrementSize() {
size--;
@ -135,9 +118,6 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
++modCount;
}
/**
* {@inheritDoc}
*/
@Override
public V put(final K key, final V value) {
if (key == null) {
@ -168,14 +148,14 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
final int bitIndex = bitIndex(key, found.key);
if (!AbstractKeyAnalyzer.isOutOfBoundsIndex(bitIndex)) {
if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) { // in 99.999...9% the case
if (!KeyAnalyzer.isOutOfBoundsIndex(bitIndex)) {
if (KeyAnalyzer.isValidBitIndex(bitIndex)) { // in 99.999...9% the case
/* NEW KEY+VALUE TUPLE */
final TrieEntry<K, V> t = new TrieEntry<K, V>(key, value, bitIndex);
addEntry(t, lengthInBits);
incrementSize();
return null;
} else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) {
} else if (KeyAnalyzer.isNullBitKey(bitIndex)) {
// A bits of the Key are zero. The only place to
// store such a Key is the root Node!
@ -187,7 +167,7 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
return root.setKeyValue(key, value);
} else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) {
} else if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
// This is a very special and rare case.
/* REPLACE OLD KEY+VALUE */
@ -198,11 +178,11 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
}
throw new IndexOutOfBoundsException("Failed to put: " + key + " -> " + value + ", " + bitIndex);
throw new IllegalArgumentException("Failed to put: " + key + " -> " + value + ", " + bitIndex);
}
/**
* Adds the given {@link TrieEntry} to the {@link Trie}
* Adds the given {@link TrieEntry} to the {@link Trie}.
*/
TrieEntry<K, V> addEntry(final TrieEntry<K, V> entry, final int lengthInBits) {
TrieEntry<K, V> current = root.left;
@ -249,9 +229,6 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
}
/**
* {@inheritDoc}
*/
@Override
public V get(final Object k) {
final TrieEntry<K, V> entry = getEntry(k);
@ -262,7 +239,7 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
* Returns the entry associated with the specified key in the
* PatriciaTrieBase. Returns null if the map contains no mapping
* for this key.
*
* <p>
* This may throw ClassCastException if the object is not of type K.
*/
TrieEntry<K,V> getEntry(final Object k) {
@ -276,39 +253,29 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return !entry.isEmpty() && compareKeys(key, entry.key) ? entry : null;
}
/**
* {@inheritDoc}
*/
public Map.Entry<K, V> select(final K key) {
final int lengthInBits = lengthInBits(key);
final Reference<Map.Entry<K, V>> reference
= new Reference<Map.Entry<K,V>>();
final Reference<Map.Entry<K, V>> reference = new Reference<Map.Entry<K,V>>();
if (!selectR(root.left, -1, key, lengthInBits, reference)) {
return reference.get();
}
return null;
}
/**
* {@inheritDoc}
*/
public Map.Entry<K,V> select(final K key, final Cursor<? super K, ? super V> cursor) {
final int lengthInBits = lengthInBits(key);
final Reference<Map.Entry<K, V>> reference
= new Reference<Map.Entry<K,V>>();
final Reference<Map.Entry<K, V>> reference = new Reference<Map.Entry<K,V>>();
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
* {@link Trie}.
* 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<K, V> h, final int bitIndex,
final K key, final int lengthInBits,
final Reference<Map.Entry<K, V>> reference) {
final K key, final int lengthInBits,
final Reference<Map.Entry<K, V>> reference) {
if (h.bitIndex <= bitIndex) {
// If we hit the root Node and it is empty
@ -333,9 +300,6 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return false;
}
/**
*
*/
private boolean selectR(final TrieEntry<K,V> h, final int bitIndex,
final K key,
final int lengthInBits,
@ -379,9 +343,6 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return false;
}
/**
* {@inheritDoc}
*/
public Map.Entry<K, V> traverse(final Cursor<? super K, ? super V> cursor) {
TrieEntry<K, V> entry = nextEntry(null);
while (entry != null) {
@ -410,9 +371,6 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsKey(final Object k) {
if (k == null) {
@ -425,9 +383,6 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return !entry.isEmpty() && compareKeys(key, entry.key);
}
/**
* {@inheritDoc}
*/
@Override
public Set<Map.Entry<K,V>> entrySet() {
if (entrySet == null) {
@ -436,9 +391,6 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return entrySet;
}
/**
* {@inheritDoc}
*/
@Override
public Set<K> keySet() {
if (keySet == null) {
@ -447,9 +399,6 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return keySet;
}
/**
* {@inheritDoc}
*/
@Override
public Collection<V> values() {
if (values == null) {
@ -787,7 +736,7 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
/**
* Returns the first entry the {@link Trie} is storing.
*
* <p>
* This is implemented by going always to the left until
* we encounter a valid uplink. That uplink is the first key.
*/
@ -847,7 +796,7 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
/**
* A {@link Trie} is a set of {@link TrieEntry} nodes
* A {@link Trie} is a set of {@link TrieEntry} nodes.
*/
static class TrieEntry<K,V> extends BasicEntry<K, V> {
@ -889,22 +838,19 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
/**
* 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();
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
final StringBuilder buffer = new StringBuilder();
@ -968,22 +914,15 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
/**
* This is a entry set view of the {@link Trie} as returned
* by {@link Map#entrySet()}
* This is a entry set view of the {@link Trie} as returned by {@link Map#entrySet()}.
*/
private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
/**
* {@inheritDoc}
*/
@Override
public Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(final Object o) {
if (!(o instanceof Map.Entry)) {
@ -994,9 +933,6 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return candidate != null && candidate.equals(o);
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(final Object o) {
final int size = size();
@ -1004,24 +940,18 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return size != size();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return PatriciaTrieBase.this.size();
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
PatriciaTrieBase.this.clear();
}
/**
* An {@link Iterator} that returns {@link Entry} Objects
* An {@link Iterator} that returns {@link Entry} Objects.
*/
private class EntryIterator extends TrieIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() {
@ -1031,38 +961,25 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
/**
* This is a key set view of the {@link Trie} as returned
* by {@link Map#keySet()}
* This is a key set view of the {@link Trie} as returned by {@link Map#keySet()}.
*/
private class KeySet extends AbstractSet<K> {
/**
* {@inheritDoc}
*/
@Override
public Iterator<K> iterator() {
return new KeyIterator();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return PatriciaTrieBase.this.size();
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(final Object o) {
return containsKey(o);
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(final Object o) {
final int size = size();
@ -1070,16 +987,13 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return size != size();
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
PatriciaTrieBase.this.clear();
}
/**
* An {@link Iterator} that returns Key Objects
* An {@link Iterator} that returns Key Objects.
*/
private class KeyIterator extends TrieIterator<K> {
public K next() {
@ -1089,46 +1003,30 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
/**
* This is a value view of the {@link Trie} as returned
* by {@link Map#values()}
* This is a value view of the {@link Trie} as returned by {@link Map#values()}.
*/
private class Values extends AbstractCollection<V> {
/**
* {@inheritDoc}
*/
@Override
public Iterator<V> iterator() {
return new ValueIterator();
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return PatriciaTrieBase.this.size();
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(final Object o) {
return containsValue(o);
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
PatriciaTrieBase.this.clear();
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(final Object o) {
for (final Iterator<V> it = iterator(); it.hasNext(); ) {
@ -1142,7 +1040,7 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
}
/**
* An {@link Iterator} that returns Value Objects
* An {@link Iterator} that returns Value Objects.
*/
private class ValueIterator extends TrieIterator<V> {
public V next() {
@ -1156,30 +1054,28 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
*/
abstract class TrieIterator<E> implements Iterator<E> {
/**
* For fast-fail
*/
/** For fast-fail. */
protected int expectedModCount = PatriciaTrieBase.this.modCount;
protected TrieEntry<K, V> next; // the next node to return
protected TrieEntry<K, V> current; // the current entry we're on
/**
* Starts iteration from the root
* Starts iteration from the root.
*/
protected TrieIterator() {
next = PatriciaTrieBase.this.nextEntry(null);
}
/**
* Starts iteration at the given entry
* Starts iteration at the given entry.
*/
protected TrieIterator(final TrieEntry<K, V> firstEntry) {
next = firstEntry;
}
/**
* Returns the next {@link TrieEntry}
* Returns the next {@link TrieEntry}.
*/
protected TrieEntry<K,V> nextEntry() {
if (expectedModCount != PatriciaTrieBase.this.modCount) {
@ -1203,16 +1099,10 @@ abstract class PatriciaTrieBase<K, V> extends AbstractTrie<K, V> {
return PatriciaTrieBase.this.nextEntry(prior);
}
/**
* {@inheritDoc}
*/
public boolean hasNext() {
return next != null;
}
/**
* {@inheritDoc}
*/
public void remove() {
if (current == null) {
throw new IllegalStateException();

View File

@ -14,7 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
package org.apache.commons.collections4.trie.analyzer;
import org.apache.commons.collections4.trie.KeyAnalyzer;
/**
* A {@link KeyAnalyzer} for byte[]s.
@ -22,34 +24,23 @@ package org.apache.commons.collections4.trie;
* @since 4.0
* @version $Id$
*/
public class ByteArrayKeyAnalyzer extends AbstractKeyAnalyzer<byte[]> {
public class ByteArrayKeyAnalyzer extends KeyAnalyzer<byte[]> {
private static final long serialVersionUID = 7382825097492285877L;
/**
* A singleton instance of {@link ByteArrayKeyAnalyzer}
*/
public static final ByteArrayKeyAnalyzer INSTANCE
= new ByteArrayKeyAnalyzer(Integer.MAX_VALUE);
/** A singleton instance of {@link ByteArrayKeyAnalyzer}. */
public static final ByteArrayKeyAnalyzer INSTANCE = new ByteArrayKeyAnalyzer(Integer.MAX_VALUE);
/**
* The length of an {@link Byte} in bits
*/
/** 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
*/
/** 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
*/
/** A place holder for null. */
private static final byte[] NULL = new byte[0];
/**
* The maximum length of a key in bits
*/
/** The maximum length of a key in bits. */
private final int maxLengthInBits;
public ByteArrayKeyAnalyzer(final int maxLengthInBits) {
@ -76,23 +67,14 @@ public class ByteArrayKeyAnalyzer extends AbstractKeyAnalyzer<byte[]> {
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) {
return false;
@ -110,11 +92,8 @@ public class ByteArrayKeyAnalyzer extends AbstractKeyAnalyzer<byte[]> {
return (key[index] & mask(bit)) != 0;
}
/**
* {@inheritDoc}
*/
public int bitIndex(final byte[] key, final int offsetInBits, final int lengthInBits,
byte[] other, final int otherOffsetInBits, final int otherLengthInBits) {
byte[] other, final int otherOffsetInBits, final int otherLengthInBits) {
if (other == null) {
other = NULL;
@ -151,11 +130,7 @@ public class ByteArrayKeyAnalyzer extends AbstractKeyAnalyzer<byte[]> {
return KeyAnalyzer.EQUAL_BIT_KEY;
}
/**
* {@inheritDoc}
*/
public boolean isPrefix(final byte[] prefix, final int offsetInBits,
final int lengthInBits, final byte[] key) {
public boolean isPrefix(final byte[] prefix, final int offsetInBits, final int lengthInBits, final byte[] key) {
final int keyLength = lengthInBits(key);
if (lengthInBits > keyLength) {
@ -173,9 +148,6 @@ public class ByteArrayKeyAnalyzer extends AbstractKeyAnalyzer<byte[]> {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public int compare(final byte[] o1, final byte[] o2) {
if (o1 == null) {

View File

@ -14,7 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
package org.apache.commons.collections4.trie.analyzer;
import org.apache.commons.collections4.trie.KeyAnalyzer;
/**
* A {@link KeyAnalyzer} for {@link Byte}s.
@ -22,58 +24,38 @@ package org.apache.commons.collections4.trie;
* @since 4.0
* @version $Id$
*/
public class ByteKeyAnalyzer extends AbstractKeyAnalyzer<Byte> {
public class ByteKeyAnalyzer extends KeyAnalyzer<Byte> {
private static final long serialVersionUID = 3395803342983289829L;
/**
* A singleton instance of {@link ByteKeyAnalyzer}
*/
/** A singleton instance of {@link ByteKeyAnalyzer}. */
public static final ByteKeyAnalyzer INSTANCE = new ByteKeyAnalyzer();
/**
* The length of an {@link Byte} in bits
*/
/** 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
*/
/** 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
*/
/** 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 1;
}
/**
* {@inheritDoc}
*/
public int lengthInBits(final Byte key) {
return LENGTH;
}
/**
* {@inheritDoc}
*/
public boolean isBitSet(final Byte key, final int bitIndex, final int lengthInBits) {
return (key.intValue() & mask(bitIndex)) != 0;
}
/**
* {@inheritDoc}
*/
public int bitIndex(final Byte key, final int offsetInBits, final int lengthInBits,
final Byte other, final int otherOffsetInBits, final int otherLengthInBits) {
final Byte other, final int otherOffsetInBits, final int otherLengthInBits) {
if (offsetInBits != 0 || otherOffsetInBits != 0) {
throw new IllegalArgumentException("offsetInBits=" + offsetInBits
@ -99,11 +81,7 @@ public class ByteKeyAnalyzer extends AbstractKeyAnalyzer<Byte> {
return KeyAnalyzer.EQUAL_BIT_KEY;
}
/**
* {@inheritDoc}
*/
public boolean isPrefix(final Byte prefix, final int offsetInBits,
final int lengthInBits, final Byte key) {
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();

View File

@ -14,7 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
package org.apache.commons.collections4.trie.analyzer;
import org.apache.commons.collections4.trie.KeyAnalyzer;
/**
* An {@link KeyAnalyzer} for {@code char[]}s.
@ -22,51 +24,34 @@ package org.apache.commons.collections4.trie;
* @since 4.0
* @version $Id$
*/
public class CharArrayKeyAnalyzer extends AbstractKeyAnalyzer<char[]> {
public class CharArrayKeyAnalyzer extends KeyAnalyzer<char[]> {
private static final long serialVersionUID = -8167897361549463457L;
/**
* A singleton instance of {@link CharArrayKeyAnalyzer}
*/
/** A singleton instance of {@link CharArrayKeyAnalyzer}. */
public static final CharArrayKeyAnalyzer INSTANCE = new CharArrayKeyAnalyzer();
/**
* The number of bits per {@link Character}
*/
/** 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
*/
/** 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
*/
/** 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 char[] key) {
return key != null ? key.length * LENGTH : 0;
}
/**
* {@inheritDoc}
*/
public int bitIndex(final char[] key, final int offsetInBits, final int lengthInBits,
final char[] other, final int otherOffsetInBits, final int otherLengthInBits) {
final char[] other, final int otherOffsetInBits, final int otherLengthInBits) {
boolean allNull = true;
if (offsetInBits % LENGTH != 0 || otherOffsetInBits % LENGTH != 0
@ -123,9 +108,6 @@ public class CharArrayKeyAnalyzer extends AbstractKeyAnalyzer<char[]> {
return KeyAnalyzer.EQUAL_BIT_KEY;
}
/**
* {@inheritDoc}
*/
public boolean isBitSet(final char[] key, final int bitIndex, final int lengthInBits) {
if (key == null || bitIndex >= lengthInBits) {
return false;
@ -137,11 +119,7 @@ public class CharArrayKeyAnalyzer extends AbstractKeyAnalyzer<char[]> {
return (key[index] & mask(bit)) != 0;
}
/**
* {@inheritDoc}
*/
public boolean isPrefix(final char[] prefix, final int offsetInBits,
final int lengthInBits, final char[] key) {
public boolean isPrefix(final char[] prefix, final int offsetInBits, final int lengthInBits, final char[] key) {
if (offsetInBits % LENGTH != 0 || lengthInBits % LENGTH != 0) {
throw new IllegalArgumentException(
"Cannot determine prefix outside of Character boundaries");

View File

@ -14,7 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
package org.apache.commons.collections4.trie.analyzer;
import org.apache.commons.collections4.trie.KeyAnalyzer;
/**
* A {@link KeyAnalyzer} for {@link Character}s.
@ -22,60 +24,39 @@ package org.apache.commons.collections4.trie;
* @since 4.0
* @version $Id$
*/
public class CharacterKeyAnalyzer extends AbstractKeyAnalyzer<Character> {
public class CharacterKeyAnalyzer extends KeyAnalyzer<Character> {
private static final long serialVersionUID = 3928565962744720753L;
/**
* A singleton instance of the {@link CharacterKeyAnalyzer}.
*/
/** A singleton instance of the {@link CharacterKeyAnalyzer}. */
public static final CharacterKeyAnalyzer INSTANCE
= new CharacterKeyAnalyzer();
/**
* The length of a {@link Character} in bits
*/
/** The length of a {@link Character} in bits. */
public static final int LENGTH = Character.SIZE;
/**
* A bit mask where the first bit is 1 and the others are zero
*/
/** 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
*/
/** 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 1;
}
/**
* {@inheritDoc}
*/
public int lengthInBits(final Character key) {
return LENGTH;
}
/**
* {@inheritDoc}
* @throws NullPointerException if the key is null
*/
public boolean isBitSet(final Character key, final int bitIndex, final int lengthInBits) {
return (key.charValue() & mask(bitIndex)) != 0;
}
/**
* {@inheritDoc}
*/
public int bitIndex(final Character key, final int offsetInBits, final int lengthInBits,
final Character other, final int otherOffsetInBits, final int otherLengthInBits) {
final Character other, final int otherOffsetInBits, final int otherLengthInBits) {
if (offsetInBits != 0 || otherOffsetInBits != 0) {
throw new IllegalArgumentException("offsetInBits=" + offsetInBits
@ -101,11 +82,8 @@ public class CharacterKeyAnalyzer extends AbstractKeyAnalyzer<Character> {
return KeyAnalyzer.EQUAL_BIT_KEY;
}
/**
* {@inheritDoc}
*/
public boolean isPrefix(final Character prefix, final int offsetInBits,
final int lengthInBits, final Character key) {
final int lengthInBits, final Character key) {
final int value1 = prefix.charValue() << offsetInBits;
final int value2 = key.charValue();

View File

@ -14,7 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
package org.apache.commons.collections4.trie.analyzer;
import org.apache.commons.collections4.trie.KeyAnalyzer;
/**
* A {@link KeyAnalyzer} for {@link Integer}s.
@ -22,58 +24,38 @@ package org.apache.commons.collections4.trie;
* @since 4.0
* @version $Id$
*/
public class IntegerKeyAnalyzer extends AbstractKeyAnalyzer<Integer> {
public class IntegerKeyAnalyzer extends KeyAnalyzer<Integer> {
private static final long serialVersionUID = 4928508653722068982L;
/**
* A singleton instance of {@link IntegerKeyAnalyzer}
*/
/** A singleton instance of {@link IntegerKeyAnalyzer}. */
public static final IntegerKeyAnalyzer INSTANCE = new IntegerKeyAnalyzer();
/**
* The length of an {@link Integer} in bits
*/
/** 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
*/
/** 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
*/
/** 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 1;
}
/**
* {@inheritDoc}
*/
public int lengthInBits(final Integer key) {
return LENGTH;
}
/**
* {@inheritDoc}
*/
public boolean isBitSet(final Integer key, final int bitIndex, final int lengthInBits) {
return (key.intValue() & mask(bitIndex)) != 0;
}
/**
* {@inheritDoc}
*/
public int bitIndex(final Integer key, final int offsetInBits, final int lengthInBits,
final Integer other, final int otherOffsetInBits, final int otherLengthInBits) {
final Integer other, final int otherOffsetInBits, final int otherLengthInBits) {
if (offsetInBits != 0 || otherOffsetInBits != 0) {
throw new IllegalArgumentException("offsetInBits=" + offsetInBits
@ -99,11 +81,8 @@ public class IntegerKeyAnalyzer extends AbstractKeyAnalyzer<Integer> {
return KeyAnalyzer.EQUAL_BIT_KEY;
}
/**
* {@inheritDoc}
*/
public boolean isPrefix(final Integer prefix, final int offsetInBits,
final int lengthInBits, final Integer key) {
final int lengthInBits, final Integer key) {
final int value1 = prefix.intValue() << offsetInBits;
final int value2 = key.intValue();

View File

@ -14,7 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
package org.apache.commons.collections4.trie.analyzer;
import org.apache.commons.collections4.trie.KeyAnalyzer;
/**
* A {@link KeyAnalyzer} for {@link Long}s.
@ -22,58 +24,38 @@ package org.apache.commons.collections4.trie;
* @since 4.0
* @version $Id$
*/
public class LongKeyAnalyzer extends AbstractKeyAnalyzer<Long> {
public class LongKeyAnalyzer extends KeyAnalyzer<Long> {
private static final long serialVersionUID = -4119639247588227409L;
/**
* A singleton instance of {@link LongKeyAnalyzer}
*/
/** A singleton instance of {@link LongKeyAnalyzer}. */
public static final LongKeyAnalyzer INSTANCE = new LongKeyAnalyzer();
/**
* The length of an {@link Long} in bits
*/
/** 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
*/
/** 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
*/
/** Returns a bit mask where the given bit is set. */
private static long mask(final int bit) {
return MSB >>> bit;
}
/**
* {@inheritDoc}
*/
public int bitsPerElement() {
return 1;
}
/**
* {@inheritDoc}
*/
public int lengthInBits(final Long key) {
return LENGTH;
}
/**
* {@inheritDoc}
*/
public boolean isBitSet(final Long key, final int bitIndex, final int lengthInBits) {
return (key.longValue() & mask(bitIndex)) != 0;
}
/**
* {@inheritDoc}
*/
public int bitIndex(final Long key, final int offsetInBits, final int lengthInBits,
final Long other, final int otherOffsetInBits, final int otherLengthInBits) {
final Long other, final int otherOffsetInBits, final int otherLengthInBits) {
if (offsetInBits != 0 || otherOffsetInBits != 0) {
throw new IllegalArgumentException("offsetInBits=" + offsetInBits
@ -99,11 +81,8 @@ public class LongKeyAnalyzer extends AbstractKeyAnalyzer<Long> {
return KeyAnalyzer.EQUAL_BIT_KEY;
}
/**
* {@inheritDoc}
*/
public boolean isPrefix(final Long prefix, final int offsetInBits,
final int lengthInBits, final Long key) {
final int lengthInBits, final Long key) {
final long value1 = prefix.longValue() << offsetInBits;
final long value2 = key.longValue();

View File

@ -14,7 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
package org.apache.commons.collections4.trie.analyzer;
import org.apache.commons.collections4.trie.KeyAnalyzer;
/**
* A {@link KeyAnalyzer} for {@link Short}s.
@ -22,58 +24,38 @@ package org.apache.commons.collections4.trie;
* @since 4.0
* @version $Id$
*/
public class ShortKeyAnalyzer implements KeyAnalyzer<Short> {
public class ShortKeyAnalyzer extends KeyAnalyzer<Short> {
private static final long serialVersionUID = -8631376733513512017L;
/**
* A singleton instance of {@link ShortKeyAnalyzer}
*/
/** A singleton instance of {@link ShortKeyAnalyzer}. */
public static final ShortKeyAnalyzer INSTANCE = new ShortKeyAnalyzer();
/**
* The length of an {@link Short} in bits
*/
/** 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
*/
/** 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
*/
/** 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 1;
}
/**
* {@inheritDoc}
*/
public int lengthInBits(final Short key) {
return LENGTH;
}
/**
* {@inheritDoc}
*/
public boolean isBitSet(final Short key, final int bitIndex, final int lengthInBits) {
return (key.intValue() & mask(bitIndex)) != 0;
}
/**
* {@inheritDoc}
*/
public int bitIndex(final Short key, final int offsetInBits, final int lengthInBits,
final Short other, final int otherOffsetInBits, final int otherLengthInBits) {
final Short other, final int otherOffsetInBits, final int otherLengthInBits) {
if (offsetInBits != 0 || otherOffsetInBits != 0) {
throw new IllegalArgumentException("offsetInBits=" + offsetInBits
@ -99,18 +81,8 @@ public class ShortKeyAnalyzer implements KeyAnalyzer<Short> {
return KeyAnalyzer.EQUAL_BIT_KEY;
}
/**
* {@inheritDoc}
*/
public int compare(final Short o1, final Short o2) {
return o1.compareTo(o2);
}
/**
* {@inheritDoc}
*/
public boolean isPrefix(final Short prefix, final int offsetInBits,
final int lengthInBits, final Short key) {
final int lengthInBits, final Short key) {
final int value1 = prefix.shortValue() << offsetInBits;
final int value2 = key.shortValue();
@ -122,4 +94,10 @@ public class ShortKeyAnalyzer implements KeyAnalyzer<Short> {
return (value1 & mask) == (value2 & mask);
}
@Override
public int compare(final Short o1, final Short o2) {
return o1.compareTo(o2);
}
}

View File

@ -14,7 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
package org.apache.commons.collections4.trie.analyzer;
import org.apache.commons.collections4.trie.KeyAnalyzer;
/**
* An {@link KeyAnalyzer} for {@link String}s.
@ -22,60 +24,42 @@ package org.apache.commons.collections4.trie;
* @since 4.0
* @version $Id$
*/
public class StringKeyAnalyzer extends AbstractKeyAnalyzer<String> {
public class StringKeyAnalyzer extends KeyAnalyzer<String> {
private static final long serialVersionUID = -7032449491269434877L;
/**
* A singleton instance of {@link StringKeyAnalyzer}
*/
/** A singleton instance of {@link StringKeyAnalyzer}. */
public static final StringKeyAnalyzer INSTANCE = new StringKeyAnalyzer();
/**
* The number of bits per {@link Character}
*/
/** 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
*/
/** 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
*/
/** 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) {
final String other, final int otherOffsetInBits, final int otherLengthInBits) {
boolean allNull = true;
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");
throw new IllegalArgumentException("The offsets and lengths must be at Character boundaries");
}
final int beginIndex1 = offsetInBits / LENGTH;
final int beginIndex2 = otherOffsetInBits / LENGTH;
@ -123,9 +107,6 @@ public class StringKeyAnalyzer extends AbstractKeyAnalyzer<String> {
return KeyAnalyzer.EQUAL_BIT_KEY;
}
/**
* {@inheritDoc}
*/
public boolean isBitSet(final String key, final int bitIndex, final int lengthInBits) {
if (key == null || bitIndex >= lengthInBits) {
return false;
@ -137,11 +118,8 @@ public class StringKeyAnalyzer extends AbstractKeyAnalyzer<String> {
return (key.charAt(index) & mask(bit)) != 0;
}
/**
* {@inheritDoc}
*/
public boolean isPrefix(final String prefix, final int offsetInBits,
final int lengthInBits, final String key) {
final int lengthInBits, final String key) {
if (offsetInBits % LENGTH != 0 || lengthInBits % LENGTH != 0) {
throw new IllegalArgumentException(
"Cannot determine prefix outside of Character boundaries");

View File

@ -0,0 +1,22 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This package contains various {@link org.apache.commons.collections4.trie.KeyAnalyzer} implementations.
*
* @version $Id$
*/
package org.apache.commons.collections4.trie.analyzer;

View File

@ -34,6 +34,9 @@ import java.util.TreeMap;
import java.util.Map.Entry;
import org.apache.commons.collections4.Trie.Cursor;
import org.apache.commons.collections4.trie.analyzer.CharacterKeyAnalyzer;
import org.apache.commons.collections4.trie.analyzer.IntegerKeyAnalyzer;
import org.apache.commons.collections4.trie.analyzer.StringKeyAnalyzer;
import org.junit.Assert;
import org.junit.Test;
@ -1079,6 +1082,7 @@ public class PatriciaTrieTest {
}
}
@SuppressWarnings("unused")
void selectFor(final Object object) {
selectFor = object;
}

View File

@ -14,12 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.trie;
package org.apache.commons.collections4.trie.analyzer;
import java.math.BigInteger;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.collections4.trie.PatriciaTrie;
import org.apache.commons.collections4.trie.analyzer.ByteArrayKeyAnalyzer;
import org.junit.Assert;
import org.junit.Test;