merge key and value arrays

we have several hundred thousand of those MiniMaps and this reduces
the memory requirement by 8 bytes per instance
This commit is contained in:
ahr
2018-03-09 08:40:12 +01:00
parent 7e5b762c0d
commit 829fddf88c

View File

@@ -15,18 +15,16 @@ public class MiniMap<K, V> {
private static final Object[] EMPTY_ARRAY = new Object[0]; private static final Object[] EMPTY_ARRAY = new Object[0];
private static final MiniMap<?,?> EMPTY_MAP = new MiniMap<>(); private static final MiniMap<?,?> EMPTY_MAP = new MiniMap<>();
private Object[] keys; // keys are on even indices (0,2,4,...) and values on uneven (1,3,5,...)
private Object[] values; private Object[] keysValues;
public MiniMap() { public MiniMap() {
keys = EMPTY_ARRAY; keysValues = EMPTY_ARRAY;
values = EMPTY_ARRAY;
} }
public MiniMap(final MiniMap<K, V> miniMap){ public MiniMap(final MiniMap<K, V> miniMap){
keys = miniMap.keys.clone(); keysValues = miniMap.keysValues.clone();
values = miniMap.values.clone();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -35,7 +33,7 @@ public class MiniMap<K, V> {
} }
public int size() { public int size() {
return keys.length; return keysValues.length / 2;
} }
public boolean isEmpty() { public boolean isEmpty() {
@@ -49,10 +47,11 @@ public class MiniMap<K, V> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public V get(Object key) { public V get(Object key) {
for (int i = 0; i < keys.length; i++) { final int size = size();
Object object = keys[i]; for (int i = 0; i < size; i++) {
Object object = keysValues[2*i];
if (Objects.equals(key, object)) { if (Objects.equals(key, object)) {
return (V) values[i]; return (V) keysValues[2*i+1];
} }
} }
return null; return null;
@@ -63,25 +62,23 @@ public class MiniMap<K, V> {
V oldValue = get(key); V oldValue = get(key);
if (oldValue != null) { if (oldValue != null) {
for (int i = 0; i < keys.length; i++) { final int size = size();
Object object = keys[i]; for (int i = 0; i < size; i++) {
Object object = keysValues[2*i];
if (Objects.equals(key, object)) { if (Objects.equals(key, object)) {
values[i] = value; keysValues[2*i+1] = value;
break; break;
} }
} }
} else { } else {
final Object[] newKeys = new Object[keys.length + 1]; final Object[] newKeysValues = new Object[keysValues.length + 2];
System.arraycopy(keys, 0, newKeys, 0, keys.length); System.arraycopy(keysValues, 0, newKeysValues, 0, keysValues.length);
final Object[] newValues = new Object[values.length + 1];
System.arraycopy(values, 0, newValues, 0, values.length);
newKeys[newKeys.length - 1] = key; newKeysValues[newKeysValues.length - 2] = key;
newValues[newValues.length - 1] = value; newKeysValues[newKeysValues.length - 1] = value;
keys = newKeys; keysValues = newKeysValues;
values = newValues;
} }
return oldValue; return oldValue;
@@ -94,26 +91,28 @@ public class MiniMap<K, V> {
} }
public void clear() { public void clear() {
keys = EMPTY_ARRAY; keysValues = EMPTY_ARRAY;
values = EMPTY_ARRAY;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Set<K> keySet() { public Set<K> keySet() {
final Set<K> result = new HashSet<>(keys.length); final Set<K> result = new HashSet<>(size());
for (Object k : keys) { final int size = size();
result.add((K) k); for (int i = 0; i < size; i++) {
K k = (K) keysValues[2*i];
result.add(k);
} }
return result; return result;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Set<V> values() { public Set<V> values() {
final Set<V> result = new HashSet<>(values.length); final Set<V> result = new HashSet<>(size());
final int size = size();
for (Object v : values) { for (int i = 0; i < size; i++) {
result.add((V) v); V v = (V) keysValues[2*i+1];
result.add(v);
} }
return result; return result;
} }
@@ -122,8 +121,7 @@ public class MiniMap<K, V> {
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + Arrays.hashCode(keys); result = prime * result + Arrays.hashCode(keysValues);
result = prime * result + Arrays.hashCode(values);
return result; return result;
} }
@@ -137,9 +135,7 @@ public class MiniMap<K, V> {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
MiniMap other = (MiniMap) obj; MiniMap other = (MiniMap) obj;
if (!Arrays.equals(keys, other.keys)) if (!Arrays.equals(keysValues, other.keysValues))
return false;
if (!Arrays.equals(values, other.values))
return false; return false;
return true; return true;
} }