JDK1.7 hashMap的简单实现

HashMap是我们在日常的开发中最长见的类之一,对于HashMap的使用在这里就不用过多的解释了。我们来看看HashMap的简单的实现原理。
首先在jdk1.7之前的版本中,HashMap的实现的都是依靠的,(数组 + 链表)的数据结构。在jdk1.8中采用的是(数组 + 红黑树)的数据结构。
对于HashMap的理解,首先我们可以简单的自己写一个HashMap的实现来加深理解,那么就先不考虑jdk1.8,用(数组 + 链表)的形式来简单的实现。

1.定义一个ICustomMap接口方法有put(), get()方法,并且定义一个Entry内部接口
2.一定一个ICustomHashMap的类实现ICustomMap,实现put()和get()方法
uml图如下:
这里写图片描述
具体的代码如下:

public interface ICustomMap<K, V> {

    K put(K key, V value);

    V get(K key);

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

        V getValue();
    }

}

public class ICustomHashMap<K, V> implements ICustomMap {


    @Override
    public Object put(Object key, Object value) {
        return null;
    }

    @Override
    public Object get(Object key) {
        return null;
    }
}

那么就开始实现put()方法。

实现的大致思路是:
对(数组 + 链表)的结构可以这样理解。一堆数据我们按照某个规律分为几个桶,就是分为几个数组,那么分到一个通的,我们可以称之为hash冲突,如何解决hash冲突呢,hashmap的操作是把产生hash冲突的数据按照链表的形式存储起来(有点像ArrayList + linkList的结合)。
那么就开始实现put的方法:

@Override
    public Object put(Object key, Object value) {

        int hash = key.hashCode();

        int i = indexFor(hash);
        /**
         *
         * 遍历这个数组上的没一个节点,观察是否有相同的,如果有相同的节点那么就替换掉
         * 判断两个对象是否相等(hashcode是否相等 + equals是否相同)
         */
        for (Entry<K, V> e = table[i]; e != null ; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                e.value = (V) value;
                return key;
            }
        }

        table[i] = new Entry(key, value, table[i], hash);

        return null;
    }

static class Entry<K,V> implements ICustomMap.Entry<K,V> {
        K key;
        V value;
        Entry<K, V> next;
        int hash;

        Entry(K k, V v, Entry<K, V> e, int h) {
            key = k;
            value = v;
            next = e;
            hash = h;
        }

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

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

在Entry的实现类中,放了4个值,key,value,上一个节点next,和确定唯一性的hash值。
每put的一个新的元素进来的时候,
(1)先求在哪个一个数组下标下,indexFor(),
(2)然后判断是否重复
(3)把值放入下标中,并且把next指向前一个值形成链表

其实这种的方式是有一定的随机性的,如果hash冲突特别的多,hasmap就会退化成一个线性结构。
在jdk1.7的源码中,对此没有给出什么好的解决方法,在jdk1.8中个出的解决方案是,不采用链表,而是采用红黑树来存储hash冲突的数据,在查找的时候,时间复杂度从原先的O(n)将为O(logn)。我们会在下节介绍在jdk1.8中的hashmap的实现。
下面附上hashmap1.7 api的方法,已经自己对这个方法的理解:
hashMap有4个构造方法:

HashMap()
HashMap(int initialCapacity)
HashMap(int initialCapacity, float loadFactor)
HashMap(Map<? extends K,? extends V> m) 

最常用的是第一个什么都不传入,默认的数组容量大小为16,负载因子为0.75,负载因子的作用是在数组扩容时体现的,当一个hashmap的hash冲突过多的时候,如果数组不扩容,那么可能的情况就是数据线性存放,那么在查找的时候时间复杂度为O(n),所以当haspmap中的容量 > 数组容量(默认为16) * 负载因子(0.75),数组扩容2倍

void clear() 清除map中所有的元素
Object clone()  返回hashmap浅拷贝的实例,该方法并非map中的方法。
boolean containsKey(Object key) 是否包括某个key
boolean containsValue(Object value) 是否包括某个value
Set<Map.entry<K,V>> entrySet() 返回Map映射中的映射集合。此方法用与遍历map
V get(Object key) 用key查找值,返回值的范性数据
boolean isEmpty() 是否为空 空为true 非空为 false
set<K> keySet() key的set集合
K put(K key, V value) 存放键值对,返回键
void putAll(Map<? extends K,? extends V> m) 存放一个map映射
V remove(Object K) 移除一个键值对
int size() 返回hashmap的键值对个数
collection<V> values() 返回map的值的集合。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值