Ranides Atterwim hace 10 años
padre
commit
a94fe921b6

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1266 - 1265
assira/src/main/java/net/ranides/assira/collection/arrays/NativeArray.java


+ 167 - 162
assira/src/main/java/net/ranides/assira/collection/arrays/NativeArrayUtils.java

@@ -1,162 +1,167 @@
-/*
- *  @author Ranides Atterwim <ranides@gmail.com>
- *  @copyright Ranides Atterwim
- *  @license WTFPL
- *  @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.collection.arrays;
-
-import java.lang.reflect.Array;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Random;
-import net.ranides.assira.collection.iterators.IntIterator;
-
-@SuppressWarnings({
-    "PMD.AvoidReassigningParameters"
-})
-public final class NativeArrayUtils {
-
-    private NativeArrayUtils() {
-        // utility class
-    }
-    
-    /**
-     * Unwraps an iterator into an array starting at a given offset for a given
-     * number of elements.
-     *
-     * <P>This method iterates over the given type-specific iterator and stores
-     * the elements returned, up to a maximum of
-     * <code>length</code>, in the given array starting at
-     * <code>offset</code>. The number of actually unwrapped elements is
-     * returned (it may be less than
-     * <code>max</code> if the iterator emits less than
-     * <code>max</code> elements).
-     *
-     * @param iterator a type-specific iterator.
-     * @param target an array to contain the output of the iterator.
-     * @param begin the first element of the array to be returned.
-     * @param end the maximum number of elements to collect.
-     * @return the number of elements unwrapped.
-     */
-    public static int collect(Iterator iterator, Object target, int begin, int end) {
-        if(int[].class.isInstance(target)) {
-            return $collect(IntIterator.wrap(iterator), (int[])target, begin, end);
-        } else {
-            return ArrayUtils.collect(iterator, NativeArray.wrap(target), begin, end);
-        }
-    }
-    
-    /**
-     * Unwraps an iterator into an array.
-     *
-     * <P>This method iterates over the given type-specific iterator and stores
-     * the elements returned in the given array. The iteration will stop when
-     * the iterator has no more elements or when the end of the array has been
-     * reached.
-     *
-     * @param iterator a type-specific iterator.
-     * @param target an array to contain the output of the iterator.
-     * @return the number of elements unwrapped.
-     */
-    public static int collect(Iterator iterator, Object target) {
-        if(int[].class.equals(target.getClass())) {
-            int[] array = (int[])target;
-            return $collect(IntIterator.wrap(iterator), array, 0, array.length);
-        } else {
-            return ArrayUtils.collect(iterator, NativeArray.wrap(target));
-        }
-    }
-    
-    static int $collect(IntIterator iterator, int target[], int begin, int end) {
-        ArrayAllocator.ensureFromTo(target.length, begin, end);
-        int j = end;
-        while (j-- != 0 && iterator.hasNext()) {
-            target[begin++] = iterator.nextInt();
-        }
-        return end - j - 1;
-    }
-        
-    /**
-     * Fills the given array with the given value.
-     *
-     * <P>This method uses a backward loop. It is significantly faster than the
-     * corresponding method in {@link java.util.Arrays}.
-     *
-     * @param array an array.
-     * @param value the new value for all elements of the array.
-     */
-    public static void fill(Object array, Object value) {
-        ArrayUtils.fill(NativeArray.wrap(array), value);
-    }
-
-    /**
-     * Fills a portion of the given array with the given value.
-     *
-     * <P>If possible (i.e.,
-     * <code>from</code> is 0) this method uses a backward loop. In this case,
-     * it is significantly faster than the corresponding method in
-     * {@link java.util.Arrays}.
-     *
-     * @param array an array.
-     * @param begin the starting index of the portion to fill (inclusive).
-     * @param end the end index of the portion to fill (exclusive).
-     * @param value the new value for all elements of the specified portion of
-     * the array.
-     */
-    public static void fill(Object array, int begin, int end, Object value) {
-        ArrayUtils.fill(NativeArray.wrap(array), begin, end, value);
-    }
-
-    /**
-     * Reverses the order of the elements in the specified array.
-     *
-     * @param array the array to be reversed.
-     * @return <code>a</code>.
-     */
-    public static <A> A reverse(A array) {
-        ArrayUtils.reverse(NativeArray.wrap(array));
-        return array;
-    }
-    
-    /**
-     * Returns true if the two arrays are elementwise equal.
-     *
-     * <P>This method uses a backward loop. It is significantly faster than the
-     * corresponding method in {@link java.util.Arrays}.
-     *
-     * @param array1 an array.
-     * @param array2 another array.
-     * @return true if the two arrays are of the same length, and their elements
-     * are equal.
-     */
-    @SuppressWarnings("PMD")
-    public static boolean equals(Object array1, Object array2) {
-        return ArrayUtils.equals(NativeArray.wrap(array1), NativeArray.wrap(array2));
-    }
-    
-    public static <A> A head(A array, Object value, Comparator cmp) {
-        return ArrayUtils.head(NativeArray.wrap(array), value, cmp).$array();
-    }
-    
-    public static <A> A tail(A array, Object value, Comparator cmp) {
-        return ArrayUtils.tail(NativeArray.wrap(array), value, cmp).$array();
-    }
-    
-    public static <A> A slice(A array, int begin, int end, Comparator cmp) {
-        return ArrayUtils.slice(NativeArray.wrap(array), begin, end, cmp).$array();
-    }
-    
-    public static <A> A slice(A array, int begin, int end) {
-        return ArrayUtils.slice(NativeArray.wrap(array), begin, end).$array();
-    }
-    
-    public static void shuffle(Object array, Random random) {
-        ArrayUtils.shuffle(NativeArray.wrap(array), random);
-    }
-    
-    public static int size(Object array) {
-        return null == array ? 0 : Array.getLength(array);
-    }
-    
-}
+/*
+ *  @author Ranides Atterwim <ranides@gmail.com>
+ *  @copyright Ranides Atterwim
+ *  @license WTFPL
+ *  @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection.arrays;
+
+import java.lang.reflect.Array;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Random;
+import net.ranides.assira.collection.iterators.IntIterator;
+
+@SuppressWarnings({
+    "PMD.AvoidReassigningParameters"
+})
+public final class NativeArrayUtils {
+
+    private NativeArrayUtils() {
+        // utility class
+    }
+    
+    /**
+     * Unwraps an iterator into an array starting at a given offset for a given
+     * number of elements.
+     *
+     * <P>This method iterates over the given type-specific iterator and stores
+     * the elements returned, up to a maximum of
+     * <code>length</code>, in the given array starting at
+     * <code>offset</code>. The number of actually unwrapped elements is
+     * returned (it may be less than
+     * <code>max</code> if the iterator emits less than
+     * <code>max</code> elements).
+     *
+     * @param iterator a type-specific iterator.
+     * @param target an array to contain the output of the iterator.
+     * @param begin the first element of the array to be returned.
+     * @param end the maximum number of elements to collect.
+     * @return the number of elements unwrapped.
+     */
+	@SuppressWarnings("unchecked")
+    public static int collect(Iterator iterator, Object target, int begin, int end) {
+        if(int[].class.isInstance(target)) {
+            return $collect(IntIterator.wrap(iterator), (int[])target, begin, end);
+        } else {
+            return ArrayUtils.collect(iterator, NativeArray.wrap(target), begin, end);
+        }
+    }
+    
+    /**
+     * Unwraps an iterator into an array.
+     *
+     * <P>This method iterates over the given type-specific iterator and stores
+     * the elements returned in the given array. The iteration will stop when
+     * the iterator has no more elements or when the end of the array has been
+     * reached.
+     *
+     * @param iterator a type-specific iterator.
+     * @param target an array to contain the output of the iterator.
+     * @return the number of elements unwrapped.
+     */
+	@SuppressWarnings("unchecked")
+    public static int collect(Iterator iterator, Object target) {
+        if(int[].class.equals(target.getClass())) {
+            int[] array = (int[])target;
+            return $collect(IntIterator.wrap(iterator), array, 0, array.length);
+        } else {
+            return ArrayUtils.collect(iterator, NativeArray.wrap(target));
+        }
+    }
+    
+    static int $collect(IntIterator iterator, int target[], int begin, int end) {
+        ArrayAllocator.ensureFromTo(target.length, begin, end);
+        int j = end;
+        while (j-- != 0 && iterator.hasNext()) {
+            target[begin++] = iterator.nextInt();
+        }
+        return end - j - 1;
+    }
+        
+    /**
+     * Fills the given array with the given value.
+     *
+     * <P>This method uses a backward loop. It is significantly faster than the
+     * corresponding method in {@link java.util.Arrays}.
+     *
+     * @param array an array.
+     * @param value the new value for all elements of the array.
+     */
+    public static void fill(Object array, Object value) {
+        ArrayUtils.fill(NativeArray.wrap(array), value);
+    }
+
+    /**
+     * Fills a portion of the given array with the given value.
+     *
+     * <P>If possible (i.e.,
+     * <code>from</code> is 0) this method uses a backward loop. In this case,
+     * it is significantly faster than the corresponding method in
+     * {@link java.util.Arrays}.
+     *
+     * @param array an array.
+     * @param begin the starting index of the portion to fill (inclusive).
+     * @param end the end index of the portion to fill (exclusive).
+     * @param value the new value for all elements of the specified portion of
+     * the array.
+     */
+    public static void fill(Object array, int begin, int end, Object value) {
+        ArrayUtils.fill(NativeArray.wrap(array), begin, end, value);
+    }
+
+    /**
+     * Reverses the order of the elements in the specified array.
+     *
+     * @param array the array to be reversed.
+     * @return <code>a</code>.
+     */
+    public static <A> A reverse(A array) {
+        ArrayUtils.reverse(NativeArray.wrap(array));
+        return array;
+    }
+    
+    /**
+     * Returns true if the two arrays are elementwise equal.
+     *
+     * <P>This method uses a backward loop. It is significantly faster than the
+     * corresponding method in {@link java.util.Arrays}.
+     *
+     * @param array1 an array.
+     * @param array2 another array.
+     * @return true if the two arrays are of the same length, and their elements
+     * are equal.
+     */
+    @SuppressWarnings("PMD")
+    public static boolean equals(Object array1, Object array2) {
+        return ArrayUtils.equals(NativeArray.wrap(array1), NativeArray.wrap(array2));
+    }
+
+	@SuppressWarnings("unchecked")
+    public static <A> A head(A array, Object value, Comparator cmp) {
+        return ArrayUtils.head(NativeArray.wrap(array), value, cmp).$array();
+    }
+    
+	@SuppressWarnings("unchecked")
+    public static <A> A tail(A array, Object value, Comparator cmp) {
+        return ArrayUtils.tail(NativeArray.wrap(array), value, cmp).$array();
+    }
+    
+	@SuppressWarnings("unchecked")
+    public static <A> A slice(A array, int begin, int end, Comparator cmp) {
+        return ArrayUtils.slice(NativeArray.wrap(array), begin, end, cmp).$array();
+    }
+    
+    public static <A> A slice(A array, int begin, int end) {
+        return ArrayUtils.slice(NativeArray.wrap(array), begin, end).$array();
+    }
+    
+    public static void shuffle(Object array, Random random) {
+        ArrayUtils.shuffle(NativeArray.wrap(array), random);
+    }
+    
+    public static int size(Object array) {
+        return null == array ? 0 : Array.getLength(array);
+    }
+    
+}

+ 434 - 433
assira/src/main/java/net/ranides/assira/test/TMap.java

@@ -1,433 +1,434 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.test;
-
-import java.io.PrintStream;
-import java.io.Serializable;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Iterator;
-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.Swapper;
-import net.ranides.assira.collection.arrays.ArrayUtils;
-import net.ranides.assira.collection.arrays.NativeArrayAllocator;
-import net.ranides.assira.collection.lookups.ALookup;
-import net.ranides.assira.collection.lookups.Lookup.LookupEntry;
-import net.ranides.assira.collection.maps.HashMap;
-import net.ranides.assira.collection.maps.AIntMap;
-import net.ranides.assira.collection.maps.IntMap;
-import net.ranides.assira.collection.maps.IntMap.IntEntry;
-import net.ranides.assira.generic.CompareUtils;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-public abstract class TMap<K,V> implements Serializable {
-    
-    private final TCollection<K> kgen = new TCollection<K>() {
-        
-        @Override
-        public K value(int index, int n) {
-            return TMap.this.item(index, n).key();
-        }
-
-        @Override
-        protected int cmp(K a, K b) {
-            return TMap.this.cmp(a, b);
-        }
-
-        @Override
-        protected int hash(K value) {
-            return TMap.this.hash(value);
-        }
-
-    };
-    
-    private final TCollection<Entry<K,V>> egen = new TCollection<Entry<K,V>>() {
-
-        @Override
-        public Entry<K,V> value(int index, int n) {
-            return TMap.this.item(index, n).entry();
-        }
-
-        @Override
-        protected int cmp(Entry<K, V> a, Entry<K, V> b) {
-            return TMap.this.cmp(a.getKey(),b.getKey());
-        }
-
-        @Override
-        protected int hash(Entry<K, V> value) {
-            return value.hashCode();
-        }
-
-    };
-    
-    private final TCollection<IntEntry<V>> eigen = new TCollection<IntEntry<V>>() {
-
-        @Override
-        public IntEntry<V> value(int index, int n) {
-            return TMap.this.item(index, n).entryInt();
-        }
-
-        @Override
-        protected int cmp(IntEntry<V> a, IntEntry<V> b) {
-            return TMap.this.cmp((K)(Object)a.getKey(),(K)(Object)b.getKey());
-        }
-
-        @Override
-        protected int hash(IntEntry<V> value) {
-            return value.hashCode();
-        }
-
-    };
-    
-    private final TCollection<LookupEntry<K>> lgen = new TCollection<LookupEntry<K>>() {
-
-        @Override
-        public LookupEntry<K> value(int index, int n) {
-            return TMap.this.item(index, n).lookup();
-        }
-
-        @Override
-        protected int cmp(LookupEntry<K> a, LookupEntry<K> b) {
-            return TMap.this.cmp(a.getKey(),b.getKey());
-        }
-
-        @Override
-        protected int hash(LookupEntry<K> value) {
-            return value.hashCode();
-        }
-
-    };
-    
-    private final TCollection<V> vgen = new TCollection<V>() {
-
-        @Override
-        public V value(int index, int n) {
-            return TMap.this.item(index,n).value();
-        }
-
-        @Override
-        protected int cmp(V a, V b) {
-            return CompareUtils.cmp(a, b);
-        }
-
-        @Override
-        protected int hash(V value) {
-            return value.hashCode();
-        }
-
-    };
-    
-    public static final class TItem<K,V> {
-        
-        private final TMap<K,V> that;
-        
-        private final K key;
-        
-        private final V value;
-
-        protected TItem(TMap<K,V> that, K key, V value) {
-            this.that = that;
-            this.key = key;
-            this.value = value;
-        }
-        
-        public K key() {
-            return key;
-        }
-        
-        public V value() {
-            return value;
-        }
-        
-        public int keyInt() {
-            return (Integer)key;
-        }
-        
-        public int valueInt() {
-            return (Integer)value;
-        }
-        
-        public Entry<K,V> entry() {
-            return new AbstractMap.SimpleImmutableEntry<>(key, value);
-        }
-        
-        public IntMap.Entry<K,V> entry(int value) {
-            return new AbstractMap.SimpleImmutableEntry<>(key, that.value(value));
-        }
-        
-        public IntEntry<V> entryInt() {
-            return new AIntMap.BasicEntry<>(keyInt(), value());
-        }
-        
-        public IntMap.IntEntry<V> entryInt(int value) {
-            return new AIntMap.BasicEntry<>(keyInt(), that.value(value));
-        }
-        
-        public LookupEntry<K> lookup(int value) {
-            return new ALookup.BasicEntry<>(key, that.item(value).valueInt());
-        }
-        
-        public LookupEntry<K> lookup() {
-            return new ALookup.BasicEntry<>(key, valueInt());
-        }
-        
-		public <M extends Map<K,V>> M into(M target) {
-			target.put(key(), value());
-			return target;
-		}
-        
-    }
-        
-    public static final class TItems<K,V> implements Iterable<TItem<K,V>> {
-        
-        protected final TMap<K,V> that;
-        
-        protected final List<TItem<K,V>> data = new ArrayList<>();
-        
-        protected TItems(TMap<K,V> that) {
-            this.that = that;
-        }
-        
-        public K[] keys() {
-            K[] array = NativeArrayAllocator.forComponent(that.key(0).getClass(), data.size());
-            for(int i=0,n=data.size(); i<n; i++) {
-                array[i] = data.get(i).key();
-            }
-            return array;
-        }
-        
-        public V[] values() {
-            V[] array = NativeArrayAllocator.forComponent(that.value(0).getClass(), data.size());
-            for(int i=0,n=data.size(); i<n; i++) {
-                array[i] = data.get(i).value();
-            }
-            return array;
-        }
-        
-        public int[] keysInt() {
-            int[] array = new int[data.size()];
-            for(int i=0,n=data.size(); i<n; i++) {
-                array[i] = data.get(i).keyInt();
-            }
-            return array;
-        }
-        
-        public int[] valuesInt() {
-            int[] array = new int[data.size()];
-            for(int i=0,n=data.size(); i<n; i++) {
-                array[i] = data.get(i).valueInt();
-            }
-            return array;
-        }
-        
-		@SuppressWarnings("unchecked")
-        public Entry<K,V>[] entries() {
-            Entry<K,V> array[] = new Entry[data.size()];
-            for(int i=0, n=data.size(); i<n; i++) {
-                array[i] = data.get(i).entry();
-            }
-            return array;
-        }
-        
-        @SuppressWarnings("unchecked")
-        public IntEntry<V>[] entriesInt() {
-            IntEntry<V> array[] = new IntEntry[data.size()];
-            for(int i=0, n=data.size(); i<n; i++) {
-                array[i] = data.get(i).entryInt();
-            }
-            return array;
-        }
-        
-        @SuppressWarnings("unchecked")
-        public LookupEntry<K>[] lookups() {
-            LookupEntry<K> array[] = new LookupEntry[data.size()];
-            for(int i=0, n=data.size(); i<n; i++) {
-                array[i] = data.get(i).lookup();
-            }
-            return array;
-        }
-        
-		public TItems<K,V> sort(Comparator<K> cmp) {
-			TItems<K,V> items = new TItems<>(that);
-			items.data.addAll(data);
-			items.data.sort((a,b)->cmp.compare(a.key(), b.key()));
-			return items;
-		}
-        
-        public TItems<K,V> shuffle(long seed) {
-            ArrayUtils.shuffle(data.size(), new Random(seed), Swapper.swapper(data));
-            return this;
-        }
-
-        public TItems<K,V> item(int item) {
-			data.add(that.item(item,0));
-			return this;
-		}
-        
-        public TItems<K,V> item(int item, int n) {
-            data.add(that.item(item,n));
-			return this;
-		}
-		
-        @Override
-        public Iterator<TItem<K,V>> iterator() {
-            return data.iterator();
-        }
-        
-        public TItem<K,V> at(int index) {
-            return data.get(index);
-        }
-		
-		public <M extends Map<K,V>> M into(M target) {
-			for(TItem<K,V> item : data) {
-				target.put(item.key(), item.value());
-			}
-			return target;
-		}
-        
-		public void dump(PrintStream out) {
-			out.printf("TItems(%d)%n", data.size());
-			for(int i=0,n=data.size(); i<n; i++) {
-				out.printf(" - %3d. %s%n", i, data.get(i).key());
-			}
-		}
-        
-    }
-    
-    protected abstract K key(int index, int n);
-    
-    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);
-    }
-    
-    protected V value(int index) {
-        return value(index, 0);
-    }
-    
-    public HashComparator<K> comparator() {
-        return kgen.comparator();
-    }
-    
-    public TItem<K,V> item(int index) {
-        return item(index, 0);
-    }
-    
-    public TItem<K,V> item(int index, int n) {
-        return new TItem<>(this, key(index, n), value(index, n));
-    }
-	
-    public TItems<K,V> list(int... indexes) {
-        TItems<K,V> ret = new TItems<>(this);
-        for(int i=0; i<indexes.length; i++) {
-            ret.data.add(item(indexes[i]));
-        }
-        return ret;
-    }
-    
-    public TItems<K,V> range(int begin, int end) {
-        TItems<K,V> ret = new TItems<>(this);
-        for(int i=begin; i<end; i++) {
-            ret.data.add(item(i));
-        }
-        return ret;
-    }
-	
-	public TItems<K,V> range(int count) {
-		return range(0,count);
-	}
-        
-    public TItems<K,V> urange(int begin, int end) {
-        TItems<K,V> ret = new TItems<>(this);
-        for(int i=begin; i<end; i++) {
-            ret.data.add(item(i,0));
-            ret.data.add(item(i,0));
-            ret.data.add(item(i,1));
-        }
-        return ret;
-    }
-    
-    public TItems<K,V> urange(int count) {
-        return urange(0,count);
-    }
-    
-    public TCollection<K> keys() {
-        return kgen;
-    }
-    
-    public TCollection<V> values() {
-        return vgen;
-    }
-    
-    public TCollection<Entry<K,V>> entries() {
-        return egen;
-    }
-    
-    public TCollection<IntEntry<V>> entriesInt() {
-        return eigen;
-    }
-    
-    public TCollection<LookupEntry<K>> lookups() {
-        return lgen;
-    }
-    
-    public TMap<K,V> asIdentity() {
-        return new TIdentityMap();
-    }
-    
-    private class TIdentityMap extends TMap<K, V> {
-        
-        private final HashMap<Integer, TItem<K,V>> emap = new HashMap<>();
-        private final HashMap<K, Integer> imap = new HashMap<>();
-
-        private TItem<K,V> iitem(int index, int n) {
-            if(n != 0) {
-                throw new UnsupportedOperationException("NO TEST");
-            }
-            if(!emap.containsKey(index)) {
-                emap.put(index, TMap.this.item(index));
-                imap.put(emap.get(index).key(), index);
-            }
-            return emap.get(index);
-        }
-                
-        @Override
-        protected K key(int index, int n) {
-            return iitem(index, n).key();
-        }
-
-        @Override
-        protected V value(int index, int n) {
-            return iitem(index, n).value();
-        }
-
-        @Override
-        protected int cmp(K a, K b) {
-            return imap.get(a) - imap.get(b);
-        }
-
-        @Override
-        protected int hash(K key) {
-            return System.identityHashCode(key);
-        }
-        
-    }
-
-}
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.test;
+
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+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.Swapper;
+import net.ranides.assira.collection.arrays.ArrayUtils;
+import net.ranides.assira.collection.arrays.NativeArrayAllocator;
+import net.ranides.assira.collection.lookups.ALookup;
+import net.ranides.assira.collection.lookups.Lookup.LookupEntry;
+import net.ranides.assira.collection.maps.HashMap;
+import net.ranides.assira.collection.maps.AIntMap;
+import net.ranides.assira.collection.maps.IntMap;
+import net.ranides.assira.collection.maps.IntMap.IntEntry;
+import net.ranides.assira.generic.CompareUtils;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public abstract class TMap<K,V> implements Serializable {
+    
+    private final TCollection<K> kgen = new TCollection<K>() {
+        
+        @Override
+        public K value(int index, int n) {
+            return TMap.this.item(index, n).key();
+        }
+
+        @Override
+        protected int cmp(K a, K b) {
+            return TMap.this.cmp(a, b);
+        }
+
+        @Override
+        protected int hash(K value) {
+            return TMap.this.hash(value);
+        }
+
+    };
+    
+    private final TCollection<Entry<K,V>> egen = new TCollection<Entry<K,V>>() {
+
+        @Override
+        public Entry<K,V> value(int index, int n) {
+            return TMap.this.item(index, n).entry();
+        }
+
+        @Override
+        protected int cmp(Entry<K, V> a, Entry<K, V> b) {
+            return TMap.this.cmp(a.getKey(),b.getKey());
+        }
+
+        @Override
+        protected int hash(Entry<K, V> value) {
+            return value.hashCode();
+        }
+
+    };
+    
+    private final TCollection<IntEntry<V>> eigen = new TCollection<IntEntry<V>>() {
+
+        @Override
+        public IntEntry<V> value(int index, int n) {
+            return TMap.this.item(index, n).entryInt();
+        }
+
+		@SuppressWarnings("unchecked")
+        @Override
+        protected int cmp(IntEntry<V> a, IntEntry<V> b) {
+            return TMap.this.cmp((K)(Object)a.getKey(),(K)(Object)b.getKey());
+        }
+
+        @Override
+        protected int hash(IntEntry<V> value) {
+            return value.hashCode();
+        }
+
+    };
+    
+    private final TCollection<LookupEntry<K>> lgen = new TCollection<LookupEntry<K>>() {
+
+        @Override
+        public LookupEntry<K> value(int index, int n) {
+            return TMap.this.item(index, n).lookup();
+        }
+
+        @Override
+        protected int cmp(LookupEntry<K> a, LookupEntry<K> b) {
+            return TMap.this.cmp(a.getKey(),b.getKey());
+        }
+
+        @Override
+        protected int hash(LookupEntry<K> value) {
+            return value.hashCode();
+        }
+
+    };
+    
+    private final TCollection<V> vgen = new TCollection<V>() {
+
+        @Override
+        public V value(int index, int n) {
+            return TMap.this.item(index,n).value();
+        }
+
+        @Override
+        protected int cmp(V a, V b) {
+            return CompareUtils.cmp(a, b);
+        }
+
+        @Override
+        protected int hash(V value) {
+            return value.hashCode();
+        }
+
+    };
+    
+    public static final class TItem<K,V> {
+        
+        private final TMap<K,V> that;
+        
+        private final K key;
+        
+        private final V value;
+
+        protected TItem(TMap<K,V> that, K key, V value) {
+            this.that = that;
+            this.key = key;
+            this.value = value;
+        }
+        
+        public K key() {
+            return key;
+        }
+        
+        public V value() {
+            return value;
+        }
+        
+        public int keyInt() {
+            return (Integer)key;
+        }
+        
+        public int valueInt() {
+            return (Integer)value;
+        }
+        
+        public Entry<K,V> entry() {
+            return new AbstractMap.SimpleImmutableEntry<>(key, value);
+        }
+        
+        public IntMap.Entry<K,V> entry(int value) {
+            return new AbstractMap.SimpleImmutableEntry<>(key, that.value(value));
+        }
+        
+        public IntEntry<V> entryInt() {
+            return new AIntMap.BasicEntry<>(keyInt(), value());
+        }
+        
+        public IntMap.IntEntry<V> entryInt(int value) {
+            return new AIntMap.BasicEntry<>(keyInt(), that.value(value));
+        }
+        
+        public LookupEntry<K> lookup(int value) {
+            return new ALookup.BasicEntry<>(key, that.item(value).valueInt());
+        }
+        
+        public LookupEntry<K> lookup() {
+            return new ALookup.BasicEntry<>(key, valueInt());
+        }
+        
+		public <M extends Map<K,V>> M into(M target) {
+			target.put(key(), value());
+			return target;
+		}
+        
+    }
+        
+    public static final class TItems<K,V> implements Iterable<TItem<K,V>> {
+        
+        protected final TMap<K,V> that;
+        
+        protected final List<TItem<K,V>> data = new ArrayList<>();
+        
+        protected TItems(TMap<K,V> that) {
+            this.that = that;
+        }
+        
+        public K[] keys() {
+            K[] array = NativeArrayAllocator.forComponent(that.key(0).getClass(), data.size());
+            for(int i=0,n=data.size(); i<n; i++) {
+                array[i] = data.get(i).key();
+            }
+            return array;
+        }
+        
+        public V[] values() {
+            V[] array = NativeArrayAllocator.forComponent(that.value(0).getClass(), data.size());
+            for(int i=0,n=data.size(); i<n; i++) {
+                array[i] = data.get(i).value();
+            }
+            return array;
+        }
+        
+        public int[] keysInt() {
+            int[] array = new int[data.size()];
+            for(int i=0,n=data.size(); i<n; i++) {
+                array[i] = data.get(i).keyInt();
+            }
+            return array;
+        }
+        
+        public int[] valuesInt() {
+            int[] array = new int[data.size()];
+            for(int i=0,n=data.size(); i<n; i++) {
+                array[i] = data.get(i).valueInt();
+            }
+            return array;
+        }
+        
+		@SuppressWarnings("unchecked")
+        public Entry<K,V>[] entries() {
+            Entry<K,V> array[] = new Entry[data.size()];
+            for(int i=0, n=data.size(); i<n; i++) {
+                array[i] = data.get(i).entry();
+            }
+            return array;
+        }
+        
+        @SuppressWarnings("unchecked")
+        public IntEntry<V>[] entriesInt() {
+            IntEntry<V> array[] = new IntEntry[data.size()];
+            for(int i=0, n=data.size(); i<n; i++) {
+                array[i] = data.get(i).entryInt();
+            }
+            return array;
+        }
+        
+        @SuppressWarnings("unchecked")
+        public LookupEntry<K>[] lookups() {
+            LookupEntry<K> array[] = new LookupEntry[data.size()];
+            for(int i=0, n=data.size(); i<n; i++) {
+                array[i] = data.get(i).lookup();
+            }
+            return array;
+        }
+        
+		public TItems<K,V> sort(Comparator<K> cmp) {
+			TItems<K,V> items = new TItems<>(that);
+			items.data.addAll(data);
+			items.data.sort((a,b)->cmp.compare(a.key(), b.key()));
+			return items;
+		}
+        
+        public TItems<K,V> shuffle(long seed) {
+            ArrayUtils.shuffle(data.size(), new Random(seed), Swapper.swapper(data));
+            return this;
+        }
+
+        public TItems<K,V> item(int item) {
+			data.add(that.item(item,0));
+			return this;
+		}
+        
+        public TItems<K,V> item(int item, int n) {
+            data.add(that.item(item,n));
+			return this;
+		}
+		
+        @Override
+        public Iterator<TItem<K,V>> iterator() {
+            return data.iterator();
+        }
+        
+        public TItem<K,V> at(int index) {
+            return data.get(index);
+        }
+		
+		public <M extends Map<K,V>> M into(M target) {
+			for(TItem<K,V> item : data) {
+				target.put(item.key(), item.value());
+			}
+			return target;
+		}
+        
+		public void dump(PrintStream out) {
+			out.printf("TItems(%d)%n", data.size());
+			for(int i=0,n=data.size(); i<n; i++) {
+				out.printf(" - %3d. %s%n", i, data.get(i).key());
+			}
+		}
+        
+    }
+    
+    protected abstract K key(int index, int n);
+    
+    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);
+    }
+    
+    protected V value(int index) {
+        return value(index, 0);
+    }
+    
+    public HashComparator<K> comparator() {
+        return kgen.comparator();
+    }
+    
+    public TItem<K,V> item(int index) {
+        return item(index, 0);
+    }
+    
+    public TItem<K,V> item(int index, int n) {
+        return new TItem<>(this, key(index, n), value(index, n));
+    }
+	
+    public TItems<K,V> list(int... indexes) {
+        TItems<K,V> ret = new TItems<>(this);
+        for(int i=0; i<indexes.length; i++) {
+            ret.data.add(item(indexes[i]));
+        }
+        return ret;
+    }
+    
+    public TItems<K,V> range(int begin, int end) {
+        TItems<K,V> ret = new TItems<>(this);
+        for(int i=begin; i<end; i++) {
+            ret.data.add(item(i));
+        }
+        return ret;
+    }
+	
+	public TItems<K,V> range(int count) {
+		return range(0,count);
+	}
+        
+    public TItems<K,V> urange(int begin, int end) {
+        TItems<K,V> ret = new TItems<>(this);
+        for(int i=begin; i<end; i++) {
+            ret.data.add(item(i,0));
+            ret.data.add(item(i,0));
+            ret.data.add(item(i,1));
+        }
+        return ret;
+    }
+    
+    public TItems<K,V> urange(int count) {
+        return urange(0,count);
+    }
+    
+    public TCollection<K> keys() {
+        return kgen;
+    }
+    
+    public TCollection<V> values() {
+        return vgen;
+    }
+    
+    public TCollection<Entry<K,V>> entries() {
+        return egen;
+    }
+    
+    public TCollection<IntEntry<V>> entriesInt() {
+        return eigen;
+    }
+    
+    public TCollection<LookupEntry<K>> lookups() {
+        return lgen;
+    }
+    
+    public TMap<K,V> asIdentity() {
+        return new TIdentityMap();
+    }
+    
+    private class TIdentityMap extends TMap<K, V> {
+        
+        private final HashMap<Integer, TItem<K,V>> emap = new HashMap<>();
+        private final HashMap<K, Integer> imap = new HashMap<>();
+
+        private TItem<K,V> iitem(int index, int n) {
+            if(n != 0) {
+                throw new UnsupportedOperationException("NO TEST");
+            }
+            if(!emap.containsKey(index)) {
+                emap.put(index, TMap.this.item(index));
+                imap.put(emap.get(index).key(), index);
+            }
+            return emap.get(index);
+        }
+                
+        @Override
+        protected K key(int index, int n) {
+            return iitem(index, n).key();
+        }
+
+        @Override
+        protected V value(int index, int n) {
+            return iitem(index, n).value();
+        }
+
+        @Override
+        protected int cmp(K a, K b) {
+            return imap.get(a) - imap.get(b);
+        }
+
+        @Override
+        protected int hash(K key) {
+            return System.identityHashCode(key);
+        }
+        
+    }
+
+}