前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java实现自己的map

java实现自己的map

作者头像
码农王同学
发布2020-03-25 10:44:07
1K0
发布2020-03-25 10:44:07
举报
文章被收录于专栏:后端Coder

由于jdk提供的map在工作中的场景用的很多,打算看下网上的文章如何实现自己的map。

代码语言:javascript
复制
文章参考于https://blog.csdn.net/m0_37499059/article/details/80623438

HashMap的底层实现主要是基于数组和链表来实现的,HashMap中通过key的hashCode来计算hash值的,由这个hash值计算在数组中的位置,将新插入的元素放到数组的这个位置,如果新插入的元素的hash值跟这个位置上已有元素的hash值相同,就会出现hash冲突,这时候回话,就在该位置通过链表来插入新的元素。

首先我们先暂时定义一下map常用的几个方法的接口。

代码语言:javascript
复制
package com.wpw.springbootmymap;

public interface MyMap {
    /**
     * 返回map集合大小
     * @return map集合大小
     */
    int size();

    /**
     * 判断map是否为空
     * @return true/false
     */
    boolean isEmpty();

    /**
     * 根据key获取value
     * @param key 键
     * @return 根据键返回的value
     */
    Object get(Object key);

    /**
     * 添加元素
     * @param key 键
     * @param value 值
     * @return 旧值
     */
    Object put(Object key,Object value);
    interface Entry<k,v>{
        /**
         * 获取key
         * @return 键
         */
        k getKey();

        /**
         * 获取值
         * @return 值
         */
        v getValue();
    }
}
代码语言:javascript
复制
package com.wpw.springbootmymap;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.util.Set;

public class MyHashMap<K, V> implements MyMap {
    /**
     * 默认容量为16
     */
    private static final int DEFAULT_CAPACITY = 1 << 4;
    /**
     * 内部存储结构
     */
    Node[] table = new Node[DEFAULT_CAPACITY];
    /**
     * 长度
     */
    private int size;
    Set<K> keySet;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    @Accessors(chain = true)
    static class Node implements MyMap.Entry {
        /**
         * hash值
         */
        int hash;
        /**
         * key
         */
        Object key;
        /**
         * value
         */
        Object value;
        /**
         * 指向下个节点(单链表)
         */
        Node next;

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

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

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

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

    @Override
    public Object get(Object key) {
        int hashValue = hash(key);
        int i = indexFor(hashValue, table.length);
        for (Node node = table[i]; node != null; node = node.next) {
            if (node.key.equals(key) && hashValue == node.hash) {
                return node.value;
            }
        }
        return null;
    }

    /**
     * 获取hash值
     *
     * @param key
     * @return
     */
    public int hash(Object key) {
        return key.hashCode();
    }

    /**
     * 获取插入的位置
     *
     * @param hashValue
     * @param length
     * @return
     */
    private int indexFor(int hashValue, int length) {
        return hashValue % length;
    }

    @Override
    public Object put(Object key, Object value) {
        /**通过key获取hash值
         * */
        int hashValue = hash(key);
        /**通过hash找到这个key应该放的位置*/
        int i = indexFor(hashValue, table.length);
        for (Node node = table[i]; node != null; node = node.next) {
            Object k;
            if (node.hash == hashValue && ((k = node.key) == key || key.equals(k))) {
                Object oldValue = node.value;
                node.value = value;
                return oldValue;
            }
        }
        /**
         * 如果i位置没有数据,或者i位置有数据但是key是新的key,新增节点
         */
        addEntry(key, value, hashValue, i);
        return null;
    }

    private void addEntry(Object key, Object value, int hashValue, int i) {
        /***
         * 如果超过了原数组大小,则扩大数组
         */
        if (++size == table.length) {
            Node[] newTable = new Node[table.length << 1];
            System.arraycopy(table, 0, newTable, 0, table.length);
            table = newTable;
        }
        Node eNode = table[i];
        /**新增节点,将该节点的next指向前一个节点*/
        table[i] = new Node(hashValue, key, value, eNode);
    }
}

基于接口和实现类,我们已完成了自定义map的实现,接下来就是测试我们自定义map的测试示例程序了。

代码语言:javascript
复制
package com.wpw.springbootmymap;

public class Test {
    public static void main(String[] args) {
        MyMap myMap=new MyHashMap<>();
        myMap.put("a",1);
        myMap.put("a",2);
        System.out.println(myMap.get("a"));
        System.out.println(myMap.isEmpty());
        System.out.println(myMap.size());
        System.out.println(myMap.put("a",3));
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农王同学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档