2.集合相关

1.Java中的常用容器有哪些?

集合中有两个顶级容器,单列集合Collection,双列结合Map

(1)Collection有三个子接口:List,Set,Queue

List有两个实现类:ArrayList,LinkdList

Set有两个实现类:HashSet,TreeSet

(2)Map有三个实现类:HashMap,TreeMap,HashTable

2.Collection 和Collections 的区别?

Collection

(1)是集合的顶层接口,定义了集合统一的接口方法

(2)Collection中有很多常用的实现类

(3)Collection的意义是为具体的集合提供统一操作方法

(4)直接继承的接口有List和Set和Queue

Collections

(1)是集合的工具类

(2)提供了很多静态方法用于对集合元素进行排序,搜索及线程安全等操作

3.HashMap是线程安全的吗?如何得到一个线程安全的Map?

HashMap是线程不安全的,如果想得到一个线程安全的Map可以选择使用ConcurrentHashMap和

HashTable,或者利用Collections工具类提供的synchronizedMap(map),利用装饰者设计模式,增强

方法来保证线程安全;

4.List和Set的区别?

List和Set都是单列顶层接口Collections的子接口

List特点: (1)有序:数据存取有序

(2)有索引:可以通过索引操作元素

(3)可重复:存储的数据可以重复

(4)底层通常通过线性表(数组,链表)实现,ArrayList基于数组,LinkList基于链表

Set特点: (1)无序:数据存取无序

(2)无索引:set集合没有索引,所以不能通过索引操作元素

(3)不可重复:存储的数据不可以重复

(4)底层通常通过Hash表和二叉搜索树实现,TreeSet基于二叉搜索树,HashSet基于HashMap,但是HashMap基于哈希表,哈希表=数据+链表+红黑树

5.HashMap 和Hashtable 的区别?

(1)Hashtable是线程安全的,而HashMap线程不安全

(2)HashMap允许null键和null值,而Hashtable不允许

6.ArrayList和LinkedList的区别?

(1)底层原理不同,ArrayList底层采用数据实现,采用动态扩容机制,而LinkedList底层基于双向

非循环链表

(2)由于数组在内存中是连续的存储单元,所以导致数组有者用索引查找快和尾部插入快,中间插入

慢的特性,而双向链表可以从头部和尾部操作,所以在中间插入元素慢,头部外部比较快,索引查询慢;

7.HashSet的实现原理

(1)HashSet底层利用HashMap实现

(2)HashSet中的元素存储在HashMap的key

(3)HashMap的value统一采用 private static final Object PRESENT = new Object();

8.如何实现数据和List之间的转换?

(1)List转为数组:调用list里面的toArray()方法

(2)数组转为List:调用Arrays里面的asList(数组)方法

9.ArrayList和Vector的区别?

(1)底层都是基于数组实现

(2)Vector是线程安全的,而ArrayList是线程不安全的,如果需要一个线程安全的ArrayList,一般推荐CopyOnWriteArrayList

(3)Vector扩容两倍,而ArrayList扩容1.5倍

10.Queue中的peek()和poll()方法有什么区别?

(1)peek()查看队列头部元素

(2)poll()出队

11.Iterator和ListIterator有什么区别?

(1)Iterator和ListIterator都是迭代器接口,不同的集合有不同的实现,ListIterator是Iterator的子接口

(2)Iterator可以遍历List也可以遍历Set,因为List和Set中都定义有iterator

ListIterator<E> listIterator();

(3)ListIterator只能遍历List集合,不能遍历Set集合,因为ListIterator只有List中有定义,Set中没有

ListIterator<E> listIterator(int index);

(4)Iterator只能向后遍历,而ListIterator可以向后遍历也可以向前遍历

(5)Iterator中对集合元素的操作只有删除,ListIterator提供了比Iterator功能丰富的方法,获取前一个

元素索引,后一个元素索引,添加元素,替换元素等方法

12.HashMap的底层原理是什么?1.7和1.8有什么区别?

在1.7之前,HashMap底层采用数据+链表,在1.8及之后采用数组+链表+红黑树

13.HashMap存储元素的流程?

(1)当使用put方法存储key value数据,首先获取key的hashCode值

(2)然后对hashCode值进行二次hash,HashMap中的hash方法

(3)对hash值取模数组的长度,得到索引下标(桶下标)

(4)将key value存入到指定索引的链表或者红黑树中

为什么要使用这种方案:提高查询效率,时间复杂度可以到O(1)

14.HashMap什么时候转换成红黑树?

数组长度>=64 && 链表长度>=8 将转换成红黑树

为什么?

因为链表中存储的数量很多,非常影响查询效率

15.HashMap什么时候扩容?

capacity即数组容量,默认16

loadFactor即加载因子,默认是0.75

threshold即阈值,阈值 = 容量*加载因子

当hashMap中的元素超过阈值,就会触发扩容,每次扩容一倍

16.HashMap为什么不直接存放红黑树?

(1)链表短的时候和红黑树的性能差不多;

(2)红黑树的的一个结点要比链表的一个结点占用内存大

(3)如果hash值很随机,按照罗松分布,长度超过8的链表概率为0.00000006,红黑树防止恶意攻击

17.红黑树什么时候退化成链表

(1)情况1:数据扩容,导致数组的拆分,并且拆分后的结点<=6个

(2)情况2:红黑树元素被删除,如果根结点的左子树,右子树,左孙子,右孙子有一个为null,再次删除一

个结点,退化成链表

18.索引如何计算?

(1)调用hashCode方法获取key的hashCode值

(2)对hashCode值再调用HashMap中的hash方法进行二次hash运算

(3)最后使用hash值%数组长度得到索引,等价于hash & (数组长度-1),但是&必须要求数组长度是2的n次方

19.索引计算为何要进行二次hash的结果计算索引

桶:链表或者红黑树存着的地方

(1)将hash的分布更均匀,将添加的元素能更平均的分配到hash表中,不至于某些桶中元素过多

20.HashMap数组长度为何是2的n次幂

(1)计算索引的时候,可以不用取模运算,采用位运算提高效率

(2)扩容的时候所有元素重新计算索引位置,hash&原始容量 = 0留在原位置,否则换到新位置

新位置 = 原始位置 + 原始容量

21.HashMap1.7和1.8添加元素的区别

(1)1.7

元素采用头插入,就是链表新元素在老元素的上面

在插入新数据时,超过阈值并且没用空位置触发扩容

(2)1.8

在第一次put的时候创建数组

计算索引

如果索引位置是null,创建node(链表结点),存放到索引位置

如果索引位置不是null,如果是node,走链表添加的逻辑,如果是treeNode,走树化的逻辑

添加完毕后判断元素的个数是否超过阈值,如果超过阈值,进行数组扩容,扩容为原来的两倍

22.扩容因子为何是0.75?

(1)大于0.75节省空间,但是链表长度可能会比较长

(2)小于0.75,扩容会比较频繁,占用内存空间会比较大

23.多线程下操作HashMap会引发什么问题?

(1)数据错乱,后面添加的数据将前面添加的数据覆盖

(2)并发死链

24.HashMap为什么要求key重写hashCode和equals方法?

(1)重写的目标

两个对象HashCode相同但equals不一定相同,但equals相同hashCode一定相同

(2)为什么

Map要求key不能相同,如何判断key已经存在呢?

通过key的hash值计算桶索引,如果桶索引位置没有元素,key一定不存在,如果桶索引位置有元素,判

断添加的key和已经存在的key的hash是否相同,不相同则不存在,如果相同,在使用equals判断,如果相同则存在,不相同则不存在.

25.Integer,Dubble,Float,String这些类的hashCode是如何重写?

(1)Integer的hashCode方法实现比较简单,直接以对应的int值作为hash值。

(2)String上面代码中的hash的定义(hash值),value的定义(String对应的char数组)

(3)Double通俗的讲就是将Double的前32位与后32位进行异或后得到hash值

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值