简单模拟HashMap数据结构的实现

    简单来说,HashMap由数组+链表组成的(jdk1.8已经重构成,当链表长度为8时,退化为红黑树),数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。所以在设计HashMap时,引入了负载因子,引入的目的,我认为:1.减少Hash碰撞,2.提高寻址速度。

什么是哈希算法。我也不知道,很复杂。简单理解就是一个函数y=f(X),这个函数很奇怪,我们能只能通过X算出对应Y,但是不能通过Y来算出对应的X,举个命题:比如张三的生日是2018年10月3号,但是反过来就算不出来了,2018年10月3号是谁的生日是算不出来的,无法唯一确定。处理通过暴力破,听说把全世界计算机联合起来,跑50年才能算出来。

代码实现:

/**
  * 定义Map通用用接口
 */
public interface Map<K, V> {
    V put(K k, V v);

    V get(K k);

    int size();

    interface Entry<K, V> {
        K getKey();

        V getValue();

        V setValue(V v);
    }
}
/**
 * 底层实现
 */
public class HashMap<K, V> implements Map<K, V> {
    //数据的存储结构(数组+链表)
    Node<K, V>[] array = null;
    //初始数组大小
    private static int defaultLength = 16;
    //加载因子
    private static double LoadFactor = 0.75;
    private static int size;


    @Override
    public V put(K k, V v) {
        //懒加载机制
        if (array == null) {
            array = new Node[defaultLength];
        }
        //hash算法确定插入数组的位置
        int index = position(k, defaultLength);
        //扩容
        if (size > defaultLength * LoadFactor) {
            resize();
        }


        //放入元素(next两种情况:1,下个元素为空 2.下个元素不为空)
        Node<K, V> node = array[index];
        if (node == null) {
            array[index] = new Node<>(k, v, null);
            size++;
        } else {
            if (k.equals(node.getKey()) || k == node.getKey()) {
                node.setValue(v);//更新(相当于去重)
            } else {
                array[index] = new Node<>(k, v, node);//返回新链表
                size++;
            }
        }

        return null;
    }

    private void resize() {
        Node<K, V>[] temp = new Node[defaultLength << 1];
        //重新计算散列值
        for (int i = 0; i < array.length; i++) {
            Node<K, V> node = array[i];
            while (node != null) {
                int index = position(node.getKey(), defaultLength);
                Node<K, V> next = node.next;
                node.next = temp[index];
                temp[index] = node;
                node = next;

            }
        }
      //替换原来的array
        array = temp;
        defaultLength=temp.length;
        temp=null;

    }

    private int position(K k, int length) {
        int code = k.hashCode();
        //取模算法
        return code % (defaultLength - 1);
        //求与算法
        //  return  code&(defaultLength-1);
    }

    @Override
    public V get(K k) {
        if (array != null) {
            int index = position(k, defaultLength);
            Node<K, V> node = array[index];
            while (node != null) {
                if (node.getKey() == k) {
                    return node.getValue();
                } else
                    node = node.next;
            }
        }
        return null;
    }

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

    static class Node<K, V> implements Entry<K, V> {
        K key;
        V value;
        Node<K, V> next;

        public Node(K key, V value, Node<K, V> next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

        @Override
        public K getKey() {
            return this.key;
        }

        @Override
        public V getValue() {
            return this.value;
        }

        @Override
        public V setValue(V v) {
            V oldValue = this.value;
            this.value = v;
            return oldValue;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "key=" + key +
                    ", value=" + value +
                    ", next=" + next +
                    '}';
        }
    }

    public void print() {
        Node<K, V> node;
        if (array != null) {
            for (int i = 0; i < array.length; i++) {
                node = array[i];
                System.out.print("[下标:" + i + "]");
                while (node != null) {
                    System.out.print(node);
                    if (node.next != null) {
                        node = node.next;
                    } else {
                        node = null;
                    }
                   
                }
            }
        }
    }
}
/**
 *  测试hashMap接口
 */
@Slf4j
public class HashMapTest {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<>();
        map.put("1", "Linux");
        map.put("2", "Windows");
        map.put("3", "Unix");
        map.print();
        log.info("size="+map.size());
        log.info("value="+map.get("009"));
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值