Forráskód Böngészése

new: VirtualList / IntVirtualList
change: HashFunction#make -> #produce

Ranides Atterwim 10 éve
szülő
commit
ca9528509c

+ 1 - 1
assira/src/main/java/net/ranides/assira/collection/HashFunction.java

@@ -15,7 +15,7 @@ public interface HashFunction<K> {
 
     boolean equals(K a, K b);
     
-    static <K> HashFunction<K> make(ToIntFunction<K> hash, BiPredicate<K,K> eq) {
+    static <K> HashFunction<K> produce(ToIntFunction<K> hash, BiPredicate<K,K> eq) {
         return new HashFunction<K>(){
             @Override
             public int hashCode(K object) {

+ 12 - 0
assira/src/main/java/net/ranides/assira/collection/lists/IntListUtils.java

@@ -119,5 +119,17 @@ public final class IntListUtils {
 		};
     }
 
+    public static IntList produce(int size, IntUnaryOperator function) {
+        return new IntVirtualList() {
+            @Override
+            public int size() {
+                return size;
+            }
+            @Override
+            public int getInt(int index) {
+                return function.applyAsInt(index);
+            }
+        };
+    } 
 
 }

+ 188 - 0
assira/src/main/java/net/ranides/assira/collection/lists/IntVirtualList.java

@@ -0,0 +1,188 @@
+/*
+ *  @author Ranides Atterwim <ranides@gmail.com>
+ *  @copyright Ranides Atterwim
+ *  @license WTFPL
+ *  @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.collection.lists;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.RandomAccess;
+import net.ranides.assira.collection.IntCollection;
+import net.ranides.assira.collection.iterators.IntListIterator;
+import net.ranides.assira.collection.sets.IntHashSet;
+import net.ranides.assira.collection.sets.IntSet;
+
+/**
+ * Abstract class for easy creation "virtual lists". Algorithms in below implementation
+ * try to minimize use of {@link #get} method, because of assumption that read operations
+ * have high cost, although class doesn't use any buffering.
+ * <p>
+ * By default list is immutable. If you want to create mutable list, you shoud override:
+ * </p>
+ * <ul>
+ *      <li> {@link #set(int index, Object value) set(int index, Object value)}</li>
+ *      <li> {@link #add(int index, Object value) add(int index, Object value)}</li>
+ *      <li> {@link #remove(int) remove(int index)}</li>
+ * </ul>
+ * @param <T>
+ */
+public abstract class IntVirtualList extends AIntList implements RandomAccess, Serializable {
+    
+    private static final long serialVersionUID = 1L;
+
+    private static final String NSE = "Not supported by immutable virtual lists.";
+
+    @Override
+    public abstract int size();
+
+    @Override
+    public abstract int getInt(int index);
+
+    @Override
+    public void add(int index, int element) {
+        throw new UnsupportedOperationException(NSE);
+    }
+
+    @Override
+    public int set(int index, int element) {
+        throw new UnsupportedOperationException(NSE);
+    }
+
+    @Override
+    public int removeInt(int index) {
+        throw new UnsupportedOperationException(NSE);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> values) {
+        // we don't use this.contains to avoid iteration over list many times
+        IntSet set = iset(values, true);
+        return values.size()==set.size() && icontainsAll(set);
+    }
+    
+    @Override
+    public boolean containsAll(IntCollection values) {
+        // we don't use this.contains to avoid iteration over list many times
+        return icontainsAll(new IntHashSet(values));
+    }
+    
+    @Override
+    public boolean removeAll(Collection<?> values) {
+        // we don't use this.remove to avoid iteration over list many times
+        return iremoveAll(iset(values, false));
+    }
+    
+    @Override
+    public boolean removeAll(IntCollection values) {
+        // we don't use this.remove to avoid iteration over list many times
+        return iremoveAll(new IntHashSet(values));
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> values) {
+        // we don't use this.remove&this.contains to avoid iteration over list many times
+        return iretainAll(iset(values, false));
+    }
+    
+    @Override
+    public boolean retainAll(IntCollection values) {
+        // we don't use this.remove&this.contains to avoid iteration over list many times
+        return iretainAll(new IntHashSet(values));
+    }
+    
+    private boolean iretainAll(IntSet set) {
+        boolean modified = false;
+        IntListIterator iterator = listIterator();
+        while(iterator.hasNext()) {
+            int value = iterator.nextInt();
+            if(!set.contains(value)) {
+                iterator.remove();
+                modified = true;
+            }
+        }
+        return modified;
+    }
+    
+    private boolean icontainsAll(IntSet set) {
+        IntListIterator iterator = listIterator();
+        while(iterator.hasNext()) {
+            set.remove( iterator.nextInt());
+            if( set.isEmpty() ) { return true; }
+        }
+        return false;
+    }
+    
+    private boolean iremoveAll(IntSet set) {
+        boolean modified = false;
+        IntListIterator iterator = listIterator();
+        while(iterator.hasNext()) {
+            int value = iterator.nextInt();
+            if(set.contains(value)) {
+                iterator.remove();
+                modified = true;
+            }
+        }
+        return modified;
+    }
+    
+    private IntSet iset(Collection<?> values, boolean failfast) {
+        IntSet set = new IntHashSet(values.size());
+        for(Object o : values) {
+            if(o instanceof Integer) {
+                set.add( ((Integer)o).intValue() );
+            } else if(failfast) {
+                break;
+            }
+        }
+        return set;
+    }
+    
+    @Override
+    public IntList subList(int begin, int end) {
+        // we use "our implementation" because we want to provide overriden #containsAll / #removeAll etc
+        return new SubList(this, begin, end);
+    }
+
+    private static class SubList extends IntVirtualList {
+
+        private final IntList list;
+        private final int from;
+        private final int to;
+
+        public SubList(IntList list, int from, int to) {
+            this.list = list;
+            this.from = from;
+            this.to = to;
+        }
+
+        @Override
+        public int size() {
+            return Math.max(0, Math.min(to, list.size() ) - from );
+        }
+
+        @Override
+        public int getInt(int index) {
+            return list.get(from+index);
+        }
+
+        @Override
+        public void add(int index, int element) {
+            list.add(from+index,element);
+        }
+
+        @Override
+        public int set(int index, int element) {
+            return list.set(from+index,element);
+        }
+
+        @Override
+        public int removeInt(int index) {
+            return list.remove(from + index);
+        }
+
+    }
+   
+}

+ 13 - 2
assira/src/main/java/net/ranides/assira/collection/lists/ListUtils.java

@@ -8,11 +8,10 @@
 package net.ranides.assira.collection.lists;
 
 import java.util.AbstractList;
-import java.util.Collection;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.function.Function;
-import java.util.function.IntUnaryOperator;
+import java.util.function.IntFunction;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import net.ranides.assira.collection.CollectionUtils;
@@ -77,5 +76,17 @@ public final class ListUtils {
 		};
     }
 
+    public static <Q> List<Q> produce(int size, IntFunction<Q> function) {
+        return new VirtualList<Q>() {
+            @Override
+            public int size() {
+                return size;
+            }
+            @Override
+            public Q get(int index) {
+                return function.apply(index);
+            }
+        };
+    }  
 
 }

+ 202 - 0
assira/src/main/java/net/ranides/assira/collection/lists/VirtualList.java

@@ -0,0 +1,202 @@
+/*
+ *  @author Ranides Atterwim <ranides@gmail.com>
+ *  @copyright Ranides Atterwim
+ *  @license WTFPL
+ *  @url http://ranides.net/projects/assira
+ */
+
+package net.ranides.assira.collection.lists;
+
+import java.io.Serializable;
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.RandomAccess;
+import java.util.Set;
+import java.util.function.IntFunction;
+import net.ranides.assira.collection.iterators.RandomAccessIterator;
+import net.ranides.assira.collection.sets.HashSet;
+
+/**
+ * Abstract class for easy creation "virtual lists". Algorithms in below implementation
+ * try to minimize use of {@link #get} method, because of assumption that read operations
+ * have high cost, although class doesn't use any buffering.
+ * <p>
+ * By default list is immutable. If you want to create mutable list, you shoud override:
+ * </p>
+ * <ul>
+ *      <li> {@link #set(int index, Object value) set(int index, Object value)}</li>
+ *      <li> {@link #add(int index, Object value) add(int index, Object value)}</li>
+ *      <li> {@link #remove(int) remove(int index)}</li>
+ * </ul>
+ * @param <T>
+ */
+public abstract class VirtualList<T> extends AbstractList<T> implements RandomAccess, Serializable {
+    
+    private static final long serialVersionUID = 1L;
+
+    private static final String NSE = "Not supported by immutable virtual lists.";
+
+    @Override
+    public abstract int size();
+
+    @Override
+    public abstract T get(int index);
+
+    @Override
+    public void add(int index, T element) {
+        throw new UnsupportedOperationException(NSE);
+    }
+
+    @Override
+    public T set(int index, T element) {
+        throw new UnsupportedOperationException(NSE);
+    }
+
+    @Override
+    public T remove(int index) {
+        throw new UnsupportedOperationException(NSE);
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+        return listIterator();
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> values) {
+        // we don't use this.contains to avoid iteration over list many times
+        Set<?> set = new HashSet<>(values);
+        ListIterator<? extends T> iterator = listIterator();
+        while(iterator.hasNext()) {
+            set.remove( iterator.next() );
+            if( set.isEmpty() ) { return true; }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> values) {
+        // we don't use this.remove to avoid iteration over list many times
+        boolean modified = false;
+        Set<?> set = new HashSet<>(values);
+        ListIterator<? extends T> iterator = listIterator();
+        while(iterator.hasNext()) {
+            T value = iterator.next();
+            if(set.contains(value)) {
+                iterator.remove();
+                modified = true;
+            }
+        }
+        return modified;
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> values) {
+        // we don't use this.remove&this.contains to avoid iteration over list many times
+        boolean modified = false;
+        Set<?> set = new HashSet<>(values);
+        ListIterator<? extends T> iterator = listIterator();
+        while(iterator.hasNext()) {
+            T value = iterator.next();
+            if(!set.contains(value)) {
+                iterator.remove();
+                modified = true;
+            }
+        }
+        return modified;
+    }
+
+    @Override
+    public ListIterator<T> listIterator() {
+        // faster than default, but without concurrent "fail fast" 
+        return new IIterator(0);
+    }
+
+    @Override
+    public ListIterator<T> listIterator(int index) {
+        // faster than default, but without concurrent "fail fast" 
+        return new IIterator(index);
+    }
+
+    @Override
+    public List<T> subList(int begin, int end) {
+        // we use "our implementation" because we want to provide overriden #containsAll / #removeAll etc
+        return new SubList<>(this, begin, end);
+    }
+
+    private class IIterator extends RandomAccessIterator<T> {
+
+        public IIterator(int index) {
+            super(index);
+        }
+
+        @Override
+        protected void remove(int index) {
+            VirtualList.this.remove(index);
+        }
+
+        @Override
+        protected void add(int index, T value) {
+            VirtualList.this.add(index, value);
+        }
+
+        @Override
+        protected void set(int index, T value) {
+            VirtualList.this.set(index, value);
+        }
+
+        @Override
+        protected T get(int index) {
+            return VirtualList.this.get(index);
+        }
+
+        @Override
+        protected int size() {
+            return VirtualList.this.size();
+        }
+
+    }
+
+    private static class SubList<Q> extends VirtualList<Q> {
+
+        private final List<Q> list;
+        private final int from;
+        private final int to;
+
+        public SubList(List<Q> list, int from, int to) {
+            this.list = list;
+            this.from = from;
+            this.to = to;
+        }
+
+        @Override
+        public int size() {
+            return Math.max(0, Math.min(to, list.size() ) - from );
+        }
+
+        @Override
+        public Q get(int index) {
+            return list.get(from+index);
+        }
+
+        @Override
+        public void add(int index, Q element) {
+            list.add(from+index,element);
+        }
+
+        @Override
+        public Q set(int index, Q element) {
+            return list.set(from+index,element);
+        }
+
+        @Override
+        public Q remove(int index) {
+            return list.remove(from + index);
+        }
+
+    }
+  
+}

+ 1 - 1
assira/src/main/java/net/ranides/assira/collection/maps/HashMultiMap.java

@@ -163,7 +163,7 @@ public final class HashMultiMap<K, V> extends AHashMap<K, V> implements MultiMap
 
     @Override
     public Set<K> uniqueKeySet() {
-        return new CustomSet<>(keySet(), HashFunction.make(this::hash, this::compare));
+        return new CustomSet<>(keySet(), HashFunction.produce(this::hash, this::compare));
     }
         
     private class MCollection extends ACollection<V> {