您当前的位置: 首页 > 

源码分析系列教程(12) - 手写Map框架(基于JDK1.7)

杨林伟 发布时间:2019-11-04 17:48:18 ,浏览量:3

代码已上传到GitHub,有兴趣的同学可以下载来看看:https://github.com/ylw-github/Java-CodeAnalysis-Demo

1. Map接口:

package com.ylw.jdk.hashmap;

public interface ExtMap {

    // 向集合中插入数据
    public V put(K k, V v);

    // 根据k 从Map集合中查询元素
    public V get(K k);

    // 获取集合元素个数
    public int size();

    // Entry的作用=== Node节点
    interface Entry {
        K getKey();

        V getValue();

        V setValue(V value);
    }

}

2. HashMap:

package com.ylw.jdk.hashmap;

public class ExtHashMap implements ExtMap {

    // 1.定义table 存放HasMap 数组元素 默认是没有初始化容器 懒加载
    Node[] table = null;

    // 2. 实际用到table 存储容量 大小
    int size;

    // 3.HashMap默认负载因子,负载因子越小,hash冲突机率越低, 根据每个链表的个数
    float DEFAULT_LOAD_FACTOR = 0.5f;

    // 4.table默认初始大小 16
    static int DEFAULT_INITIAL_CAPACITY = 16; // 16

    public V put(K key, V value) {

        // 1.判断table 数组大小是否为空(如果为空的情况下 ,做初始化操作)
        if (table == null) {
            table = new Node[DEFAULT_INITIAL_CAPACITY];
        }
        // 2. hashMap 扩容机制 为什么要扩容?扩容数组之后,有什么影响? hahsmap 中是从什么时候开始扩容
        // 实际存储大小=负载因子*初始容量=DEFAULT_LOAD_FACTOR0.75*DEFAULT_INITIAL_CAPACITY16=12
        // 如果size>12的时候就需要开始扩容数组,扩容数组大小之前两倍
        if (size > (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY)) {
            // 需要开始对table进行属数组扩容
            resize();
        }

        // 3.计算hash值指定下标位置
        int index = getIndex(key, DEFAULT_INITIAL_CAPACITY);
        Node node = table[index];
        if (node == null) {
            // 没有发生hash冲突问题--- index冲突
            node = new Node(key, value, null);
            size++;
        } else {

            Node newNode = node;
            while (newNode != null) {
                // 已经发生hash冲突问题key 直接添加(冲突node)到前面了 不是往后面加
                if (newNode.getKey().equals(key) || newNode.getKey() == key) {
                    // hashCodoe 相同,而且equals 相等情况 说明是同一个对象 修改值
                    // node.value = value;
                    return newNode.setValue(value);
                } else {
                    // 继续添加,排在前面 hascode 取模余数相同 index 存放在链表 或者hashCode 相同但是对象不同
                    // 新的node 的next 原来的node
                    if (newNode.next == null) {
                        // 说明遍历到最后一个node ,添加node
                        node = new Node(key, value, node);
                        size++;
                    }

                }
                newNode = newNode.next;
            }

        }
        table[index] = node;
        return null;
    }

    // 对table进行扩容
    private void resize() {

        // 1.生成新的table 是之前的两倍的大小 DEFAULT_INITIAL_CAPACITY*2
        Node[] newTable = new Node[DEFAULT_INITIAL_CAPACITY             
关注
打赏
1688896170
查看更多评论
0.0629s