JAVA_12


JAVA容器HashMap

1.HashMap

底层实现采用了哈希表,这是一种非常重要的数据结构。
对于我们以后理解很多技术都非常有帮助(比如:redis 数据库的核心技术和 HashMap 一样),因此,非常有必要理解。

2.数据结构中由数组和链表来实现对数据的存储,他们各有特点。

(1)数组:占用空间连续。寻址容易,查询速度快。但是,增加和删除效率非常低。
(2)链表:占用空间不连续。 寻址困难,查询速度慢。但是,增加和删除效率非常高。
那么,我们能不能结合数组和链表的优点(即查询快,增删效率也高)呢?答案就是“哈希表”。哈希表的本质就是“数组+链表”

3.equals和hashcode通常需要一起重写!

equals为true,那么hashcode必须相等(主要就是为了HashMap。如果不这么规定,HashMap存取的时候就有悖论了!)

4.手写HashMap

package obj.src.lz;

import java.util.HashMap;

/**
 * 自定义map接口
 * @param <K>
 * @param <V>
 */
public interface MyMap<K,V> {
    public void put(K key,V value);
    public V get(K key);
    public boolean containsKey(K key);
    public boolean containValue(V value);
    public void remove(K key);
    public int size();
    public boolean isEmpty();


}

5.手写MyHashMap

package obj.src.lz;

import java.util.Arrays;

/**
 * 手工实现HashMap
 *
 * @param <K>
 * @param <V>
 */
public class MyHashMap<K, V> implements MyMap<K, V> {

    private static final int INITIAL_CAPACITY = 16;

    private int size;

    private Entry[] table;

    public MyHashMap() {
        table = new Entry[INITIAL_CAPACITY];
    }

    public static void main(String[] args) {
        MyMap<String, String> map = new MyHashMap<>();
        System.out.println(map.size());
        map.put("a", "123");
        map.put("a", "124");
        map.put("b", "1234");
        map.put("c", "12345");
        String b = map.get("b");
        System.out.println(b);
        map.remove("b");
        System.out.println(map);
    }

    @Override
    public String toString() {
//        return "MyHashMap{" +
//                "size=" + size +
//                ", table=" + Arrays.toString(table) +
//                '}';
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        //思考:怎么去掉最后一个,
//        for (Entry e : table) {
//            while (e != null) {
//                sb.append("{" + e.key + ":" + e.value + "},");
//                e = e.next;
//            }
//        }
        boolean first = true;

        for (Entry<K, V> e : table) {
            while (e != null) {
                if (!first) {
                    sb.append(", ");
                }
                sb.append("{").append(e.key).append(":").append(e.value).append("}");
                first = false; 
                e = e.next;
            }
        }
        sb.append("]");
        return sb.toString();
    }

    @Override
    public void put(K key, V value) {
        int index = hash(key);

        Entry entry = new Entry(key, value, index, null);

        if (table[index] == null) {
            table[index] = entry;
        } else {
            Entry e = table[index];
            Entry last = e;
            while (e != null) {
                if (e.key.equals(key)) {
                    e.value = value;//key相等,则覆盖value
                    return;
                }
                last = e;
                e = e.next;
            }
            last.next = entry;
        }
        size++;
    }

    public int hash(Object key) {
        int hashcode = key.hashCode();//返回int,可能时负数
        hashcode = hashcode < 0 ? -hashcode : hashcode;

//        int index = hashcode % table.length;//早期jdk就是这样做的
        int index = hashcode & (table.length - 1);//位运算,效率高
        return index;
    }

    @Override
    public V get(K key) {
        int index = hash(key);

        while (table[index] != null) {
            Entry e = table[index];
            while (e != null) {
                if (e.key.equals(key)) {
                    return (V) e.value;
                }
                e = e.next;
            }
        }

        return null;
    }

    @Override
    public boolean containsKey(K key) {
        return false;
    }

    @Override
    public boolean containValue(V value) {
        return false;
    }

    @Override
    public void remove(K key) {
        int index = hash(key);
        if (table[index] != null) {
            Entry e = table[index];
            Entry previous = null;
            while (e != null) {
                if (e.key.equals(key)) {
                    if (previous == null) {//说明是第一个节点
                        table[index] = e.next;
                    } else {
                        previous.next = e.next;
                    }
                    size--;
                }
                previous = e;
                e = e.next;
            }
        }
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }
}

class Entry<K, V> {
    K key;
    V value;
    int hash;
    Entry next;

    public Entry(K key, V value, int hash, Entry next) {
        this.key = key;
        this.value = value;
        this.hash = hash;
        this.next = next;
    }

    public Entry() {
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值