数据结构之手写HashMap

本文探讨了HashMap和HashSet两种常用数据结构,包括它们的特点(如null值处理、线程安全性和无序性)、HashMap的底层实现(基于数组和哈希算法),以及如何在实际开发中使用它们。重点介绍了put和get方法的工作原理以及HashSet的查找机制。

一:HashMap和HashSet特点

HashMap
1)HashMap的key和value都可以为null,key不可以重复,只要key一样就会把之前的覆盖掉。
2)HashMap是无序的,线程不安全的
3)Hashtable是Map的古老实现类;线程安全的,效率低;因为锁的是整个map。不可以存储null的key和value
HashSet
1)HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
2)HashSet 允许有 null 值。
3)HashSet 是无序的,即不会记录插入的顺序。
4)HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。
5)HashSet 实现了 Set 接口。

二:HashMap

1.定义map接口

public interface Map<K,V> {
    /**
     * put方法
     * @param k
     * @param v
     * @return
     */
    V put(K k,V v);
    /**
     * get方法
     * @param k
     * @return
     */
    V get(K k);
    /**
     * map长度
     * @return
     */
    int size();
    /**
     *
     * @param <K>
     * @param <V>
     */
    interface Entry<K,V>{
        /**
         * 获取key
         * @return
         */
        K getKey();
        /**
         * 获取value
         * @return
         */
        V getValue();
    }
}

2.定义HashMap<K,V>并且实现Map<K,V>

    Entry<K,V>[] table = null;
    int size = 0;
    public HashMap(){
        table = new Entry[16];
    }
  • HashMap底层就是一个数组,默认长度是16

3.对hashMap的key进行hash算法

    private int hash(K k){
        int index = k.hashCode() % 16;
        return index>=0?index:-index;
    }
  • 对hashMap的key值进行hash算法,取模算出下标

4.重写get和put方法

    @Override
    public V get(K k) {
        int index = hash(k);
        Entry<K, V> entry = findValue(table[index],k);
        return entry==null?null:entry.getValue();
    }

    @Override
    public V put(K k, V v) {
        int index = hash(k);
        Entry<K, V> entry = table[index];
        if(null == entry){
            table[index] = new Entry<>(k, v, index, null);
            size++;
        } else {
            table[index] = new Entry<>(k, v, index, entry);
        }
        return table[index].getValue();
    }
    @Override
    public int size() {
        return 0;
    }

1.key进行hash,取模算出index下标
2.找到数组对应的节点对象,判断对象是否为空
3.如果为空,直接返回空对象
4.如果不为空,用查出来的k和当前k做比较
1):如果相等,直接返回数据
2):如果不相等,查询next是否为空,为空直接返回
3):如果不为空,查询取出来的key和当前的key是否相等,直到相等为止

5.在entry数组中,找到指定key所对应的value值

 public Entry<K,V> findValue(Entry<K, V> entry,K k){
        if (k.equals(entry.getKey()) || k == entry.getKey()){
            return entry;
        } else {
            if( entry.next != null){
                return findValue(entry.next, k);
            }
        }
        return null;
    }

6.重写entry数组

 class Entry<K,V> implements Map.Entry<K,V>{
        K k;
        V v;
        int index;
        Entry<K,V> next;
        public Entry(K k, V v, int index, Entry<K, V> next) {
            this.k = k;
            this.v = v;
            this.index = index;
            this.next = next;
        }
        @Override
        public K getKey() {
            return k;
        }
        @Override
        public V getValue() {
            return v;
        }
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

随意石光

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

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

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

打赏作者

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

抵扣说明:

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

余额充值