簡體   English   中英

自定義 HashMap 實現

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM