I want to explain to beginners what a Map
is in Java, with the assumption that beginners do not understand what a hashcode is.
As I developed games (Tarot, Belote, President, Pokemon), I know Java pretty well and I do not understand why overriding hashcode considering that I developed a Map
class that looks like the standard HashMap
class.
Besides, order of entries is not random unlike the standard HashMap
class. The order of entries in my custom Map
class is the order of inserting them. Besides, I think that my Map
objects are lighter than objects of the standard HashMap
class.
I hope that beginners will understand better collections with my customized class.
package util;
import java.io.Serializable;
public final class EntryCust<K, V> implements Serializable {
private static final String SEPARATOR = " ";
private K key;
private V value;
public EntryCust(K _k, V _v) {
key = _k;
value = _v;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public void setValue(V _v) {
value = _v;
}
@Override
public boolean equals(Object _obj) {
if (!(_obj instanceof EntryCust)) {
return false;
}
//EntryCust is a final class, so testing "_obj instanceof EntryCust" is sufficient.
EntryCust<?,?> pair_ = (EntryCust<?,?>) _obj;
if (key == null) {
if (value == null) {
if (pair_.value != null) {
return false;
}
return pair_.key == null;
}
if (!value.equals(pair_.value)) {
return false;
}
return pair_.key == null;
}
if (value == null) {
if (!key.equals(pair_.key)) {
return false;
}
return pair_.value == null;
}
if (!key.equals(pair_.key)) {
return false;
}
if (!value.equals(pair_.value)) {
return false;
}
return true;
}
@Override
public String toString() {
return key+SEPARATOR+value;
}
}
Keys of my maps are compared ONLY with "equals" method in order to make much easier to understand functionment of maps. I want to serialize my maps with the Serializable
interface.
package util;
import java.io.Serializable;
import java.util.ArrayList;
/**Serializable interface is used for serializing this map*/
public class Map<K, V> implements Serializable {
/**list cannot be null, even by reflection.
New entries are appended to the list
in order to code better tests about order of entries*/
private final ArrayList<EntryCust<K, V>> list = new ArrayList<EntryCust<K, V>>();
//Default constructor
public Map() {
}
//Copy the map object but not the entries
public Map(Map<? extends K, ? extends V> _arg0) {
putAllMap(_arg0);
}
//Return the entries
public ArrayList<EntryCust<K,V>> entryList() {
return list;
}
//Only equals method is used if the parameter _key is not null.
//hashcode is too much hard for using by beginners
public V get(K _key) {
if (_key == null) {
for (EntryCust<K, V> e:entryList()) {
if (e.getKey() == null) {
return e.getValue();
}
}
return null;
}
for (EntryCust<K, V> e:entryList()) {
if (_key.equals(e.getKey())) {
return e.getValue();
}
}
return null;
}
//The contains method uses only equals on the parameter _key
public boolean contains(K _key) {
return getKeys().contains(_key);
}
//The contains method uses only equals on the parameter _key
public boolean has(V _value) {
return values().contains(_value);
}
public ArrayList<V> values() {
ArrayList<V> s_ = new ArrayList<V>();
for (EntryCust<K, V> e: list) {
s_.add(e.getValue());
}
return s_;
}
//Only equals method is used if the parameter _key is not null.
public void put(K _key, V _v) {
if (_key == null) {
int i_ = 0;
for (EntryCust<K, V> e: list) {
if (e.getKey() == null) {
list.get(i_).setValue(_v);
return;
}
i_++;
}
list.add(new EntryCust<K, V>(_key, _v));
return;
}
int i_ = 0;
for (EntryCust<K, V> e: list) {
K key_ = e.getKey();
if (_key.equals(key_)) {
list.get(i_).setValue(_v);
return;
}
i_++;
}
list.add(new EntryCust<K, V>(_key, _v));
return;
}
//Only equals method is used if the parameter _key is not null.
public void remove(K _key) {
if (_key == null) {
int i_ = 0;
for (EntryCust<K, V> e:entryList()) {
if (e.getKey() == null) {
entryList().remove(i_);
return;
}
i_++;
}
return;
}
int i_ = 0;
for (EntryCust<K, V> e:entryList()) {
K key_ = e.getKey();
if (_key.equals(key_)) {
entryList().remove(i_);
return;
}
i_++;
}
}
public ArrayList<K> getKeys() {
ArrayList<K> s_ = new ArrayList<K>();
for (EntryCust<K, V> e: list) {
s_.add(e.getKey());
}
return s_;
}
//Clear the map entries
public void clear() {
list.clear();
}
//Put the entries of an other map using equals on keys
public void putAllMap(Map<? extends K, ? extends V> _m) {
for (EntryCust<? extends K,? extends V> e: _m.entryList()) {
put(e.getKey(), e.getValue());
}
}
//Test is the map is empty or not
public boolean isEmpty() {
return list.isEmpty();
}
//Return the number of entries
public int size() {
return list.size();
}
//Return the string representation of the map
@Override
public String toString() {
return list.toString();
}
}
if/else
cascades, useless code (default constructor) unnessesarry commments... And finally: If you think you students cannot deal with hashcode, why should they do better with serialisation? \$\endgroup\$