前注:本文介绍的HashMap并非Java类库的实现。而是根据哈希表知识的一个实现。
上文介绍了开放地址法实现HashTable,它的缺点是对hashCode映射为地址后如果出现重复地址,则会占用其他元素的位置。这样HashTable存储容量有限,而且不便于算法理解。本文介绍链地址法实现HashMap。
链地址法内部仍然有一个数组,但区别与开放地址法,该数组存储的是一个链表的引用。当根据hashCode计算出数组下表后,对元素的增删查改都是在该数组元素所指向的链表上完成的。这就解决了hashCode重复的问题。因为,当hashCode重复,多个元素对应同一个地址,但元素实际存储的位置在数组对应的链表上。所以相同hashCode的不同元素可以存储在同一位置。
下面是代码实现:
package org.lyk.impl; import java.util.ArrayList; import org.lyk.interfaces.IMap; public class HashMap<K,V> implements IMap<K, V> { private class KeyValue { private K key; private V value; public KeyValue(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public void setKey(K key) { this.key = key; } public V getValue() { return value; } public void setValue(V value) { this.value = value; } } private int maxSize = 10; // private int currentAmmount = 0; private Object[] table; public HashMap() { this.table = new Object[this.maxSize]; for(int i = 0; i < this.maxSize; i++) { this.table[i] = new java.util.ArrayList<KeyValue>(); } } @Override public void add(K key, V value) { int index = this.getIndex(key); ((java.util.List<KeyValue>)this.table[index]).add(new KeyValue(key, value)); } @Override public boolean remove(K key) { int index = this.getIndex(key); java.util.List<KeyValue> kvs = (java.util.List<KeyValue>)this.table[index]; int listIndex = -1; for(KeyValue kv : kvs) { if(kv.key.equals(key)) { listIndex = kvs.indexOf(kv); } } if(listIndex != -1) { kvs.remove(listIndex); return true; } return false; } @Override public V get(K key) { KeyValue kv= this.find(key); if(kv != null) return kv.getValue(); else return null; } @Override public boolean contains(K key) { if(this.get(key) != null) return true; else return false; } @Override public void replace(K key, V value) { KeyValue kv = this.find(key); if(kv != null) { kv.setValue(value); } } private int getIndex(K key) { return Math.abs(key.hashCode())%this.maxSize; } private KeyValue find(K key) { int index = this.getIndex(key); java.util.List<KeyValue> kvs = (java.util.List<KeyValue>)this.table[index]; int listIndex = -1; for(KeyValue kv : kvs) { if(kv.key.equals(key)) { return kv; } } return null; } }
HashMap
package org.lyk.impl; import java.math.BigInteger; public class Info { private String name; private String address; private Integer age; public Info(String name, String address, Integer age) { super(); this.name = name; this.address = address; this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((address == null) ? 0 : address.hashCode()); result = prime * result + ((age == null) ? 0 : age.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } // @Override // public int hashCode() // { // final int prime = 27; // int result = 1; // result = prime*result + (this.name == null ? 0:this.name.hashCode()); // result = prime*result + (this.address == null ? 0:this.address.hashCode()); // result = prime*result + (this.age == null ? 0 : this.age.hashCode()); // return result; // } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Info other = (Info) obj; if (address == null) { if (other.address != null) return false; } else if (!address.equals(other.address)) return false; if (age == null) { if (other.age != null) return false; } else if (!age.equals(other.age)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Info [name=" + name + ", address=" + address + ", age=" + age + "]"; } }
Info
package org.lyk.main; import java.util.ArrayList; import java.util.List; import org.lyk.impl.HashMap; import org.lyk.impl.Info; public class Main { public static void main(String[] args) { HashMap<String, Info> hm = new HashMap<String, Info>(); for(int i = 0; i < 15; i++) { hm.add("sheldon" + i, new Info("sheldon" + i, "address" + i, i)); } String key = "sheldon12"; Info sheldon12 = new Info("sheldon12", "洛杉矶", 99); System.out.println(hm.get(key)); hm.replace(key, sheldon12); System.out.println(hm.get(key)); hm.remove(key); System.out.println(hm.get(key)); System.out.println("///~ main done"); } }
Main测试
时间: 2024-10-11 09:44:11