正常情况下,Map的key和Value都可以用数组实现,一边ArrayList是key的keys,另一边是ArrayList value的values。
通过key获取value的方式是这样的values.get(keys.indexOf(key)).
然而,数组的长度是有限的。不符合map可以无限放入元素的要求。所以要对这个数组进行特殊的要求。
那就是同一个数组的index可以存放多个值,只是这些相同index的hascode值不同,这样就能把他们却别开了。同时也就实现无限个元素要求了(用数组实现主要是性能的优势)。那么要确定value就要计算hascode和数组下标。
数组不直接执行value的值,而是用equals()方法线性的查找;正常情况下这样的查找方式也会慢,但是只要hascode方法设计的合理,每个插槽将会只有少量的value.这样查找也就快很多;
import java.util.Map;
public class MapEntry<K,V> implements Map.Entry<K, V> {
private K key;
private V value;
public MapEntry(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
V result = this.value;
this.value =value;
return result;
}
@Override
public int hashCode() {
return (key == null ? 0:key.hashCode())^(value == null ? 0: value.hashCode());
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof MapEntry)) {
return false;
}
MapEntry me = (MapEntry)obj;
return (key ==null ? me.getKey() == null : key.equals(me.getKey())) &&
(value == null ? me.getValue()==null : value.equals(me.getValue()));
}
@Override
public String toString() {
return key+"="+value;
}
}
import java.util.AbstractMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
public class SimpleHashMap<K,V> extends AbstractMap<K, V> {
static final int SIZE = 997;
/**集合类型数组,数组的每个元素都是一个List集合类型**/
LinkedList<MapEntry<K, V>>[] buckets = new LinkedList[SIZE];
public V put(K key, V value) {
V oldValueV = null;
/**根据hascode对数组长度求模,计算得出应该放入数组的index位置**/
int index = Math.abs(key.hashCode())%SIZE;
if(buckets[index] == null) {
/**如果该下标下还没有集合,则创建**/
buckets[index] = new LinkedList<MapEntry<K, V>>();
}
LinkedList<MapEntry<K, V>> bucket = buckets[index];
/**把传进来的key和value封装为MapEntry类型**/
MapEntry<K, V> pair = new MapEntry<K, V>(key, value);
/**假设在该数组index下的机会里找不到与pair对应的值**/
boolean found = false;
ListIterator<MapEntry<K, V>> it = bucket.listIterator();
while(it.hasNext()) {
MapEntry<K, V> iPair = it.next();
if(iPair.getKey().equals(key)) {
/**如果已经存在,则替换掉**/
oldValueV = iPair.getValue();
it.set(pair);
found = true;
break;
}
}
if(!found) {
/**如果不存在,则把封装后的MapEntry对象加入的集合中**/
buckets[index].add(pair);
}
return oldValueV;
}
public V ge(Object key) {
/**已同样的方式计算出应该的index**/
int index = Math.abs(key.hashCode())%SIZE;
if(buckets[index]==null) {
/**对应的index里没有机会**/
return null;
}
for(MapEntry<K, V> iPair : buckets[index]) {
if(iPair.getKey().equals(key)) {
/**对该index下的机会进行查找,比较MapEntr的key值**/
return iPair.getValue();
}
}
return null;
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
Set<Map.Entry<K, V>> set = new HashSet<Map.Entry<K,V>>();
for(LinkedList<MapEntry<K, V>> bucket : buckets) {
if(bucket == null) continue;
for(MapEntry<K, V> mpair : bucket) {
/**用2个for循环,遍历这个二维的集合,把遍历到的每个值放到Set里**/
set.add(mpair);
}
}
return set;
}
public static void main(String[] args) {
SimpleHashMap<String, String> mMap = new SimpleHashMap<String,String>();
mMap.put("YYY", "yyy");
mMap.put("QQQ", "qqq");
mMap.put("AAA", "aaa");
mMap.put("GGG", "ggg");
System.out.println(mMap);
System.out.println(mMap.get("GGG"));
System.out.println(mMap.entrySet());
}
}
摘自thinking in java
来源:oschina
链接:https://my.oschina.net/u/782865/blog/200554