集合与方法常见问题

String和StringBuilder和String Buffer的区别?

 String是不可变的,如果尝试修改,会新生成一个字符串对象,而StringBuilder和StringBuffer是可变的。

StringBuffer是线程安全的,String Builder是线程不安全的。所以在单线程String Builder效率更高,而多线程则采用String Buffer。

泛型中extends和super的区别?

< ? extends T>表示包括T在内的任何T的子类

<? super T>表示包括T在内的任何T的父类

==和equals的区别?

==:如果是基本数据类型,比较是值,如果是引用数据类型,比较的是引用地址。

Equals:具体看各个类型重写equals方法之后的比较逻辑比如String类,虽然是引用数据类型,但它重写了equals方法,比较的是各个字符是否相等。

重载和重写的区别?

重载:(OverLoad)在一个类中,同名的方法如果有不同的参数列表(参数类型不同,参数个数不同)则为重载。

重写:(OverRide)在子类中把父类的方法重写一遍,子类继承了父类的方法,但有时子类并不想原封不动的继承父类的方法,所以在方法名,参数列表,返回类型都相同的情况下,对方法体进行修改,这就是重写。

List和Set的区别?

List:有序,按对象插入的顺序保存对象,可重复,允许多个null元素,可以使用Iterator方法遍历所有元素,还可以使用get(int index)获取指定下标的元素。

Set:无序,不可重复,最多允许有一个null元素,取元素只能用Iterator逐一遍历所有元素。

Array List和LinkedList的区别?

首先,他们的底层结构不同,Array List是基于数组实现的,而Linked List是基于链表实现的。

由于底层数据结构不同,他们使用场景也不同,Array List适用于随机查找,Linked List适用于删除和添加,查询,删除和添加的时间复杂度不同。

另外Array List和Linked List都实现了List接口,但是LinkedList还实现了Deque接口,所以Linked List还可以当队列来使用。

谈谈concurrentHashMap的扩容机制?

JDK1.7:

1.7的Concurrent Hash Map是基于Segment实现的。

每个Segment都是一个小的Hash Map,每个Segment内部都会进行扩容,和Hash Map的扩容机制类似先生成数组,在转移元素到新数组中。

扩容的判断是每个Segment单独判断的,是否超过阈值。

JDK1.8:

1.8的版本不再是通过Segment实现的。

当某个线程进行put时,如果发现concurrentHashMap正在进行扩容,那么该线程一起进行扩容。

如果某个线程put时,发现concurrentHashMap没有进行扩容,则将key value添加到Hashmap中,然后判断是否超过阈值,超过则进行扩容。

ConcurrentHash Map支持多线程同时扩容。

扩容前也是新生成一个新数组,转移元素时,先将原数组分类,将每组分给不同的线程进行元素转移,每个线程负责一组或多组的元素转移工作。

JDK1.7到JDK1.8HashMap发生了什么变化?

1:1.7中底层使用数组+链表 ,而1.8中使用数组+链表+红黑树,目的是提高查询和插入效率。

1.7使用头插法,而1.8使用尾插法,因为1.8中插入key和value时要判断链表元素个数,所以正好用尾插法。

1.7哈希算法比较复杂,存在各种异或右移运算,1.8进行了简化,加进红黑树简化哈希算法,节省CPU资源。

说一下Hash Map的put方法?

Put的大体流程:

1:根据key通过哈希算法和与运算得出数组下标;

2:如果数组下标位置元素为空,则将key和value封装为Entry对象,(1.7是Entry,1.8是Node)放入该位置。

3:如果下表位置不为空,分情况讨论:

a:如果是JDK1.7,则会先判断是否需要扩容,如果要进行扩容就进行扩容,否则生成Entry对象用头插法插入当前链表中。

b:如果是JDK1.8,则会先判断当前位置上的Node的类型,看是红黑树Node还是链表Node。

  1. :如果是红黑树Node,则将Key和Value封装成一个红黑树节点并添加到红黑树中去,在这个过程中会判断红黑树是否存在当前key,如果存在则更新value.
  2. :如果此位置上的Node对象是链表节点,则将key和value封装成一个链表Node并通过尾插法插入到最后的位置去,因为是尾插法,所以要遍历整个链表,遍历过程中判断是否存在当前key,存在则更新value,遍历完后,将新节点插入到链表中去,查看节点个数,若大于8,则将链表转为红黑树。
  3. 将key和value封装插入到红黑树或者链表中,判断是否要扩容,不需要则结束put方法。

HashMap的扩容机制?

1.7版本

先生成新数组,

遍历老数组中每个位置上的元素

取每个元素的key,并基于新数组长度,计算每个元素在新数组下标。

将元素添加到新数组。

所有元素转移完了后,将新数组赋值给Hash Map的table属性。

1.8版本

先生成新数组。

遍历每个位置的数组或红黑树

如果是链表,则直接计算下表添加到新数组。

如果是红黑树,先遍历红黑树,计算每个元素在新数组的下标

 a:统计每个下标元素个数

 b:如果该位置元素超过8个,则生成新的红黑树,并将根节点添加到新数组的对应位置

 c:如果元素没有超过8,则生成一个链表,并将链表头节点添加到数组的对应位置

所有元素转移完后,将新数组赋值给HahsMap的table属性。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗着,享受着

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值