|
|
@@ -8,11 +8,13 @@ package net.ranides.assira.collection.lookups;
|
|
|
|
|
|
import java.util.Comparator;
|
|
|
import java.util.Iterator;
|
|
|
+import java.util.ListIterator;
|
|
|
import java.util.Map;
|
|
|
import java.util.SortedMap;
|
|
|
import net.ranides.assira.collection.sets.ASortedSet;
|
|
|
import net.ranides.assira.collection.IntCollection;
|
|
|
import net.ranides.assira.collection.iterators.IntIterator;
|
|
|
+import net.ranides.assira.collection.iterators.IntListIterator;
|
|
|
|
|
|
/**
|
|
|
* An abstract class for sorted maps with primitive int values.
|
|
|
@@ -20,13 +22,52 @@ import net.ranides.assira.collection.iterators.IntIterator;
|
|
|
public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K, Integer> {
|
|
|
|
|
|
private static final long serialVersionUID = 2L;
|
|
|
+
|
|
|
+ // @todo (assira # 1) acmp
|
|
|
+ protected Comparator<? super K> acmp;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The value of this variable remembers, after a
|
|
|
+ * <code>put()</code> or a
|
|
|
+ * <code>remove()</code>, whether the <em>domain</em> of the map has been
|
|
|
+ * modified.
|
|
|
+ */
|
|
|
+ protected transient boolean modified;
|
|
|
|
|
|
protected SortedLookup() {
|
|
|
// do nothing
|
|
|
}
|
|
|
+
|
|
|
+ protected SortedLookup(Comparator<? super K> comparator) {
|
|
|
+ this.acmp = comparator;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final Integer put(K key, Integer value) {
|
|
|
+ int oldValue = put(key, value.intValue());
|
|
|
+ return modified ? null : oldValue;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final Integer remove(Object key) {
|
|
|
+ int oldValue = removeInt(key);
|
|
|
+ return modified ? oldValue : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final boolean containsValue(int value) {
|
|
|
+ ValueIterator iterator = new ValueIterator(fastEntryIterator());
|
|
|
+ int max = size();
|
|
|
+ while (max-- != 0) {
|
|
|
+ if (iterator.nextInt() == value) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
@Override
|
|
|
- public ASortedSet<K> keySet() {
|
|
|
+ public final ASortedSet<K> keySet() {
|
|
|
return new KeySet();
|
|
|
}
|
|
|
|
|
|
@@ -35,13 +76,13 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
|
|
|
* @return a type-specific collection view of the values contained in this map
|
|
|
*/
|
|
|
@Override
|
|
|
- public IntCollection values() {
|
|
|
+ public final IntCollection values() {
|
|
|
return new ValuesCollection();
|
|
|
}
|
|
|
|
|
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
|
@Override
|
|
|
- public ASortedSet<Entry<K, Integer>> entrySet() {
|
|
|
+ public final ASortedSet<Entry<K, Integer>> entrySet() {
|
|
|
return (ASortedSet)fastEntrySet();
|
|
|
}
|
|
|
|
|
|
@@ -55,8 +96,55 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
|
|
|
* @see #entrySet()
|
|
|
*/
|
|
|
@Override
|
|
|
- public abstract ASortedSet<LookupEntry<K>> fastEntrySet();
|
|
|
+ public final ASortedSet<LookupEntry<K>> fastEntrySet() {
|
|
|
+ return new EntrySet();
|
|
|
+ }
|
|
|
+
|
|
|
+ // @todo (assira # 1) move to parent
|
|
|
+ protected abstract ListIterator<LookupEntry<K>> fastEntryIterator();
|
|
|
+
|
|
|
+ protected abstract ListIterator<LookupEntry<K>> fastEntryIterator(K begin);
|
|
|
+
|
|
|
+ protected abstract boolean inside(K key);
|
|
|
+
|
|
|
+ protected abstract LookupEntry<K> findEntry(K key);
|
|
|
+
|
|
|
+ protected abstract LookupEntry<K> firstEntry();
|
|
|
+
|
|
|
+ protected abstract LookupEntry<K> lastEntry();
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final K firstKey() {
|
|
|
+ return firstEntry().getKey();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public final K lastKey() {
|
|
|
+ return lastEntry().getKey();
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ @Override
|
|
|
+ public final boolean containsKey(Object k) {
|
|
|
+ return findEntry( (K)k) != null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ @Override
|
|
|
+ public final int getInt(Object k) {
|
|
|
+ LookupEntry<K> e = findEntry((K) k);
|
|
|
+ return e == null ? defRetValue : e.getIntValue();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ @Override
|
|
|
+ public final Integer get(Object ok) {
|
|
|
+ LookupEntry<K> e = findEntry((K) ok);
|
|
|
+ return e == null ? (null) : e.getValue();
|
|
|
+ }
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* Returns the comparator associated with this sorted set, or null if it
|
|
|
* uses its keys' natural ordering.
|
|
|
@@ -67,7 +155,9 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
|
|
|
* @see SortedMap#comparator()
|
|
|
*/
|
|
|
@Override
|
|
|
- public abstract Comparator<? super K> comparator();
|
|
|
+ public final Comparator<? super K> comparator() {
|
|
|
+ return acmp;
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* Returns a view of the portion of this sorted map whose keys range from
|
|
|
@@ -107,7 +197,7 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
|
|
|
@Override
|
|
|
public abstract SortedLookup<K> tailMap(K begin);
|
|
|
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* A wrapper exhibiting the keys of a map.
|
|
|
*/
|
|
|
@@ -161,12 +251,12 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
|
|
|
|
|
|
@Override
|
|
|
public Iterator<K> iterator(K from) {
|
|
|
- return new KeySetIterator<>(entrySet().iterator(new BasicEntry<>(from, 0)));
|
|
|
+ return new KeySetIterator<>(fastEntryIterator(from));
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public Iterator<K> iterator() {
|
|
|
- return new KeySetIterator<>(entrySet().iterator());
|
|
|
+ return new KeySetIterator<>(fastEntryIterator());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -178,9 +268,9 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
|
|
|
*/
|
|
|
protected static class KeySetIterator<K> implements Iterator<K> {
|
|
|
|
|
|
- private final Iterator<Map.Entry<K, Integer>> riv;
|
|
|
+ private final Iterator<LookupEntry<K>> riv;
|
|
|
|
|
|
- public KeySetIterator(Iterator<Map.Entry<K, Integer>> riv) {
|
|
|
+ public KeySetIterator(Iterator<LookupEntry<K>> riv) {
|
|
|
this.riv = riv;
|
|
|
}
|
|
|
|
|
|
@@ -200,7 +290,6 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* A wrapper exhibiting the values of a map.
|
|
|
*/
|
|
|
@@ -208,7 +297,7 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
|
|
|
|
|
|
@Override
|
|
|
public IntIterator iterator() {
|
|
|
- return new ValueIterator<>(entrySet().iterator());
|
|
|
+ return new ValueIterator<>(fastEntryIterator());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -233,24 +322,131 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
|
|
|
* <P>To provide an iterator on values, just create an instance of this
|
|
|
* class using the corresponding iterator on entries.
|
|
|
*/
|
|
|
- protected static class ValueIterator<K> extends IntIterator {
|
|
|
+ protected static class ValueIterator<K> extends IntListIterator {
|
|
|
|
|
|
- private final Iterator<Map.Entry<K, Integer>> riv;
|
|
|
+ private final ListIterator<LookupEntry<K>> delegate;
|
|
|
|
|
|
- public ValueIterator(Iterator<Map.Entry<K, Integer>> riv) {
|
|
|
- this.riv = riv;
|
|
|
+ public ValueIterator(ListIterator<LookupEntry<K>> riv) {
|
|
|
+ this.delegate = riv;
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
+ @Override
|
|
|
public int nextInt() {
|
|
|
- return riv.next().getValue();
|
|
|
+ return delegate.next().getIntValue();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int previousInt() {
|
|
|
+ return delegate.previous().getIntValue();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public boolean hasNext() {
|
|
|
- return riv.hasNext();
|
|
|
+ return delegate.hasNext();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean hasPrevious() {
|
|
|
+ return delegate.hasPrevious();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int nextIndex() {
|
|
|
+ return delegate.nextIndex();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int previousIndex() {
|
|
|
+ return delegate.previousIndex();
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
+ protected class EntrySet extends ASortedSet<LookupEntry<K>> {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Iterator<LookupEntry<K>> iterator() {
|
|
|
+ return fastEntryIterator();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Iterator<LookupEntry<K>> iterator(LookupEntry<K> from) {
|
|
|
+ return fastEntryIterator(from.getKey());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Comparator<? super LookupEntry<K>> comparator() {
|
|
|
+ return SortedLookup.this.entrySet().comparator();
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ @Override
|
|
|
+ public boolean contains(Object object) {
|
|
|
+ if (!(object instanceof Map.Entry)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ Map.Entry<K, Integer> entry = (Map.Entry<K, Integer>) object;
|
|
|
+ LookupEntry<K> found = findEntry(entry.getKey());
|
|
|
+ return found != null && inside(entry.getKey()) && entry.equals(found);
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ @Override
|
|
|
+ public boolean remove(Object o) {
|
|
|
+ if (!(o instanceof Map.Entry)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ Map.Entry<K, Integer> entry = (Map.Entry<K, Integer>) o;
|
|
|
+ LookupEntry<K> found = findEntry((entry.getKey()));
|
|
|
+ if (found != null && inside(found.getKey())) {
|
|
|
+ SortedLookup.this.removeInt(found.getIntValue());
|
|
|
+ }
|
|
|
+ return found != null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ int c = 0;
|
|
|
+ for (Iterator<?> i = iterator(); i.hasNext(); i.next()) {
|
|
|
+ c++;
|
|
|
+ }
|
|
|
+ return c;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean isEmpty() {
|
|
|
+ return !fastEntryIterator().hasNext();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void clear() {
|
|
|
+ SortedLookup.this.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public LookupEntry<K> first() {
|
|
|
+ return SortedLookup.this.firstEntry();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public LookupEntry<K> last() {
|
|
|
+ return SortedLookup.this.lastEntry();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ASortedSet<LookupEntry<K>> subSet(LookupEntry<K> from, LookupEntry<K> to) {
|
|
|
+ return subMap(from.getKey(), to.getKey()).fastEntrySet();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ASortedSet<LookupEntry<K>> headSet(LookupEntry<K> to) {
|
|
|
+ return headMap(to.getKey()).fastEntrySet();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ASortedSet<LookupEntry<K>> tailSet(LookupEntry<K> from) {
|
|
|
+ return tailMap(from.getKey()).fastEntrySet();
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
}
|