map基础知识

map是双列数据,存储key-value 键值对,是无序的

map 里的key是不可重复的

hashmap是map的主要实现类,线程不安全,效率高,可以存储null的key和value

jdk7及以前: 数组+链表

jdk8:数组+链表+红黑树(什么是红黑树)

还有一些其他实现类

hashlinkmap:能按照添加顺序进行遍历,因为在hashmap基础上加了指针。

hashtable:古老实现类,线程安全,不能存储null的key和value

 

默认数组初始长度是16

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

 

hashmap 继承 map 接口  实现接口规定的 entry<k,v> 方法

数组用的也是 entry 类型数组

 

再说说hashmap的无序性,无序性不是随机性,这个无序性是指将数据存储入底层数组并不是按照先后顺序放入数组,而是通过hash函数(我也不知道这个是什么东西,有空再查查),计算出数据的hash值,再通过算法(简单认为将 hash 值除 数组长度)计算出这个数据再数组中的位置。

找不到 hash 值怎么出来的。。。

当已经使用的数组+链表长度达到数组总长度的0.75,数组就会自动扩容,数组总长度扩大为原来的2倍。

链表是为了解决 hash 冲突

如果多个数据都在数组的同一位置上(根据key的hash值计算这个键值对在数组中的位置),就会出现 hash 冲突,发送冲突后会先比较数据是否重复,首先比较两个键值对的key的hash值是否相同,在同一数组位置上的数据的hash值可能是不同的,例如  hash值为 1/16(取模) 放在数组第一个位置, 17/16 也是放在数组第一个位置,如果hash值相同就用equals 比较(对象还要重写hashcode方法)。

如果存储的是基本数据类型没有equals方法用什么比较? 

不能存储基本数据类型

如果发送key 相同的冲突,后来的会覆盖先来的

public class test1 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("apple","aa");
map.put("apple","bb");
for(String key : map.keySet()){
System.out.println(key+"-------"+map.get(key));
}
}
}


有点问题

public class test1 {
    public static void main(String[] args) {
        Integer a1 = new Integer(4);
        Integer a2 = new Integer(4);
        Integer a3 = new Integer(5);
        Integer a4 = new Integer(6);
        Map<Integer,Integer> map = new HashMap<>();
        map.put(a1,a3);
        map.put(a2,a4);
        for(Integer key : map.keySet()){
            System.out.println(key+"----"+map.get(key));
        }
        }
    }

这里new了两个Interger 地址是不同里,应该可以都存进去,但是发生了覆盖。

key里放的是引用类型对象的地址,我用new,两个Interger的地址肯定是不同的,为什么会发生这种情况?

查了资料,hash 值是根据函数自己重写的 hashcode 方法计算的,就算我new了两个Integer,他们的hash 值一样,会落在数组的同一个位置上,然后用equals方法比较,结果就重复了。

大概就这样吧



















map基础知识

上一篇:logstash配置从提取业务日志时间更新到@timestamp及取消kinbana显示_source, _id, _type, _index, _score元数据


下一篇:怎么实现一个RPC框架?