Java实现HashMap

14 篇文章 1 订阅

1.HashMap的介绍

HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。

HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。

HashMap 是无序的,即不会记录插入的顺序。

HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。

HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。

2.HashMap的实现

1.添加元素

/**
     * 往MyMap中添加元素
     *
     * @param key   key值
     * @param value key值对应的value值
     * @return 所添加的元素
     */
    public Object put(Object key, Object value) {
        //获取key的hashCode值
        int hashValue = key.hashCode();
        //获取key的hashCode值对应的数组下标的值
        int index = hashValue % nodes.length;
        //判断是否需要扩容
        if (size == nodes.length * 0.75) {
            //扩容操作
            capacity();
        }
        //如果index对应的链表不为空
        Node node = nodes[index];
        //遍历index对应的链表
        while (node != null) {
            //如果链表上已经存在该key值则进行替换key的value
            if (key.equals(node.key)) {
                Object oldValue = node.value;
                //替换key的value值
                node.value = value;
                return oldValue;
            }
            node = node.next;
        }
        //index对应的链表为空
        Node node1 = nodes[index];
        //新增数组节点
        nodes[index] = new Node(key, value, node1);
        size++;
        return null;
    }

2.移除元素

/**
     * 移除MyMap中的一个数据
     *
     * @param key key值
     * @return 移除key值对应的value值
     */
    public Object remove(Object key) {
        //获取key的hashCode值
        int hashValue = key.hashCode();
        //获取key的hashCode值对应的数组下标的值
        int index = hashValue % nodes.length;
        Node node = nodes[index];
        if (node != null) {
            //如果index上存在数据
            if (node.key.equals(key)) {
                //key对应上链表的第一个节点
                nodes[index] = node.next;
                size--;
                return node.value;
            } else {
                //如果key不对应链表的第一个节点
                while (null != node.next) {
                    //当前节点的下一个节点不为空
                    if (key.equals(node.next.key)) {
                        Object oldValue = node.next.value;
                        node.next = node.next.next;
                        size--;
                        return oldValue;
                    }
                    node = node.next;
                }
            }
        }
        //index上不存在数据
        return null;
    }

3.判断是否包含某个key值

/**
     * 判断MyMap是否包含某个key
     *
     * @param key 传入一个key
     * @return 包含传入的key返回true,否则返回false
     */
    public boolean containsKey(Object key) {
        //获取key的hashCode值
        int hashValue = key.hashCode();
        //获取key的hashCode值对应的数组下标的值
        int index = hashValue % nodes.length;
        //遍历数组下标对应的链表
        Node node = nodes[index];
        while (node != null) {
            if (key.equals(node.key)) {
                //如果链表中存在与key相等的值
                return true;
            }
            node = node.next;
        }
        return false;
    }

4.获取key对应的value值

/**
     * 获取key对应的value值
     *
     * @param key 传入一个key
     * @return key对应的value值,没有则返回null
     */
    public Object get(Object key) {
        //获取key的hashCode值
        int hashValue = key.hashCode();
        //获取key的hashCode值对应的数组下标的值
        int index = hashValue % nodes.length;
        //遍历数组下标对应的链表
        Node node = nodes[index];
        while (node != null) {
            if (key.equals(node.key)) {
                //如果链表中存在与key相等的值且该key的hashCode值也相等
                //返回key对应的value
                return node.value;
            }
            node = node.next;
        }
        //链表中不存在则返回null
        return null;
    }

3.完整代码+测试用例

完整代码如下:

package practice;

public class MyHashMap {

    public static void main(String[] args) {
        MyMap myMap = new MyMap();
        myMap.put("a", 1);
        myMap.put("b", 2);
        myMap.put("c", 3);
        myMap.put("d", 4);
        myMap.put("e", 5);
        myMap.put("f", 6);
        myMap.put("h", 7);
        myMap.put("i", 8);
        myMap.put("j", 9);
        myMap.put("j", 10);
        myMap.put("l", 11);
        myMap.put("m", 12);
        myMap.put("n", 13);
        myMap.put("o", 14);
        myMap.put("p", 15);
        myMap.put("qw", 16);
        myMap.put("as", 17);
        myMap.put("wt", 18);
        myMap.put("cs", 19);
        myMap.put("go", 20);
//        System.out.println(myMap.nodes.length);
        System.out.println("size:" + myMap.getSize());
//        System.out.println("isEmpty:" + myMap.isEmpty());
//        System.out.println("key对应的值:" + myMap.get("r"));
        System.out.println("containsKey:" + myMap.containsKey("a"));
        System.out.println("remove的key对应的value:" + myMap.remove("a"));
        System.out.println("size:" + myMap.getSize());
        System.out.println("containsKey:" + myMap.containsKey("a"));
//        myMap.clear();
//        System.out.println("size:" + myMap.getSize());
//        System.out.println("isEmpty:" + myMap.isEmpty());
//        System.out.println("key对应的值:" + myMap.get("r"));
    }
}


class MyMap {

    //无参构造函数
    public MyMap() {
    }

    //含Node[]的有参构造函数
    public MyMap(Node[] nodes) {
        this.nodes = nodes;
    }

    /**
     * 定义的一个单链表类
     */
    static class Node {

        Object key;
        Object value;
        Node next;

        public Node(Object key, Object value, Node next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

    }

    //起始数组长度
    private final int length = 16;

    //初始化一个数组
    Node[] nodes = new Node[length];

    //用来记录MyMap中存放的数据个数
    private int size = 0;

    /**
     * 获取MyMap的大小
     *
     * @return MyMap的大小
     */
    public int getSize() {
        return this.size;
    }

    /**
     * 判断MyMap是否为空
     *
     * @return MyMap为空返回true,否则返回false
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 判断MyMap是否包含某个key
     *
     * @param key 传入一个key
     * @return 包含传入的key返回true,否则返回false
     */
    public boolean containsKey(Object key) {
        //获取key的hashCode值
        int hashValue = key.hashCode();
        //获取key的hashCode值对应的数组下标的值
        int index = hashValue % nodes.length;
        //遍历数组下标对应的链表
        Node node = nodes[index];
        while (node != null) {
            if (key.equals(node.key)) {
                //如果链表中存在与key相等的值
                return true;
            }
            node = node.next;
        }
        return false;
    }

    /**
     * 获取key对应的value值
     *
     * @param key 传入一个key
     * @return key对应的value值,没有则返回null
     */
    public Object get(Object key) {
        //获取key的hashCode值
        int hashValue = key.hashCode();
        //获取key的hashCode值对应的数组下标的值
        int index = hashValue % nodes.length;
        //遍历数组下标对应的链表
        Node node = nodes[index];
        while (node != null) {
            if (key.equals(node.key)) {
                //如果链表中存在与key相等的值且该key的hashCode值也相等
                //返回key对应的value
                return node.value;
            }
            node = node.next;
        }
        //链表中不存在则返回null
        return null;
    }

    /**
     * 往MyMap中添加元素
     *
     * @param key   key值
     * @param value key值对应的value值
     * @return 所添加的元素
     */
    public Object put(Object key, Object value) {
        //获取key的hashCode值
        int hashValue = key.hashCode();
        //获取key的hashCode值对应的数组下标的值
        int index = hashValue % nodes.length;
        //判断是否需要扩容
        if (size == nodes.length * 0.75) {
            //扩容操作
            capacity();
        }
        //如果index对应的链表不为空
        Node node = nodes[index];
        //遍历index对应的链表
        while (node != null) {
            //如果链表上已经存在该key值则进行替换key的value
            if (key.equals(node.key)) {
                Object oldValue = node.value;
                //替换key的value值
                node.value = value;
                return oldValue;
            }
            node = node.next;
        }
        //index对应的链表为空
        Node node1 = nodes[index];
        //新增数组节点
        nodes[index] = new Node(key, value, node1);
        size++;
        return null;
    }

    /**
     * 移除MyMap中的一个数据
     *
     * @param key key值
     * @return 移除key值对应的value值
     */
    public Object remove(Object key) {
        //获取key的hashCode值
        int hashValue = key.hashCode();
        //获取key的hashCode值对应的数组下标的值
        int index = hashValue % nodes.length;
        Node node = nodes[index];
        if (node != null) {
            //如果index上存在数据
            if (node.key.equals(key)) {
                //key对应上链表的第一个节点
                nodes[index] = node.next;
                size--;
                return node.value;
            } else {
                //如果key不对应链表的第一个节点
                while (null != node.next) {
                    //当前节点的下一个节点不为空
                    if (key.equals(node.next.key)) {
                        Object oldValue = node.next.value;
                        node.next = node.next.next;
                        size--;
                        return oldValue;
                    }
                    node = node.next;
                }
            }
        }
        //index上不存在数据
        return null;
    }

    /**
     * 清空MyMap
     */
    public void clear() {
        Node[] nodes1 = new Node[nodes.length];
        size = 0;
        nodes = nodes1;
//        if (nodes != null && size > 0) {
//            size = 0;
//            Arrays.fill(nodes, null);
//        }
    }

    /**
     * 数组扩容
     */
    public void capacity() {
        //定义一个新数组
        Node[] newNode = new Node[nodes.length * 2];
        //创建一个新的MyMap对象,将新数组存入对象
        MyMap map = new MyMap(newNode);
        //遍历原来的数组
        for (Node value : nodes) {
            if (value != null) {
                //nodes[i]处存在链表就将链表put进新的MyMap对象中
                Node node = value;
                while (node != null) {
                    map.put(node.key, node.value);
                    node = node.next;
                }
            }
        }
        //最后将新的MyMap对象的nodes赋值给原来的nodes
        nodes = map.nodes;
    }

}

测试用例结果如下:

HashMap的实现到这里就结束啦!中途有任何问题可以再评论区留言,我会为你们解答。 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欲戴王冠♛必承其重

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值