Delete unneeded interface dependencies of HashPMap

To reduce class count and to avoid unneeded invokeinterface's
This commit is contained in:
Alexander Udalov
2014-06-09 22:44:27 +04:00
parent d83df541b7
commit fca9a0bca2
6 changed files with 61 additions and 185 deletions
@@ -11,7 +11,7 @@ import java.util.NoSuchElementException;
*
* @author harold
*/
public final class ConsPStack<E> implements PStack<E> {
public final class ConsPStack<E> implements Iterable<E> {
private static final ConsPStack<Object> EMPTY = new ConsPStack<Object>();
@SuppressWarnings("unchecked")
@@ -48,7 +48,6 @@ public final class ConsPStack<E> implements PStack<E> {
return listIterator(0);
}
@Override
public int size() {
return size;
}
@@ -111,7 +110,6 @@ public final class ConsPStack<E> implements PStack<E> {
};
}
@Override
public ConsPStack<E> plus(E e) {
return new ConsPStack<E>(e, this);
}
@@ -126,7 +124,6 @@ public final class ConsPStack<E> implements PStack<E> {
return new ConsPStack<E>(first, newRest);
}
@Override
public ConsPStack<E> minus(int i) {
return minus(get(i));
}
@@ -1,7 +1,5 @@
package kotlin.reflect.jvm.internal.pcollections;
import static java.util.Map.Entry;
/**
* A persistent map from non-null keys to non-null values.
* <p/>
@@ -13,18 +11,18 @@ import static java.util.Map.Entry;
*
* @author harold
*/
public final class HashPMap<K, V> implements PMap<K, V> {
public static final HashPMap<Object, Object> EMPTY = new HashPMap<Object, Object>(IntTreePMap.<PStack<Entry<Object, Object>>>empty(), 0);
public final class HashPMap<K, V> {
private static final HashPMap<Object, Object> EMPTY = new HashPMap<Object, Object>(IntTreePMap.<ConsPStack<MapEntry<Object, Object>>>empty(), 0);
@SuppressWarnings("unchecked")
public static <K, V> HashPMap<K, V> empty() {
return (HashPMap<K, V>) HashPMap.EMPTY;
}
private final IntTreePMap<PStack<Entry<K, V>>> intMap;
private final IntTreePMap<ConsPStack<MapEntry<K, V>>> intMap;
private final int size;
private HashPMap(IntTreePMap<PStack<Entry<K, V>>> intMap, int size) {
private HashPMap(IntTreePMap<ConsPStack<MapEntry<K, V>>> intMap, int size) {
this.intMap = intMap;
this.size = size;
}
@@ -37,28 +35,25 @@ public final class HashPMap<K, V> implements PMap<K, V> {
return keyIndexIn(getEntries(key.hashCode()), key) != -1;
}
@Override
public V get(Object key) {
PStack<Entry<K, V>> entries = getEntries(key.hashCode());
for (Entry<K, V> entry : entries)
ConsPStack<MapEntry<K, V>> entries = getEntries(key.hashCode());
for (MapEntry<K, V> entry : entries)
if (entry.getKey().equals(key))
return entry.getValue();
return null;
}
@Override
public HashPMap<K, V> plus(K key, V value) {
PStack<Entry<K, V>> entries = getEntries(key.hashCode());
ConsPStack<MapEntry<K, V>> entries = getEntries(key.hashCode());
int size0 = entries.size();
int i = keyIndexIn(entries, key);
if (i != -1) entries = entries.minus(i);
entries = entries.plus(new SimpleImmutableEntry<K, V>(key, value));
entries = entries.plus(new MapEntry<K, V>(key, value));
return new HashPMap<K, V>(intMap.plus(key.hashCode(), entries), size - size0 + entries.size());
}
@Override
public HashPMap<K, V> minus(Object key) {
PStack<Entry<K, V>> entries = getEntries(key.hashCode());
ConsPStack<MapEntry<K, V>> entries = getEntries(key.hashCode());
int i = keyIndexIn(entries, key);
if (i == -1) // key not in this
return this;
@@ -69,15 +64,15 @@ public final class HashPMap<K, V> implements PMap<K, V> {
return new HashPMap<K, V>(intMap.plus(key.hashCode(), entries), size - 1);
}
private PStack<Entry<K, V>> getEntries(int hash) {
PStack<Entry<K, V>> entries = intMap.get(hash);
private ConsPStack<MapEntry<K, V>> getEntries(int hash) {
ConsPStack<MapEntry<K, V>> entries = intMap.get(hash);
if (entries == null) return ConsPStack.empty();
return entries;
}
private static <K, V> int keyIndexIn(PStack<Entry<K, V>> entries, Object key) {
private static <K, V> int keyIndexIn(ConsPStack<MapEntry<K, V>> entries, Object key) {
int i = 0;
for (Entry<K, V> entry : entries) {
for (MapEntry<K, V> entry : entries) {
if (entry.getKey().equals(key))
return i;
i++;
@@ -0,0 +1,47 @@
package kotlin.reflect.jvm.internal.pcollections;
/**
* <p/>
* An Entry maintaining an immutable key and value. This class
* does not support method <tt>setValue</tt>. This class may be
* convenient in methods that return thread-safe snapshots of
* key-value mappings.
*/
final class MapEntry<K, V> implements java.io.Serializable {
private static final long serialVersionUID = 7138329143949025153L;
private final K key;
private final V value;
public MapEntry(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof MapEntry)) return false;
MapEntry<?, ?> e = (MapEntry<?, ?>) o;
return (key == null ? e.key == null : key.equals(e.key)) &&
(value == null ? e.value == null : value.equals(e.value));
}
@Override
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : value.hashCode());
}
@Override
public String toString() {
return key + "=" + value;
}
}
@@ -1,14 +0,0 @@
package kotlin.reflect.jvm.internal.pcollections;
/**
* An immutable, persistent map from non-null keys of type K to non-null values of type V.
*
* @author harold
*/
public interface PMap<K, V> {
public PMap<K, V> plus(K key, V value);
public PMap<K, V> minus(Object key);
V get(Object key);
}
@@ -1,14 +0,0 @@
package kotlin.reflect.jvm.internal.pcollections;
/**
* An immutable, persistent stack.
*
* @author harold
*/
public interface PStack<E> extends Iterable<E> {
PStack<E> plus(E e);
PStack<E> minus(int i);
int size();
}
@@ -1,135 +0,0 @@
package kotlin.reflect.jvm.internal.pcollections;
import java.util.Map;
/**
* <p/>
* An Entry maintaining an immutable key and value. This class
* does not support method <tt>setValue</tt>. This class may be
* convenient in methods that return thread-safe snapshots of
* key-value mappings.
*
* @since 1.6
*/
final class SimpleImmutableEntry<K, V> implements Map.Entry<K, V>, java.io.Serializable {
private static final long serialVersionUID = 7138329143949025153L;
private final K key;
private final V value;
/**
* Creates an entry representing a mapping from the specified
* key to the specified value.
*
* @param key the key represented by this entry
* @param value the value represented by this entry
*/
public SimpleImmutableEntry(K key, V value) {
this.key = key;
this.value = value;
}
/**
* Returns the key corresponding to this entry.
*
* @return the key corresponding to this entry
*/
@Override
public K getKey() {
return key;
}
/**
* Returns the value corresponding to this entry.
*
* @return the value corresponding to this entry
*/
@Override
public V getValue() {
return value;
}
/**
* Replaces the value corresponding to this entry with the specified
* value (optional operation). This implementation simply throws
* <tt>UnsupportedOperationException</tt>, as this class implements
* an <i>immutable</i> map entry.
*
* @param value new value to be stored in this entry
* @return (Does not return)
* @throws UnsupportedOperationException always
*/
@Override
public V setValue(V value) {
throw new UnsupportedOperationException();
}
/**
* Compares the specified object with this entry for equality.
* Returns {@code true} if the given object is also a map entry and
* the two entries represent the same mapping. More formally, two
* entries {@code e1} and {@code e2} represent the same mapping
* if<pre>
* (e1.getKey()==null ?
* e2.getKey()==null :
* e1.getKey().equals(e2.getKey()))
* &amp;&amp;
* (e1.getValue()==null ?
* e2.getValue()==null :
* e1.getValue().equals(e2.getValue()))</pre>
* This ensures that the {@code equals} method works properly across
* different implementations of the {@code Map.Entry} interface.
*
* @param o object to be compared for equality with this map entry
* @return {@code true} if the specified object is equal to this map
* entry
* @see #hashCode
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
return eq(key, e.getKey()) && eq(value, e.getValue());
}
/**
* Returns the hash code value for this map entry. The hash code
* of a map entry {@code e} is defined to be: <pre>
* (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
* (e.getValue()==null ? 0 : e.getValue().hashCode())</pre>
* This ensures that {@code e1.equals(e2)} implies that
* {@code e1.hashCode()==e2.hashCode()} for any two Entries
* {@code e1} and {@code e2}, as required by the general
* contract of {@link Object#hashCode}.
*
* @return the hash code value for this map entry
* @see #equals
*/
@Override
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : value.hashCode());
}
/**
* Returns a String representation of this map entry. This
* implementation returns the string representation of this
* entry's key followed by the equals character ("<tt>=</tt>")
* followed by the string representation of this entry's value.
*
* @return a String representation of this map entry
*/
@Override
public String toString() {
return key + "=" + value;
}
/**
* Utility method for SimpleEntry and SimpleImmutableEntry.
* Test for equality, checking for nulls.
*/
private static boolean eq(Object o1, Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
}
}