繁体   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