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:
parent
edd64cfd82
commit
467d516b9c
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 & value
|
||||
* Replaces the current key and value with the provided key & 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;
|
||||
|
|
|
@ -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} < {@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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
|
@ -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();
|
|
@ -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");
|
|
@ -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();
|
|
@ -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();
|
|
@ -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();
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
Loading…
Reference in New Issue