集合(三)Map: HashMap HashTable TreeMap WeakHashMap

Map: HashMap  HashTable  TreeMap  WeakHashMap

HashMap,HashTable,TreeMap都是Map的实现类。

Map是用来存储键值对的数据结构,在数组中通过下标对其内容索引,在Map中,是通过对象来进行索引,用来索引的对象就是key,其对应的对象叫value.

1.HashMap与HashTable的异同:

都采用了hash法进行索引,HashMap是HashTable的轻量级实现(非线程安全的实现)。

HashMap允许空键值(key),单只允许一条,HashTable不允许空键值

HashMap的方法是非线程安全的,HashTable的方法是线程安全的。

HashTable使用Enumeration,HashMap使用Iterator

Hash值不同,HashTable直接使用对象的HashCode.

2.HashMap的原理,LinkedHashMap,WeakHashMap

LinkedHashMap是HashMap的一个子类,特性:输出的顺序和输入的相同,还可以按读取顺序排列

WeakHashMap与HashMap类似,只是key采取的是弱引用,只要WeakHashMap的key不再被外部引用,就可以被垃圾收集器回收。HashMap采取的是强引用,当HashMap的key没有被外部引用时,只有当这个key从HashMap中删除后,才能被GC

同步:

在一个时间点只能有一个线程可以修改hash表,任何线程执行Hashtable的更新操作前都需要获取对象锁,其它线程则等待锁的释放

HashCode()方法会返回对象存储的内存地址。

Object类的equals()方法的比较规则:

当参数obj引用的对象与当前对象是同一个对象时,返回true,则否返回false.

如果用自定义类型作为HashMap或Hashtable的key(想根据对象的相关属性判断对象是否相等),则需要重写equals()和hashCode()方法

class Person{
//将id看做是否相等的标准
    String id;
    String name;
//
    public int hashCode(){
        return id.hashCode();
    }
//
    public boolean equals(Object obj){
        Person p = (Person)obj;
        if(p.id.equals(this.id)){
            return true;
        }
        else
        return false;
    }
}

 

HashMap实现原理:

使用链地址法解决冲突。向HashMap中添加元素时,若有冲突产生:

首先调用key的hashCode()方法获取key的hash值h,确定key的所有值存储的首地址。

如果h对应的key值有多个,接着遍历所有key,调用key的equals()方法判断key的内容是否相等,当equals()方法返回true时,对应的value才是正确的结果。

3.TreeMap,红黑树

TreeMap实现了SortMap接口,因此,取出来的是排序后的键值对。红黑树实现。

内部存储:

内部包含一个 comparator 比较器(或值被置为Key的比较器,或是被置为外部传入的比较器),根结点 root (指向红黑树的跟结点),记录修改次数 modCount ,还有一个静态内部类(其实可以理解为一个树结点),其中有存储键和值的key和value,还有指向左孩子和右孩子的“指针”,还有指向父结点的“指针”,最后还包括一个标志 color。也就是说,一个root指向树的跟结点,而这个跟根结点又链接为一棵树,最后通过这个root可以遍历整个树。

private final Comparator<? super K> comparator;
private transient Entry<K,V> root;
private transient int modCount = 0;
//静态成员内部类
static final class Entry<K,V> implements Map.Entry<K,V> {
    K key;
    V value;
    Entry<K,V> left;
    Entry<K,V> right;
    Entry<K,V> parent;
    boolean color = BLACK;
    .........
   }

添加方法put():

  1. 判断此树是否是空的,空树的操作就很简单了
  2. 判断比较器的来源做不同的操作(比较value值确定位置)
  3. 构建新结点挂上树
  4. 调用方法重构红黑树

参考:https://www.jb51.net/article/110407.htm 

https://mp.weixin.qq.com/s?__biz=MzU2MTI4MjI0MQ==&mid=2247483824&idx=1&sn=b8208d582d54cdd8a7c331c3acb3c11e&chksm=fc7a6c1ecb0de508a599152c0abc1253c69cde5f31612c807f98bb17f70aa2db04641e7b2b50&scene=21#wechat_redirect

猜你喜欢

转载自blog.csdn.net/weixin_38108266/article/details/82354921