[英]Custom HashMap implementation
這個問題是在一次采訪中問我的。 我認為獲得最佳解決方案的唯一方法是 SOF。 所以問題是“您將如何在 java 中實現自定義 HashMap(假設沒有這種稱為 HashMap 的數據結構) ”。 我能想到的唯一答案是實現關聯數組(但話說回來,Java 沒有關聯數組)。 請各位專家談談您對這個問題的看法?
簡答:
它將是一個數組(或列表)數組。
Object[][] map;
其中map[bucketIndex]
將返回“bucket”。
插入內容時,您需要一個函數來計算bucketIndex
這將使用插入對象的hashcode
。
繁榮完成!
:)
參考資料: - http://javarevisited.blogspot.sg/2011/10/override-hashcode-in-java-example.html - http://javarevisited.blogspot.in/2011/02/how-to-write-equals -method-in-java.html
class Entry<K, V> {
K key;
V val;
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getVal() {
return val;
}
public void setVal(V val) {
this.val = val;
}
@Override
public int hashCode() {
int prime = 13;
int mul = 11;
if (key != null) {
int hashCode = prime * mul + key.hashCode();
return hashCode;
}
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || this.getClass().getName() != o.getClass().getName()) {
return false;
}
Entry e = (Entry) o;
if (this.key == e.key) {
return true;
}
return false;
}
}
public class HashMapImpl<K, V> {
private float loadfactor = 0.75f;
private int capacity = 100;
private int size = 0;
private Entry<K, V> table[] = new Entry[capacity];
private int Hashing(int hashCode) {
int location = hashCode % capacity;
System.out.println("Location:"+location);
return location;
}
public int size() {
// TODO Auto-generated method stub
return this.size;
}
public boolean isEmpty() {
if(this.size == 0) {
return true;
}
return false;
}
public boolean containsKey(Object key) {
if(key == null) {
if(table[0].getKey() == null) {
return true;
}
}
int location = Hashing(key.hashCode());
Entry e = null;
try {
e = table[location];
}catch(NullPointerException ex) {
}
if(e!= null && e.getKey() == key) {
return true;
}
return false;
}
public boolean containsValue(Object value) {
for(int i=0; i<table.length;i++) {
if(table[i] != null && table[i].getVal() == value) {
return true;
}
}
return false;
}
public V get(K key) {
V ret = null;
if(key == null) {
Entry<K, V> e = null;
try{
e = table[0];
}catch(NullPointerException ex) {
}
if(e != null) {
return (V) e.getVal();
}
} else {
int location = Hashing(key.hashCode());
Entry<K, V> e = null;
try{
e = table[location];
}catch(NullPointerException ex) {
}
if(e!= null && e.getKey() == key) {
return (V)e.getVal();
}
}
return ret;
}
public V put(K key, V val) {
V ret = null;
if (key == null) {
ret = putForNullKey(val);
return ret;
} else {
int location = Hashing(key.hashCode());
if(location >= capacity) {
System.out.println("Rehashing required");
return null;
}
Entry<K, V> e = null;
try{
e = table[location];
}catch(NullPointerException ex) {
}
if (e!= null && e.getKey() == key) {
ret = (V) e.getVal();
} else {
Entry<K, V> eNew = new Entry<K,V>();
eNew.setKey(key);
eNew.setVal(val);
table[location] = eNew;
size++;
}
}
return ret;
}
private V putForNullKey(V val) {
Entry<K, V> e = null;
try {
e = table[0];
}catch(NullPointerException ex) {
}
V ret = null;
if (e != null && e.getKey() == null) {
ret = (V) e.getVal();
e.setVal(val);
return ret;
} else {
Entry<K, V> eNew = new Entry<K,V>();
eNew.setKey(null);
eNew.setVal(val);
table[0] = eNew;
size++;
}
return ret;
}
public V remove(K key) {
int location = Hashing(key.hashCode());
V ret = null;
if(table[location].getKey() == key) {
for(int i=location; i<table.length;i++) {
table[i] = table[i+1];
}
}
return ret;
}
public static void main(String[] args) {
HashMapImpl<Integer, String> hashMap = new HashMapImpl<Integer, String>();
hashMap.put(10, "Apple");
hashMap.put(1, "Orange");
hashMap.put(79, "Grape");
System.out.println("Val at 79 "+hashMap.get(79));
System.out.println("Val at 1 "+hashMap.get(1));
System.out.println("Val at 10 "+hashMap.get(10));
System.out.println("Val at 2 "+hashMap.get(2));
hashMap.put(null, "Pear");
System.out.println("Val at null "+hashMap.get(null));
System.out.println("Hashmap has key at null:"+hashMap.containsKey(null));
System.out.println("Hashmap has value at null:"+hashMap.containsValue("Pear"));
System.out.println("Size of Map:"+hashMap.size());
}
}
public class ArrayAsHashMap {
Object [][] hashArr = new Object [10] [2];
public void put(HashObject key, String value){
int index = key.hashCode();
Object [] arr = {key, value};
hashArr[index] = arr;
}
public String get(HashObject key){
int index = key.hashCode();
Object [] arr = hashArr[index];
return (String)arr[1];
}
}
查看 Cliff Click 的nonblockinghahmap以了解需要在 java 中實現的 hashmap 的示例。 請記住,關聯數組只是哈希映射的另一個名稱,因此他問您如何實現它。
通常散列是使用標准數組實現的(不是列表或任何追求速度的東西)。 問題是這些數組中的每一個都有什么......在散列沖突的情況下,您是要使用 LinkedList(鏈接)還是要重新散列並轉到另一個數組位置(開放尋址)。 閱讀更多計算機科學以了解兩者的成本/收益。
添加另一種方法 - 如果我們以這種方式使用 set 而不是 hashMap 怎么樣
創建一個名為 pair 的自定義類 -
public class Pair {
private String key;
private Object Value;
public Pair(String key, Object value) {
this.key = key;
Value = value;
}
public String getKey() {
return key;
}
public Object getValue() {
return Value;
}
@Override
public int hashCode() {
return key.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pair other = (Pair) obj;
if (key != other.getKey())
return false;
return true;
}
}
然后就可以直接使用java Set as Hashmap
public static void main(String[] args) {
Set<Pair> set = new HashSet<Pair>();
set.add(new Pair("key1", "val1"));
set.add(new Pair("key2", "val2"));
set.add(new Pair("key1", "val3"));
// you can advanced for loop for looping over set
for (Pair pair : set) {
}
// with java 8 - you can also use streams over it
// set.stream().filter
// set.stream().anyMatch
// and some more methods can be directly used
}
使用 Java-8 Stream API - 它將使更多操作變得簡單快捷。
只需將其添加為自定義哈希圖的另一種可能方法 -
每當特定索引處沒有值時,我們將直接將 Entry 對象放置在該索引處。 否則,我們將遍歷 LinkedList 直到到達列表的最后一個條目,並將新條目對象放置為最后一個條目對象的下一個節點。 在這個過程中,如果我們發現鍵已經存在,那么我們只需用新的值替換它的值。
public void put(K key, V value){
int index = index(key);
Entry newEntry = new Entry(key, value, null);
if(table[index] == null){
table[index] = newEntry;
}else {
Entry previousNode = null;
Entry currentNode = table[index];
while(currentNode != null){
if(currentNode.getKey().equals(key)){
currentNode.setValue(value);
break;
}
previousNode = currentNode;
currentNode = currentNode.getNext();
}
if(previousNode != null)
previousNode.setNext(newEntry);
}
}
public class Entry {
protected final Object key;
protected Object value;
protected Entry next;
public Entry(Object k, Object v) {
this.key = k;
this.value = v;
}
public void setValue(Object v) {
this.value = v;
}
public Object getValue() {
return this.value;
}
public Object getKey() {
return this.key;
}
@Override
public String toString() {
return "Entry [key=" + key + ", value=" + value + ", next=" + next + "]";
}
}
public class OwnHashMap {
private static final int SIZE = 16;
private Entry tables[] = new Entry[SIZE];
public Entry get(Object k) {
int hash = k.hashCode() % SIZE;
hash=Math.abs(hash);
Entry e = tables[hash];
if (e != null) {
while (e.getKey().equals(k)) {
return e;
}
e = e.next;
}
return null;
}
public void put(Object k, Object v) {
int hash = k.hashCode() % SIZE;
hash=Math.abs(hash);
Entry e = tables[hash];
if (e != null) {
if (e.getKey().equals(k)) {
e.value = v;
} else {
while (e.next != null) {
e = e.next;
}
Entry entryOld = new Entry(k, v);
tables[hash] = entryOld;
}
} else {
Entry entryNew = new Entry(k, v);
tables[hash] = entryNew;
}
}
public void printMap() {
for(Entry m:tables) {
if(m!=null)
System.out.println(m.getKey()+" "+m.getValue());
}
}
public static void main(String[] args) {
OwnHashMap map = new OwnHashMap();
map.put("Vikas", 10);
map.put("Govind", 1);
map.put("Abhishek", 3);
map.put("Sandeep", 4);
map.printMap();
}
}
輸出
Govind 1
Sandeep 4
Abhishek 3
Vikas 10
Simple HashMap Implementation in java
// Implementation class
public class HashMapCustom<K, V>
{
static class Entry <K,V>{
K key;
V value;
Entry<K,V> next;
public Entry(K key, V value,Entry<K,V> next ){
this.key=key;
this.value=value;
this.next=next;
}
}
private Entry<K,V>[] bucket ;
private int capacity = 4;
public HashMapCustom(){
bucket = new Entry [capacity];
}
public void put(K key, V value){
if(null == key) return; // null keys not allowed
int hash = hash(key);
Entry<K,V> add = new Entry<K,V> (key,value,null);
if(bucket[hash]==null){
bucket[hash]=add;
}else{
Entry<K,V> curr = bucket[hash];
while(null !=curr){
if(curr.key.equals (key)){
curr.value =value;
return;
}else{
if(curr.next == null){
curr.next = add;
return;
}
curr = curr.next;
}
}
}
}
public V get(K key){
if(null == key) return null;
int hash = hash(key);
Entry<K,V> b = bucket[hash];
if(null == b) return null;
while(null !=b){
if(b.key.equals (key)){
return b.value;
}else{
b=b.next;
}
}
return null;
}
public boolean remove(K key){
if(null == key) return false;
int hash = hash(key);
Entry<K,V> b = bucket[hash];
if(null == b) return false;
Entry<K,V> prev = null;
while(null !=b){
if(b.key.equals (key)){
//delete
if(prev == null) { // first node to remove
bucket[hash]=b.next;
return true;
}else{
prev.next = b.next;
return true;
}
}else{
prev=b;
b =b.next;
}
}
return false;
}
private int hash (K key)
{
return Math.abs (key.hashCode ())%capacity;
}
}
// calling class
public class App
{
public static void main(String a[]){
HashMapCustom<Integer,Integer> map = new HashMapCustom<Integer,Integer> ();
map.put (1,99);
map.put (2,24);
map.put (6,32);
map.put (4,10);
map.put (10,12);
map.remove (2);
map.put (1,44);
System.out.println ( map.get (6));
System.out.println ( map.get (2));
System.out.println ( map.get (6));
System.out.println ( map.get (1));
}
}
您應該使用一維數組。 對象[] arr。
數組的索引是來自 Key 對象的規范化哈希碼。 數組保存對。
值由 Key 和 Value 組成的原因是,如果存在任何哈希沖突,它必須遍歷槽內的鍵列表並找出哪個是正確的鍵(在鍵對象上使用 equals)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.