diff --git a/runtime/Java/src/org/antlr/v4/runtime/misc/ClosedHashingSet.java b/runtime/Java/src/org/antlr/v4/runtime/misc/ClosedHashingSet.java deleted file mode 100644 index 0f5209d2f..000000000 --- a/runtime/Java/src/org/antlr/v4/runtime/misc/ClosedHashingSet.java +++ /dev/null @@ -1,243 +0,0 @@ -package org.antlr.v4.runtime.misc; - -import java.util.Collection; -import java.util.Iterator; -import java.util.Set; - -/** Set impl with closed hashing (open addressing). */ -public class ClosedHashingSet implements Set { - public static final int INITAL_CAPACITY = 4; - public static final double LOAD_FACTOR = 0.5; - - protected T[] table; - - /** How many elements in set */ - protected int n; - - protected int threshold; - - public ClosedHashingSet() { - table = (T[])new Object[INITAL_CAPACITY]; - threshold = (int)(INITAL_CAPACITY * LOAD_FACTOR); - } - - /** Add t to set if not there; return existing value if already there. */ - public T put(T o) { - int i = findInsertionSlot(o); - if ( i == -1 ) { - expand(); - i = findInsertionSlot(o); - } - if ( table[i]==null ) { - table[i] = o; - n++; - if ( n > threshold ) expand(); - } - else { - o = table[i]; // found, return old one - } - return o; - } - - public T get(Object o) { - int i = findSlot((T)o); - if ( i == -1 ) return null; - return table[i]; - } - - /** Where does o go in table? Return -1 if no empty space. - * Uses double-hashing to find non-home slot as explained here: - * http://www.cs.wcupa.edu/~rkline/ds/closed-hashing.html - */ - protected int findInsertionSlot(T o) { - // look for an empty slot. - int hash = hashCode(o); - int hash2 = table.length-2 - Math.abs(hash % table.length-2); - int i = hash & (table.length-1); // assumes len is power of 2 - int home = i; - if ( n>=table.length ) return -1; // full - while ( table[i]!=null && !equals(table[i],o) ) { -// System.out.println("table["+i+"]="+table[i]+", o="+o); - i = (i+hash2) & (table.length-1); - } - if ( i!=home ) System.out.println("rehash "+i+" from "+home); - return i; - } - - /** Where is o in table? Return -1 if not found. - * Uses double-hashing to find non-home slot as explained here: - * http://www.cs.wcupa.edu/~rkline/ds/closed-hashing.html - */ - protected int findSlot(T o) { - // look for the key or find an empty slot. - int hash = hashCode(o); - int hash2 = table.length-2 - Math.abs(hash % table.length-2); - int i = hash & (table.length-1); // assumes len is power of 2 - int home = i; - while ( table[i]!=null && !equals(table[i],o) ) { -// System.out.println("table["+i+"]="+table[i]+", o="+o); - i = (i+hash2) & (table.length-1); - } - if ( i!=home ) System.out.println("rehash "+i+" from "+home); - if ( table[i]==null ) return -1; // not found - return i; - } - - protected void expand() { - T[] old = table; - int newCapacity = old.length * 2; - T[] newTable = (T[])new Object[newCapacity]; - table = newTable; - threshold = (int)(newCapacity * LOAD_FACTOR); - System.out.println("new size="+newCapacity+", thres="+threshold); - // rehash all existing entries - for (T o : old) { - if ( o!=null ) { - int i = findInsertionSlot(o); - table[i] = o; - } - } - } - - public int hashCode(T t) { return t.hashCode(); } - -// // return i+1 for linear probing. doesn't terminate for other schemes -// public int rehash(int hash, int i) { return table.length-2 - Math.abs(hash % table.length); } - - public boolean equals(T a, T b) { - if ( a==null && b==null ) return true; - if ( a==null || b==null ) return false; - if ( a==b ) return true; - return a.equals(b); - } - - @Override - public boolean add(T t) { - T existing = put(t); - return existing!=t; - } - - @Override - public int size() { - return n; - } - - @Override - public boolean isEmpty() { - return n==0; - } - - @Override - public boolean contains(Object o) { - int i = findSlot((T)o); - return i == -1 || table[i]!=null; - } - - @Override - public Iterator iterator() { - throw new UnsupportedOperationException(); - } - - @Override - public Object[] toArray() { - Object[] a = new Object[size()]; - int i = 0; - for (T o : table) a[i++] = o; - return a; - } - - @Override - public U[] toArray(U[] a) { - int i = 0; - for (T o : table) a[i++] = (U)o; - return a; - } - - @Override - public boolean remove(Object o) { - int i = findSlot((T)o); - if ( i == -1 ) return false; - T existing = table[i]; - table[i]=null; - if ( existing!=null ) n--; // we wacked something - return existing!=null; - } - - @Override - public boolean containsAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean addAll(Collection c) { - boolean changed = false; - for (T o : c) { - T existing = put(o); - if ( existing!=o ) changed=true; - } - return changed; - } - - @Override - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - table = (T[])new Object[table.length]; - n = 0; - } - - public String toString() { - if ( size()==0 ) return "{}"; - - StringBuilder buf = new StringBuilder(); - buf.append('{'); - boolean first = true; - for (T o : table) { - if ( o==null ) continue; - if ( first ) first=false; - else buf.append(", "); - buf.append(o.toString()); - } - buf.append('}'); - return buf.toString(); - } - - public String toTableString() { - StringBuilder buf = new StringBuilder(); - buf.append('['); - boolean first = true; - for (T o : table) { - if ( first ) first=false; - else buf.append(" "); - if ( o==null ) buf.append("_"); - else buf.append(o.toString()); - } - buf.append(']'); - return buf.toString(); - } - - public static void main(String[] args) { - ClosedHashingSet clset = new ClosedHashingSet(); - Set set = clset; - set.add("hi"); - set.add("mom"); - set.add("foo"); - set.add("ach"); - set.add("cbba"); - set.add("d"); - set.add("edf"); - set.add("f"); - set.add("gab"); - set.remove("ach"); - System.out.println(set); - System.out.println(clset.toTableString()); - } -} diff --git a/runtime/Java/src/org/antlr/v4/runtime/misc/FlexHashingSet.java b/runtime/Java/src/org/antlr/v4/runtime/misc/FlexHashingSet.java new file mode 100644 index 000000000..5aac53591 --- /dev/null +++ b/runtime/Java/src/org/antlr/v4/runtime/misc/FlexHashingSet.java @@ -0,0 +1,318 @@ +package org.antlr.v4.runtime.misc; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +/** Set impl with closed hashing (open addressing). */ +public class FlexHashingSet implements Set { + + public static final int INITAL_CAPACITY = 4; + public static final int INITAL_BUCKET_CAPACITY = 2; + public static final double LOAD_FACTOR = 0.8; + + protected T[][] buckets; + + /** How many elements in set */ + protected int n = 0; + + protected int threshold = (int)(INITAL_CAPACITY * LOAD_FACTOR); // when to expand + + protected int currentPrime = 1; // jump by 4 primes each expand or whatever + + public FlexHashingSet() { + buckets = (T[][])new Object[INITAL_CAPACITY][]; + } + + /** Add o to set if not there; return existing value if already there. */ + public T put(T o) { + if ( n > threshold ) expand(); + return put_(o); + } + + protected T put_(T o) { + int b = getBucket(o); + T[] bucket = buckets[b]; + if ( bucket==null ) { + buckets[b] = (T[])new Object[INITAL_BUCKET_CAPACITY]; + buckets[b][0] = o; + n++; + return o; + } + for (int i=0; i other = (FlexHashingSet)o; + if ( other.size() != size() ) return false; + return containsAll(other); + } + + protected void expand() { + T[][] old = buckets; + currentPrime += 4; + int newCapacity = buckets.length * 2; + T[][] newTable = (T[][])new Object[newCapacity][]; + buckets = newTable; + threshold = (int)(newCapacity * LOAD_FACTOR); + System.out.println("new size="+newCapacity+", thres="+threshold); + // rehash all existing entries + int oldSize = size(); + for (T[] bucket : old) { + if ( bucket==null ) continue; + for (T o : bucket) { + if ( o==null ) break; + put_(o); + } + } + n = oldSize; + } + + public int hashCode(T o) { + return o.hashCode(); + } + + public boolean equals(T a, T b) { + if ( a==null && b==null ) return true; + if ( a==null || b==null ) return false; + if ( a==b ) return true; + return a.equals(b); + } + + @Override + public boolean add(T t) { + T existing = put(t); + return existing!=t; + } + + @Override + public int size() { + return n; + } + + @Override + public boolean isEmpty() { + return n==0; + } + + @Override + public boolean contains(Object o) { + return get((T)o) != null; + } + + @Override + public Iterator iterator() { +// return new Iterator() { +// int i = -1; +// @Override +// public boolean hasNext() { return (i+1) < table.length; } +// +// @Override +// public T next() { +// i++; +// if ( i > table.length ) throw new NoSuchElementException(); +// while ( table[i]==null ) i++; +// return table[i]; +// } +// +// @Override +// public void remove() { +// } +// } + throw new UnsupportedOperationException(); + } + + @Override + public Object[] toArray() { + Object[] a = new Object[size()]; + int i = 0; + for (T[] bucket : buckets) { + if ( bucket==null ) continue; + for (T o : bucket) { + if ( o==null ) break; + a[i++] = o; + } + } + return a; + } + + @Override + public U[] toArray(U[] a) { + int i = 0; + for (T[] bucket : buckets) { + if ( bucket==null ) continue; + for (T o : bucket) { + if ( o==null ) break; + a[i++] = (U)o; + } + } + return a; + } + + @Override + public boolean remove(Object o) { + if ( o==null ) return false; + int b = getBucket((T)o); + T[] bucket = buckets[b]; + if ( bucket==null ) return false; // no bucket + for (int i=0; i c) { + if ( c instanceof FlexHashingSet) { + for (Object o : ((FlexHashingSet)c).buckets) { + if ( o!=null && !contains(o) ) return false; + } + } + else { + for (Object o : c) { + if ( !contains(o) ) return false; + } + } + return true; + } + + @Override + public boolean addAll(Collection c) { + boolean changed = false; + for (T o : c) { + T existing = put(o); + if ( existing!=o ) changed=true; + } + return changed; + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + buckets = (T[][])new Object[buckets.length][]; + n = 0; + } + + public String toString() { + if ( size()==0 ) return "{}"; + + StringBuilder buf = new StringBuilder(); + buf.append('{'); + boolean first = true; + for (T[] bucket : buckets) { + if ( bucket==null ) continue; + for (T o : bucket) { + if ( o==null ) break; + if ( first ) first=false; + else buf.append(", "); + buf.append(o.toString()); + } + } + buf.append('}'); + return buf.toString(); + } + + public String toTableString() { + StringBuilder buf = new StringBuilder(); + for (T[] bucket : buckets) { + if ( bucket==null ) { + buf.append("null\n"); + continue; + } + buf.append('['); + boolean first = true; + for (T o : bucket) { + if ( first ) first=false; + else buf.append(" "); + if ( o==null ) buf.append("_"); + else buf.append(o.toString()); + } + buf.append("]\n"); + } + return buf.toString(); + } + + public static void main(String[] args) { + FlexHashingSet clset = new FlexHashingSet(); + Set set = clset; + set.add("hi"); + set.add("mom"); + set.add("foo"); + set.add("ach"); + set.add("cbba"); + set.add("d"); + set.add("edf"); + set.add("f"); + set.add("gab"); + set.remove("ach"); + System.out.println(set); + System.out.println(clset.toTableString()); + } +}