阅读 37

理解思考 HashMap

hashmap的key其hashcode值很重要

hashmap有个hash方法利用对象的hashcode来计算的,并且利用hash值来得到元素放在数组的哪个索引上;所以你hashmap的key的对象是否重写hashcode和equals就很关键了

第一种情况未重写:

当未重写时,hashcode默认实现是取对象的地址值来转成int值的,所以2个完全不同的对象无论内容是否一摸一样,其hashcode都是不同的;所以hashmap会存放不同的位置,不会覆盖内容;

注意的是即使你后期修改了对象的内容,他的hashcode也不会改变,从创建出来他的值就固定了;

第二种情况重写了:

当重写了hashcode和equals, 他的hashcode是根据内容来生成的,所以即使是new的2个对象只要他们内容一样hashcode就是一样的,hashmap中就会覆盖其value的内容;

注意: 这时不可变对象就很重要了,你要保证生成的对象后期无法修改里面内容的,否则你把数据放入hashmap中,后期key的对象内容如果改变了,它的hash值就变了,你使用它取hashamap里取数据就get不到内容了;

什么是hash冲突?

当2个不同的对象但生成的hash值计算出的索引一样时就是hash冲突了;因为2个不同的对象在hashmap中应该放在数组的不同索引上, 你hash值生成的数组索引一样了,为了你get取数据时能获取到预期的数据,所以hashmap会在当前元素上建立一个链表来把2条数据都存下来;

put(key,value)添加元素逻辑:

  1. 首次判断是否存在table数组是否存在,不存在则resize初始化table数组
  2. table[i]是否有元素,不存在则把当前value创建一个newNode元素放上
  3. table[i]有元素,则进行比较是否应该覆盖元素;旧元素的hash一直 && 旧key和新key相等 或是 equals相等也可以(当重写equals和hashcode时结果是不同的和==)
  4. table[i]有元素但并不是同一个对象无法覆盖也要显示在同一个索引上,使用链表和树来处理hash冲突;先判断当前索引上的元素是否已经转成tree结构了,如果是直接pushTree一个新元素;
  5. 如果不是树就是是链表了,对链表进行迭代,判断其next节点是否存在,不存在直接insert一个元素;如果存在则判断是否应该覆盖;利用hash和key来判断是否相同对象;
文章分类
Android
文章标签