Parcourir la source

SortedLookup - review (partial)

Ranides Atterwim il y a 11 ans
Parent
commit
0e2c9524fb

Fichier diff supprimé car celui-ci est trop grand
+ 103 - 809
assira/src/main/java/net/ranides/assira/collection/lookups/AVLTreeLookup.java


+ 26 - 26
assira/src/main/java/net/ranides/assira/collection/lookups/RBTreeLookup.java

@@ -86,7 +86,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
     /**
      * This map's comparator, as provided in the constructor.
      */
-    protected Comparator<? super K> scmp;
+    protected Comparator<? super K> acmp;
 
     {
         allocatePaths();
@@ -107,7 +107,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
      */
     public RBTreeLookup(Comparator<? super K> comparator) {
         this();
-        scmp = comparator;
+        acmp = comparator;
     }
 
     /**
@@ -204,7 +204,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
     Entry<K> findKey(K key) {
         Entry<K> entry = tree;
         int cmp;
-        while (entry != null && (cmp = ValueUtils.cmp(scmp, key, entry.key)) != 0) {
+        while (entry != null && (cmp = ValueUtils.cmp(acmp, key, entry.key)) != 0) {
             entry = cmp < 0 ? entry.left() : entry.right();
         }
         return entry;
@@ -221,7 +221,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
     Entry<K> locateKey(K key) {
         Entry<K> current = tree, last = tree;
         int cmp = 0;
-        while (current != null && (cmp = ValueUtils.cmp(scmp, key, current.key)) != 0) {
+        while (current != null && (cmp = ValueUtils.cmp(acmp, key, current.key)) != 0) {
             last = current;
             current = cmp < 0 ? current.left() : current.right();
         }
@@ -253,7 +253,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
             Entry<K> current = tree, next;
             int cmp, i = 0;
             while (true) {
-                if ((cmp = ValueUtils.cmp(scmp, key, current.key)) == 0) {
+                if ((cmp = ValueUtils.cmp(acmp, key, current.key)) == 0) {
                     final int oldValue = current.value;
                     current.value = value;
                     // We clean up the node path, or we could have stale references later.
@@ -403,7 +403,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
         int i = 0;
         final K kkey = (K) key;
         while (true) {
-            if ((cmp = ValueUtils.cmp(scmp, kkey, current.key)) == 0) {
+            if ((cmp = ValueUtils.cmp(acmp, kkey, current.key)) == 0) {
                 break;
             }
             dirPath[ i] = cmp > 0;
@@ -1078,7 +1078,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
 
         TreeIterator(K k) {
             if ((next = locateKey(k)) != null) {
-                if (ValueUtils.cmp(scmp, next.key, k) <= 0) {
+                if (ValueUtils.cmp(acmp, next.key, k) <= 0) {
                     prev = next;
                     next = next.next();
                 } else {
@@ -1211,7 +1211,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
                 final Comparator<? super LookupEntry<K>> comparator = new Comparator<LookupEntry<K>>() {
                     @Override
                     public int compare(LookupEntry<K> entry1, LookupEntry<K> entry2) {
-                        return ValueUtils.cmp(scmp, entry1.getKey(), entry2.getKey());
+                        return ValueUtils.cmp(acmp, entry1.getKey(), entry2.getKey());
                     }
                 };
 
@@ -1488,7 +1488,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
 
     @Override
     public Comparator<? super K> comparator() {
-        return scmp;
+        return acmp;
     }
 
     @Override
@@ -1562,7 +1562,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
          * to &infin;.
          */
         public Submap(K from, boolean bottom, K to, boolean top) {
-            if (!bottom && !top && ValueUtils.cmp(scmp, from, to) > 0) {
+            if (!bottom && !top && ValueUtils.cmp(acmp, from, to) > 0) {
                 throw new IllegalArgumentException("Start key (" + from + ") is larger than end key (" + to + ")");
             }
             this.from = from;
@@ -1588,8 +1588,8 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
          * @return true if is the key is in the submap range.
          */
         boolean in(K key) {
-            return (bottom || ValueUtils.cmp(scmp, key, from) >= 0)
-                    && (top || ValueUtils.cmp(scmp, key, to) < 0);
+            return (bottom || ValueUtils.cmp(acmp, key, from) >= 0)
+                    && (top || ValueUtils.cmp(acmp, key, to) < 0);
         }
 
         @Override
@@ -1819,7 +1819,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
 
         @Override
         public Comparator<? super K> comparator() {
-            return scmp;
+            return acmp;
         }
 
         @Override
@@ -1827,7 +1827,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
             if (top) {
                 return new Submap(from, bottom, to, false);
             }
-            return ValueUtils.cmp(scmp, to, this.to) < 0 ? new Submap(from, bottom, to, false) : this;
+            return ValueUtils.cmp(acmp, to, this.to) < 0 ? new Submap(from, bottom, to, false) : this;
         }
 
         @Override
@@ -1835,7 +1835,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
             if (bottom) {
                 return new Submap(from, false, to, top);
             }
-            return ValueUtils.cmp(scmp, from, this.from) > 0 ? new Submap(from, false, to, top) : this;
+            return ValueUtils.cmp(acmp, from, this.from) > 0 ? new Submap(from, false, to, top) : this;
         }
 
         @Override
@@ -1844,10 +1844,10 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
                 return new Submap(from, false, to, false);
             }
             if (!top) {
-                to = ValueUtils.cmp(scmp, to, this.to) < 0 ? to : this.to;
+                to = ValueUtils.cmp(acmp, to, this.to) < 0 ? to : this.to;
             }
             if (!bottom) {
-                from = ValueUtils.cmp(scmp, from, this.from) > 0 ? from : this.from;
+                from = ValueUtils.cmp(acmp, from, this.from) > 0 ? from : this.from;
             }
             if (!top && !bottom && from == this.from && to == this.to) {
                 return this;
@@ -1872,12 +1872,12 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
             } else {
                 e = locateKey(from);
                 // If we find either the start or something greater we're OK.
-                if (ValueUtils.cmp(scmp, e.key, from) < 0) {
+                if (ValueUtils.cmp(acmp, e.key, from) < 0) {
                     e = e.next();
                 }
             }
             // Finally, if this submap doesn't go to infinity, we check that the resulting key isn't greater than the end.
-            if (e == null || !top && ValueUtils.cmp(scmp, e.key, to) >= 0) {
+            if (e == null || !top && ValueUtils.cmp(acmp, e.key, to) >= 0) {
                 return null;
             }
             return e;
@@ -1900,12 +1900,12 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
             } else {
                 e = locateKey(to);
                 // If we find something smaller than the end we're OK.
-                if (ValueUtils.cmp(scmp, e.key, to) >= 0) {
+                if (ValueUtils.cmp(acmp, e.key, to) >= 0) {
                     e = e.prev();
                 }
             }
             // Finally, if this submap doesn't go to -infinity, we check that the resulting key isn't smaller than the start.
-            if (e == null || !bottom && ValueUtils.cmp(scmp, e.key, from) < 0) {
+            if (e == null || !bottom && ValueUtils.cmp(acmp, e.key, from) < 0) {
                 return null;
             }
             return e;
@@ -1949,13 +1949,13 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
             SubmapIterator(K k) {
                 this();
                 if (next != null) {
-                    if (!bottom && ValueUtils.cmp(scmp, k, next.key) < 0) {
+                    if (!bottom && ValueUtils.cmp(acmp, k, next.key) < 0) {
                         prev = null;
-                    } else if (!top && ValueUtils.cmp(scmp, k, (prev = lastEntry()).key) >= 0) {
+                    } else if (!top && ValueUtils.cmp(acmp, k, (prev = lastEntry()).key) >= 0) {
                         next = null;
                     } else {
                         next = locateKey(k);
-                        if (ValueUtils.cmp(scmp, next.key, k) <= 0) {
+                        if (ValueUtils.cmp(acmp, next.key, k) <= 0) {
                             prev = next;
                             next = next.next();
                         } else {
@@ -1968,7 +1968,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
             @Override
             void updatePrevious() {
                 prev = prev.prev();
-                if (!bottom && prev != null && ValueUtils.cmp(scmp, prev.key, from) < 0) {
+                if (!bottom && prev != null && ValueUtils.cmp(acmp, prev.key, from) < 0) {
                     prev = null;
                 }
             }
@@ -1976,7 +1976,7 @@ public final class RBTreeLookup<K> extends SortedLookup<K> implements java.io.Se
             @Override
             void updateNext() {
                 next = next.next();
-                if (!top && next != null && ValueUtils.cmp(scmp, next.key, to) >= 0) {
+                if (!top && next != null && ValueUtils.cmp(acmp, next.key, to) >= 0) {
                     next = null;
                 }
             }

+ 215 - 19
assira/src/main/java/net/ranides/assira/collection/lookups/SortedLookup.java

@@ -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();
+		}
+	}
 
 }