Java基础知识总结笔记一

equals()和==区别。为什么重写equal要重写hashcode?

== 号是运算符,equals来自于object定义的一个方法;
== 可以用于基本数据类型和引用数据类型,equals只能用于引用类型;
== 两端如果是基本数据类型,比较的值;
equals重写之后,判断两个对象的属性值是否相同;
equals不重写,其实就是==号;

重写equals可以让我们自己定义判断两个对象是否相同的条件;
Object中定义的hashCode方法生成的哈希码能保证同一个对象的哈希码一定是不同的;
当equals返回为true,我们在逻辑上可以认为是同一个对象,但是查看哈希码发现不同,和equals方法的返回结果违背;

Object中定义的hashCode方法生成的哈希码跟对象的本身属性值无关;
重写hashCode后可以自定义hash码的生成规则;可以通过对象的属性值计算出哈希码;

hashMap中,借助 equals 和 hashCode 来完成这个数据的存储;

将根据对象的内容查询转换为索引查询;

hashmap在1.8中做了那些优化?

java1.7 hashMap的数据结构为数组+链表;
java1.8 hashMap的数据结构为数组+链表+红黑树;

java1.7中,插入链表节点使用头插法。java1.8中变成了尾插法。
java1.8的hash中;将hash值高位(前16位)参与到取模的运算中,使得计算结果的不确定性增强,降低发生哈希碰撞的概率;

扩容优化:
1.7对元素进行rehash算法,计算原来的每个元素在扩容之后的哈希表的位置;
1.8通过高位运算(e.hash & oldCap)来确定元素是否需要移动,比如key1 的信息如下:
key1.hash = 10 0000 1010
oldCap = 16 0001 0000
使用e.hash & oldCap 得到的结果,高一位为0,当结果为0时表示元素在扩容时位置不会发生任何变化,为1时位置发生变化,新下标位置等于 原下标位置 + 原数组长度 hashmap,无需重新计算下标位置。

hashmap线程安全的方式?

方式一:通过Collections.synchonizedMap()返回一个新的Map,这个新的map就是线程安全的。
特点:
1)使用了经典的synchronized来进行互斥;
2)使用了代理模式,创建了一个新的类,这个类同样实习map接口;
优点:代码实现简单,一看就懂;缺点:从锁的角度来看,方法一直使用了锁住方法,性能较差。

方式二:ConcurrentHashMap
1.7 为分段锁,1.8 CAS尝试失败了在加锁。
优点:需要互斥的代码比较少,性能会比较好,把整个hashmap分为多个块,发生锁碰撞的概率大大降低,性能会比较好。缺点:代码比较繁琐
4、为什么hashmap扩容的时候是两倍?
1.8扩容之后,重新确认元素位置,和原来的hash标进行高位运算。
降低哈希冲突;

当hashMap的容量是16时,他的二进制是10000,(n-1)01111,与hash计算结果很少重复;
当hashmap的容量不是2的n次幂的情况,会出现严重hash冲突;

解决hash冲突的方式有那些?

  1. 开放定址法 :一直找空位置
  2. 再哈希法 :多个hash方法,直到算出无冲突
  3. 链地址法 :java实际使用的方式,生成链表/树 尾插法形式
  4. 建立公共溢出区:将哈希表分为基础表和溢出表,只要发生冲突,一律填入溢出表

hashmap为什么用红黑树不用普通的AVL树?

平衡二叉树类型 介绍 平衡度 调整频率 适用场景
AVL树 任何节点的两个子树的高度最大差别为1 查询多,增/删少
红黑树 任何节点的两个子树的高度最大差别为2倍 增/删频繁
上一篇:3. Longest Substring Without Repeating Characters


下一篇:java集合详解