Ranides Atterwim пре 10 година
родитељ
комит
7faf09e1be

+ 2 - 24
assira/src/main/java/net/ranides/assira/collection/arrays/ArrayUtils.java

@@ -155,21 +155,7 @@ public final class ArrayUtils {
         }
         return true;
     }
-    
-    public static <K> K[] head(K[] values, K value) {
-        return islice(values, 0, ifind(values, value, 0));
-    }
-    
-    public static <K> K[] tail(K[] values, K value) {
-        return islice(values, ifind(values, value, 0), values.length);
-    }
-    
-    public static <K> K[] slice(K[] values, K begin, K end) {
-        int bi = ifind(values, begin, 0);
-        int ei = ifind(values, end, bi);
-        return islice(values, bi, ei);
-    }
-    
+
     public static <K> K[] head(K[] values, K value, Comparator<K> cmp) {
         return islice(values, 0, ifind(values, value, 0, cmp));
     }
@@ -191,15 +177,7 @@ public final class ArrayUtils {
         }
         return i;
     }
-    
-    private static <K> int ifind(K[] values, K value, int begin) {
-        int i = begin;
-        while(i<values.length && !value.equals(values[i])) {
-            i++;
-        }
-        return i;
-    }
-    
+
     private static <K> K[] islice(K[] values, int begin, int end) {
         int size = end - begin;
         K[] result = ArrayAllocator.allocate(values, size);

+ 45 - 2
assira/src/main/java/net/ranides/assira/collection/lookups/Lookup.java

@@ -12,6 +12,8 @@ import java.util.Set;
 import net.ranides.assira.collection.sets.ASet;
 import net.ranides.assira.collection.IntCollection;
 import net.ranides.assira.collection.iterators.IntIterator;
+import net.ranides.assira.collection.maps.IntMap;
+import net.ranides.assira.collection.sets.ASortedSet;
 import net.ranides.assira.generic.HashUtils;
 import net.ranides.assira.generic.CompareUtils;
 
@@ -82,9 +84,9 @@ public abstract class Lookup<K> implements Map<K, Integer>, java.io.Serializable
     @SuppressWarnings({"unchecked", "rawtypes"})
     @Override
     public Set<Map.Entry<K, Integer>> entrySet() {
-        return (Set) fastEntrySet();
+        return new EntrySetAdapter<>(fastEntrySet());
     }
-
+    
     /**
      * Returns a hash code for this map.
      *
@@ -328,7 +330,48 @@ public abstract class Lookup<K> implements Map<K, Integer>, java.io.Serializable
             return key + "->" + value;
         }
     }
+    
+    private static final class EntrySetAdapter<K> extends ASet<Map.Entry<K, Integer>> {
+        
+        private final Set<LookupEntry<K>> that;
 
+        public EntrySetAdapter(Set<LookupEntry<K>> that) {
+            this.that = that;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Iterator<Entry<K, Integer>> iterator() {
+            return (Iterator)that.iterator();
+        }
+
+        @Override
+        public int size() {
+            return that.size();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return that.isEmpty();
+        }
+
+        @Override
+        public void clear() {
+            that.clear();
+        }
+
+        @Override
+        public boolean remove(Object value) {
+            return that.remove(value);
+        }
+
+        @Override
+        public boolean contains(Object value) {
+            return that.contains(value);
+        }
+    
+    }
+    
     protected class KeySet extends ASet<K> {
         @Override
         @SuppressWarnings("element-type-mismatch")

+ 112 - 1
assira/src/main/java/net/ranides/assira/collection/lookups/SortedLookup.java

@@ -88,7 +88,7 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
 	@SuppressWarnings({"unchecked", "rawtypes"})
     @Override
     public final ASortedSet<Entry<K, Integer>> entrySet() {
-        return (ASortedSet)fastEntrySet();
+        return new EntrySetAdapter<>(this);
     }
 
     /**
@@ -366,6 +366,117 @@ public abstract class SortedLookup<K> extends Lookup<K> implements SortedMap<K,
             delegate.remove();
         }
 		
+    }
+    
+    protected static class EntrySetAdapter<K> extends ASortedSet<Map.Entry<K, Integer>> {
+        
+        private final SortedLookup<K> that;
+
+        public EntrySetAdapter(SortedLookup<K> that) {
+            super((entry1, entry2) -> that.acmp.compare(entry1.getKey(), entry2.getKey()));
+            this.that = that;
+        }
+        
+        @SuppressWarnings("unchecked")
+        @Override
+		public ListIterator<Map.Entry<K, Integer>> iterator() {
+			return (ListIterator)that.entryIterator();
+		}
+
+        @SuppressWarnings("unchecked")
+		@Override
+		public ListIterator<Map.Entry<K, Integer>> iterator(Map.Entry<K, Integer> from) {
+			return (ListIterator)that.entryIterator(from.getKey());
+		}
+
+		@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 = that.findEntry(entry.getKey());
+			return entry.equals(found);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		public boolean remove(Object object) {
+			if (!(object instanceof Map.Entry)) {
+				return false;
+			}
+			Map.Entry<K, Integer> entry = (Map.Entry<K, Integer>) object;
+            if(null == entry.getValue()) {
+                return false;
+            }
+			LookupEntry<K> found = that.findEntry(entry.getKey());
+			if (found != null && found.getIntValue()==entry.getValue()) {
+				that.removeInt(found.getKey());
+                return true;
+			}
+			return false;
+		}
+
+		@Override
+		public int size() {
+			int c = 0;
+			for (Iterator<?> i = iterator(); i.hasNext(); i.next()) {
+				c++;
+			}
+			return c;
+		}
+
+		@Override
+		public boolean isEmpty() {
+			return !that.entryIterator().hasNext();
+		}
+
+		@Override
+		public void clear() {
+			that.clear();
+		}
+
+		@Override
+		public LookupEntry<K> first() {
+            LookupEntry<K> entry = that.firstEntry();
+            if(null == entry) {
+                throw new NoSuchElementException();
+            }
+			return entry;
+		}
+
+		@Override
+		public LookupEntry<K> last() {
+            LookupEntry<K> entry = that.lastEntry();
+            if(null == entry) {
+                throw new NoSuchElementException();
+            }
+			return entry;
+		}
+
+		@Override
+		public ASortedSet<Map.Entry<K,Integer>> subSet(Map.Entry<K,Integer> begin, Map.Entry<K,Integer> end) {
+            return subset(begin, false, end, false);
+		}
+
+		@Override
+		public ASortedSet<Map.Entry<K,Integer>> headSet(Map.Entry<K,Integer> end) {
+			return that.headMap(end.getKey()).entrySet();
+		}
+
+		@Override
+		public ASortedSet<Map.Entry<K,Integer>> tailSet(Map.Entry<K,Integer> begin) {
+			return that.tailMap(begin.getKey()).entrySet();
+		}
+		
+		@Override
+		protected ASortedSet<Map.Entry<K,Integer>> subset(Map.Entry<K,Integer> begin, boolean bottom, Map.Entry<K,Integer> end, boolean top) {
+			K begkey = (null == begin) ? null : begin.getKey();
+			K endkey = (null == end) ? null : end.getKey();
+			return that.submap(begkey, bottom, endkey, top).entrySet();
+		}
+        
     }
 
 	protected static class EntrySet<K> extends ASortedSet<LookupEntry<K>> {

+ 6 - 3
assira/src/main/java/net/ranides/assira/test/TGenerator.java

@@ -7,6 +7,7 @@
 package net.ranides.assira.test;
 
 import java.util.function.IntFunction;
+import net.ranides.assira.collection.HashComparator;
 
 /**
  *
@@ -14,14 +15,16 @@ import java.util.function.IntFunction;
  */
 public interface TGenerator<T> extends IntFunction<T> {
     
-    public T value(int index);
+    T value(int index);
     
-    public default int valueInt(int index) {
+    HashComparator<T> comparator();
+    
+    default int valueInt(int index) {
         return ((Number)value(index)).intValue();
     }
 
     @Override
-    public default T apply(int index) {
+    default T apply(int index) {
         return value(index);
     }
     

+ 88 - 3
assira/src/main/java/net/ranides/assira/test/TMap.java

@@ -14,7 +14,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Random;
+import net.ranides.assira.collection.HashComparator;
 import net.ranides.assira.collection.arrays.ArrayAllocator;
+import net.ranides.assira.generic.CompareUtils;
 
 /**
  *
@@ -22,6 +24,81 @@ import net.ranides.assira.collection.arrays.ArrayAllocator;
  */
 public abstract class TMap<K,V> {
     
+    private final HashComparator<K> kcmp = new HashComparator<K>() {
+        @Override
+        public int hashCode(K object) {
+            return hash(object);
+        }
+        @Override
+        public int compare(K a, K b) {
+            return cmp(a,b);
+        }
+    };
+    
+    private final HashComparator<Entry<K,V>> ecmp = new HashComparator<Entry<K,V>>() {
+        @Override
+        public int hashCode(Entry<K,V> entry) {
+            return entry.hashCode();
+        }
+        @Override
+        public int compare(Entry<K,V> a, Entry<K,V> b) {
+            return cmp(a.getKey(),b.getKey());
+        }
+    };
+    
+    private final HashComparator<V> vcmp = new HashComparator<V>() {
+        @Override
+        public int hashCode(V entry) {
+            return entry.hashCode();
+        }
+        @Override
+        public int compare(V a, V b) {
+            return CompareUtils.cmp(a, b);
+        }
+    };
+    
+    private final TGenerator<K> kgen = new TGenerator<K>() {
+
+        @Override
+        public K value(int index) {
+            return item(index).key();
+        }
+
+        @Override
+        public HashComparator<K> comparator() {
+            return kcmp;
+        }
+
+    };
+    
+    private final TGenerator<Entry<K,V>> egen = new TGenerator<Entry<K,V>>() {
+
+        @Override
+        public Entry<K,V> value(int index) {
+            return item(index).entry();
+        }
+
+        @Override
+        public HashComparator<Entry<K,V>> comparator() {
+            return ecmp;
+        }
+
+    };
+    
+    private final TGenerator<V> vgen = new TGenerator<V>() {
+
+        @Override
+        public V value(int index) {
+            return item(index).value();
+        }
+
+        @Override
+        public HashComparator<V> comparator() {
+            return vcmp;
+        }
+
+    };
+    
     public static final class TItem<K,V> {
         
         private final TMap<K,V> that;
@@ -181,6 +258,10 @@ public abstract class TMap<K,V> {
     
     protected abstract V value(int index, int n);
     
+    protected abstract int cmp(K a, K b);
+    
+    protected abstract int hash(K key);
+    
     protected K key(int index) {
         return key(index, 0);
     }
@@ -189,6 +270,10 @@ public abstract class TMap<K,V> {
         return value(index, 0);
     }
     
+    public HashComparator<K> comparator() {
+        return kcmp;
+    }
+    
     public TItem<K,V> item(int index) {
         return item(index, 0);
     }
@@ -232,15 +317,15 @@ public abstract class TMap<K,V> {
     }
     
     public TGenerator<K> keys() {
-        return (int index) -> item(index).key();
+        return kgen;
     }
     
     public TGenerator<V> values() {
-        return (int index) -> item(index).value();
+        return vgen;
     }
     
     public TGenerator<Entry<K,V>> entries() {
-        return (int index) -> item(index).entry();
+        return egen;
     }
 
 }

+ 13 - 0
assira/src/test/java/net/ranides/assira/collection/mockup/TPoint.java

@@ -107,6 +107,19 @@ public class TPoint implements Serializable {
             return 10 * index + n;
         }
 
+        @Override
+        protected int cmp(TPoint a, TPoint b) {
+            int dx = a.x - b.x;
+            int dy = a.y - b.y;
+            int dz = a.z - a.z;
+            return dx!=0 ? dx : (dy!=0 ? dy : dz);
+        }
+
+        @Override
+        protected int hash(TPoint key) {
+            return HashUtils.hashValues(1, 1199, key.x, key.y, key.z);
+        }
+
     };
     
 }

+ 5 - 4
assira/src/test/java/net/ranides/assira/collection/suite/SetTester.java

@@ -6,6 +6,7 @@
  */
 package net.ranides.assira.collection.suite;
 
+import java.util.Arrays;
 import java.util.NoSuchElementException;
 import java.util.SortedSet;
 import net.ranides.assira.collection.arrays.ArrayUtils;
@@ -34,7 +35,7 @@ public class SetTester {
 
         for(int i=0; i<n; i++) {
             V point = content[i];
-            V[] exp = ArrayUtils.head(content, point);
+            V[] exp = ArrayUtils.head(content, point, generator.comparator());
             SortedSet<V> map = target.headSet(point);
             assertEquals(exp.length, map.size());
             if(nested) {
@@ -58,7 +59,7 @@ public class SetTester {
         
         for(int i=0; i<n; i++) {
             V entry = content[i];
-            V[] exp = ArrayUtils.tail(content, entry);
+            V[] exp = ArrayUtils.tail(content, entry, generator.comparator());
             SortedSet<V> map = target.tailSet(entry);
             assertEquals(exp.length, map.size());
             if(nested) {
@@ -83,7 +84,7 @@ public class SetTester {
         checkSub(nested, generator, target, 4, 6, content);
         checkSub(nested, generator, target, 5, 6, content);
 
-        checkSub(nested, generator, target, 6, 5, content);
+        checkSub(nested, generator, target, 6, 7, content);
         checkSub(nested, generator, target, 6, 6, content);
         
         checkSub(nested, generator, target, 0, 3, content);
@@ -94,7 +95,7 @@ public class SetTester {
     private static <V> void checkSub(boolean nested, TGenerator<V> generator, SortedSet<V> target, int ibegin, int iend, V[] content) {
         V begin = generator.value(ibegin);
         V end = generator.value(iend);
-        V[] exp = ArrayUtils.slice(content, begin, end);
+        V[] exp = ArrayUtils.slice(content, begin, end, generator.comparator());
         SortedSet<V> map = target.subSet(begin, end);
         assertEquals(exp.length, map.size());
         checkRange(map, exp);

+ 21 - 11
assira/src/test/java/net/ranides/assira/collection/suite/SortedMapTester.java

@@ -94,7 +94,8 @@ public final class SortedMapTester<K,V> {
         checkSub(true, target, $map.list(3,4,5,6,7).keys());
     }
     
-    private void checkHead(boolean nested, SortedMap<K, V> target, K... content) {
+    @SafeVarargs
+    final void checkHead(boolean nested, SortedMap<K, V> target, K... content) {
         int n = content.length;
         assertEquals(0, target.headMap($map.item(0).key()).size());
         assertEquals(n, target.headMap($map.item(9).key()).size());
@@ -102,7 +103,7 @@ public final class SortedMapTester<K,V> {
         
         for(int i=0; i<n; i++) {
             K point = content[i];
-            K[] exp = ArrayUtils.head(content, point);
+            K[] exp = ArrayUtils.head(content, point, $map.comparator());
             SortedMap<K, V> map = target.headMap(point);
             assertEquals(exp.length, map.size());
             if(nested) {
@@ -113,7 +114,8 @@ public final class SortedMapTester<K,V> {
         }
     }
     
-    private void checkTail(boolean nested, SortedMap<K, V> target, K... content) {
+    @SafeVarargs
+    final void checkTail(boolean nested, SortedMap<K, V> target, K... content) {
         int n = content.length;
         assertEquals(n, target.tailMap($map.item(0).key()).size());
         assertEquals(0, target.tailMap($map.item(9).key()).size());
@@ -121,7 +123,7 @@ public final class SortedMapTester<K,V> {
         
         for(int i=0; i<n; i++) {
             K point = content[i];
-            K[] exp = ArrayUtils.tail(content, point);
+            K[] exp = ArrayUtils.tail(content, point, $map.comparator());
             SortedMap<K, V> map = target.tailMap(point);
             assertEquals(exp.length, map.size());
             if(nested) {
@@ -132,7 +134,8 @@ public final class SortedMapTester<K,V> {
         }
     }
     
-    private void checkSub(boolean nested, SortedMap<K, V> target, K... content) {
+    @SafeVarargs
+    final void checkSub(boolean nested, SortedMap<K, V> target, K... content) {
         checkSub(nested, target, $map.item(3), $map.item(9), content);
         checkSub(nested, target, $map.item(5), $map.item(9), content);
             
@@ -150,7 +153,7 @@ public final class SortedMapTester<K,V> {
     }
     
     private void checkSub(boolean nested, SortedMap<K, V> target, TItem<K,V> begin, TItem<K,V> end, K[] content) {
-        K[] exp = ArrayUtils.slice(content, begin.key(), end.key());
+        K[] exp = ArrayUtils.slice(content, begin.key(), end.key(), $map.comparator());
         
         SortedMap<K, V> map = target.subMap(begin.key(), end.key());
         assertEquals(exp.length, map.size());
@@ -219,13 +222,13 @@ public final class SortedMapTester<K,V> {
     @Test
     public void basicIterator(SortedMap<K, V> target) {
         TItems<K,V> list1 = $map.list();
-        TItems<K,V> list2 = $map.list(4, 7, 5, 3, 6);
+        TItems<K,V> list2 = $map.list(3, 4, 5, 6, 7);
         
         IteratorTester.basicIterator((ListIterator)target.keySet().iterator(), 0, list1.keys());
         IteratorTester.basicIterator((ListIterator)target.entrySet().iterator(), 0, list1.entries());
         IteratorTester.basicIterator((ListIterator)target.values().iterator(), 0, list1.values());
         
-        list2.into(target);
+        $map.list(4, 7, 5, 3, 6).into(target);
         
         IteratorTester.basicIterator((ListIterator)target.keySet().iterator(), 0, list2.keys());
         IteratorTester.basicIterator((ListIterator)target.entrySet().iterator(), 0, list2.entries());
@@ -236,7 +239,7 @@ public final class SortedMapTester<K,V> {
     @Test
     public void basicIteratorFrom(SortedMap<K, V> target) {
         TItems<K,V> list1 = $map.list();
-        TItems<K,V> list2 = $map.list(4, 7, 5, 3, 6);
+        TItems<K,V> list2 = $map.list(3, 4, 5, 6, 7);
         TItem<K,V> item = $map.item(4);
         
         IteratorTester.basicIterator((ListIterator)sort(target.keySet()).iterator(item.key()), 0, list1.keys());
@@ -291,7 +294,7 @@ public final class SortedMapTester<K,V> {
     @Test
     public void basicSubMap_Remove(SortedMap<K, V> target) {
         $map.list(4, 7, 5, 3, 6).into(target);
-        SortedMap<K, V> map = target.subMap($map.item(4).key(), $map.item(6).key());
+        SortedMap<K, V> map = target.subMap($map.item(4).key(), $map.item(7).key());
         assertEquals(5, target.size());
         assertEquals(3, map.size());
 
@@ -319,7 +322,14 @@ public final class SortedMapTester<K,V> {
     @Test
     public void basicToString(SortedMap<K, V> target) {
         $map.list(2,5,1,3,4).into(target);
-        assertEquals("{(7:4:6)=>17, (8:4:12)=>21, (9:4:13)=>22, (20:40:3)=>31, (33:42:6)=>81}", target.toString());
+        String expected = "{"
+            + $map.item(1).key() + "=>" + $map.item(1).value() + ", "
+            + $map.item(2).key() + "=>" + $map.item(2).value() + ", "
+            + $map.item(3).key() + "=>" + $map.item(3).value() + ", "
+            + $map.item(4).key() + "=>" + $map.item(4).value() + ", "
+            + $map.item(5).key() + "=>" + $map.item(5).value()
+            + "}";
+        assertEquals(expected, target.toString());
     }
     
 }

+ 10 - 2
assira/src/test/java/net/ranides/assira/test/TComparatorTest.java

@@ -6,7 +6,6 @@
  */
 package net.ranides.assira.test;
 
-import java.util.Arrays;
 import java.util.TreeMap;
 import org.junit.Test;
 import static org.junit.Assert.*;
@@ -25,13 +24,22 @@ public class TComparatorTest {
             assert n==0;
             return "K"+index;
         }
-
+        
         @Override
         protected String value(int index, int n) {
             assert n==0;
             return "V"+index;
         }
 
+        @Override
+        protected int cmp(String a, String b) {
+            return a.compareTo(b);
+        }
+
+        @Override
+        protected int hash(String key) {
+            return key.hashCode();
+        }
     };
         
     @Test