182 lines
5.5 KiB
Java
182 lines
5.5 KiB
Java
/**
|
|
* A hash map that associates a 'Massive'-object with a Vector3 (typically this is the force
|
|
* exerted on the object). The number of key-value pairs is not limited.
|
|
*/
|
|
public class MassiveForceHashMap {
|
|
private int size;
|
|
private Massive[] keys;
|
|
private Vector3[] values;
|
|
|
|
/**
|
|
* Initializes 'this' as an empty map.
|
|
*/
|
|
public MassiveForceHashMap() {
|
|
this(16);
|
|
}
|
|
|
|
public MassiveForceHashMap(int capacity) {
|
|
this.size = 0;
|
|
this.keys = new Massive[capacity];
|
|
this.values = new Vector3[capacity];
|
|
}
|
|
|
|
/**
|
|
* Adds a new key-value association to this map. If the key already exists in this map,
|
|
* the value is replaced and the old value is returned. Otherwise 'null' is returned.
|
|
* Precondition: key != null.
|
|
*/
|
|
public Vector3 put(Massive key, Vector3 value) {
|
|
if (size > keys.length / 2) doubleCapacity();
|
|
|
|
int idx = ((key.hashCode() % keys.length) + keys.length) % keys.length;
|
|
for (int i = 0; i < keys.length; i++) {
|
|
int pos = (idx + i) % keys.length;
|
|
if (values[pos] == null) {
|
|
keys[pos] = key;
|
|
values[pos] = value;
|
|
size++;
|
|
return null;
|
|
} else if (keys[pos].equals(key)) {
|
|
Vector3 old = values[pos];
|
|
values[pos] = value;
|
|
return old;
|
|
}
|
|
}
|
|
throw new RuntimeException();
|
|
}
|
|
|
|
private void doubleCapacity() {
|
|
Massive[] oldKeys = keys;
|
|
Vector3[] oldValues = values;
|
|
keys = new Massive[keys.length * 2];
|
|
values = new Vector3[values.length * 2];
|
|
size = 0;
|
|
|
|
for (int i = 0; i < oldKeys.length; i++) {
|
|
Massive k = oldKeys[i];
|
|
Vector3 v = oldValues[i];
|
|
if (v != null) put(k, v);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the value associated with the specified key, i.e. the method returns the force vector
|
|
* associated with the specified key. Returns 'null' if the key is not contained in this map.
|
|
* Precondition: key != null.
|
|
*/
|
|
public Vector3 get(Massive key) {
|
|
int pos = find(key);
|
|
return (pos == -1) ? null : values[pos];
|
|
}
|
|
|
|
private int find(Massive key) {
|
|
int idx = ((key.hashCode() % keys.length) + keys.length) % keys.length;
|
|
for (int i = 0; i < keys.length; i++) {
|
|
int pos = (idx + i) % keys.length;
|
|
if (keys[pos] == null) {
|
|
break;
|
|
} else if (keys[pos].equals(key)) {
|
|
return pos;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Deletes the mapping for the specified key from this map if present.
|
|
* Returns the previous value associated with key, or null if there was
|
|
* no mapping for key.
|
|
* Precondition: key != null
|
|
*/
|
|
public Vector3 delete(Massive key) {
|
|
int pos = find(key);
|
|
if (pos == -1) return null;
|
|
|
|
Vector3 val = values[pos];
|
|
values[pos] = null;
|
|
return val;
|
|
}
|
|
|
|
/**
|
|
* Returns 'true' if this map contains a mapping for the specified key.
|
|
*/
|
|
public boolean containsKey(Massive key) {
|
|
return this.get(key) != null;
|
|
}
|
|
|
|
/**
|
|
* Returns a readable representation of this map, with all key-value pairs. Their order is not
|
|
* defined.
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
if (size == 0) return "{}";
|
|
|
|
StringBuilder sb = new StringBuilder("{");
|
|
for (int i = 0; i < keys.length; i++) {
|
|
Massive k = keys[i];
|
|
Vector3 v = values[i];
|
|
if (k != null && v != null) {
|
|
sb.append("\n ");
|
|
sb.append(k);
|
|
sb.append(": ");
|
|
sb.append(v);
|
|
sb.append(",");
|
|
}
|
|
}
|
|
sb.deleteCharAt(sb.length() - 1);
|
|
sb.append("\n}");
|
|
return sb.toString();
|
|
}
|
|
|
|
/**
|
|
* Compares `this` with the specified object for equality. Returns `true` if the specified
|
|
* `o` is not `null` and is of type `MassiveForceHashMap` and both `this` and `o` have equal
|
|
* key-value pairs, i.e. the number of key-value pairs is the same in both maps and every
|
|
* key-value pair in `this` equals one key-value pair in `o`. Two key-value pairs are
|
|
* equal if the two keys are equal and the two values are equal. Otherwise, `false` is returned.
|
|
*/
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (!(o instanceof MassiveForceHashMap map) || map.size != size)
|
|
return false;
|
|
|
|
for (int i = 0; i < keys.length; i++) {
|
|
Massive k1 = keys[i];
|
|
Vector3 v1 = values[i];
|
|
if (k1 == null || v1 == null) continue;
|
|
Vector3 v2 = map.get(k1);
|
|
if (!v1.equals(v2)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the hashCode of `this`.
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
int hash = 0;
|
|
for (int i = 0; i < keys.length; i++) {
|
|
Massive k = keys[i];
|
|
Vector3 v = values[i];
|
|
if (k == null || v == null) continue;
|
|
hash ^= k.hashCode();
|
|
hash ^= v.hashCode();
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
/**
|
|
* Returns a list of all the keys in no specified order.
|
|
*/
|
|
public MassiveLinkedList keyList() {
|
|
MassiveLinkedList list = new MassiveLinkedList();
|
|
for (int i = 0; i < keys.length; i++) {
|
|
if (keys[i] != null && values[i] != null)
|
|
list.addLast(keys[i]);
|
|
}
|
|
return list;
|
|
}
|
|
}
|