Java面试题基础篇(二)

本文详细解析了List、Set、Map等集合类的区别与应用场景,对比了ArrayList与LinkedList、HashMap与Hashtable等实现类的特点,并深入探讨了HashMap与ConcurrentHashMap的工作原理。

集合

14、List, Set和Map 区别
List:
可以允许重复的元素。
可以插入多个null数据。
是一个有序的容器,保持了每一个元素的插入顺序,输出顺序就是插入的顺序。
常用的实现类有ArrayList,LinkedList和Vector,Arraylist使用最为流行,它提供了使用索引的随意访问,而LinkedList则对于经常需要从List中添加或删除元素的场合更为适合。
Set:
不允许有重复的元素。
只允许有一个null元素。
常用的实现类是HashSet,LinkedHashSet和TreeSet,最为流行的是基于HashMap实现HashSet,TreeSet还实现了SortedSet接口,因此TreeSet是一个根据compare()和compareTo()的定义进行排序的有序容器。
Map:
Map 的 每个 Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。
TreeMap 也通过 Comparator  或者 Comparable 维护了一个排序顺序。
Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。
Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)
List,Set,Map的使用场景:
如果经常使用索引访问容器中的元素,那么优先选择List,如果已经知道索引的话,ArrayList可以提供更快速的访问,如果需要经常删除添加元素,那么肯定要选择LinkedList。如果需要容器中的元素按照插入的次序进行有序的存储,还是选择List,因为它是一个有序的容器,按照插入的顺序进行存储。
如果要保证插入元素的唯一性,那么可以选择一个Set的实现类,所有Set的实现类都遵循唯一型约束。Tree还是一个SortedSet,所有存储于 TreeSet 中的元素可以使用 Java 里的 Comparator 或者 Comparable 进行排序。LinkedHashSet 也按照元素的插入顺序对它们进行存储。
如果你以键和值的形式进行数据存储那么 Map 是你正确的选择。你可以根据你的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。

15、Arraylist 与 LinkedList 区别
①ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构;
②对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针;
③对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 


16、ArrayList 与 Vector 区别
Vector是线程安全的,ArrayList不是线程安全的,导致Vector效率无法与ArrayList相比。
Vector和ArrayList都采用线性连续的存储空间,底层都是数组实现的,当存储空间不足时,ArrayList默认增加50%,Vector默认增加原来的一倍。
Vector可以设置capacityIncrement,而ArrayList不可以,从字面理解就是capacity容量,Increment增加,容量增长的参数。

17、HashMap 和 Hashtable 的区别
(1)HashTable是线程安全的,而HashMap则是非线程安全的。HashTable实现方法里面添加了synchronized关键字来确保线程同步,因而相对而言HashMap效率会更高。使用中若无特殊需求建议使用HashMap,在多线程环境中使用Collections.synchronizedMap()方法来获取一个线程安全的集合。
(2)HashMap可以使用null作为key,而HashTable则不允许null作为key
(3)HashMap继承AbstractMap,而HashTable继承Dictionary抽象类,二者均实现Map接口。
(4)HashMap初始容量是16,HashTable初始容量是11,二者的填充因子默认都是0.75。
(5)HashMap扩容时是当前容量翻倍,HashTable扩容时是当前容量翻倍加1。
(6)HashMap和Hashtable的底层实现都是数组+链表结构实现。
(7)两者计算hash的方法不同:HashTable计算hash是直接使用key的hashcode对table数组的长度直接进行取模;HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸

18、HashSet 和 HashMap 区别
(1)HashSet是set的一个实现类,hashMap是Map的一个实现类。
(2)当调用HashSet的add方法时,实际上是向HashMap中增加了一行(key-value对),该行的key就是向HashSet增加的那个对象,该行的value就是一个Object类型的常量。
(3)HashSet以对象作为元素,而HashMap以(key-value)的一组对象作为元素。

19、HashMap 和 ConcurrentHashMap 的区别(参考https://www.cnblogs.com/remember-forget/p/6021644.html)
(1)Hashmap本质是数组加链表。根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面。
(2)ConcurrentHashMap:在hashMap的基础上,ConcurrentHashMap将数据分为多个segment,默认16个(concurrency level),然后每次操作对一个segment加锁,避免多线程锁的几率,提高并发效率。

20、HashMap 的工作原理及代码实现
HashMap概述:
HashMap是基于哈希表的Map接口的实现,此实现提供所有可选的映射操作,并且可以使用null值和健,它不保证该顺序永远不变。HashMap不是线程安全的,如果想要线程安全的HashMap,可以通过Collections类的静态方法synchronizedMap获得线程安全的HashMap。Map map = Collections.synchronizedMap(new HashMap());
HashMap的数据结构
HashMap的底层数据结构是基于数组和链表来实现的,它之所以有相当快的查询速度主要是因为它通过计算散列码来决定存储的位置,能够很快的计算出对象所存储的位置。HashMap主要是通过key的hashCode来计算hash值的,只要hashCode相同,计算出来的hash值就一样。如果存储的对象多了,就有可能不同的对象计算出来的hash值是相同的,出现hash冲突,HashMap中通过链表来解决hash冲突。HashMap底层就是一个数组结构,数组中存放的是一个Entry对象,如果产生hash冲突,也就是说要存储的那个位置上面已经存储了对象了,这时候该位置存储的就是一个链表了。
HashMap源码分析
(1)HashMap初始容量是16,默认加载因子是0.75。加载因子是表示Hash表中元素的填满的程度,加载因子越大,填满的元素越多,空间利用率高,查找成本越小,但是冲突的机会就加大了,反之,加载因子越小,冲突机会减小了,但空间利用率小了,查找成本增大。
(2)构造HashMap的时候如果我们指定了加载因子和初始容量的话就调用第一个构造方法,否则的话就是用默认的。默认初始容量为16,默认加载因子为0.75。通过追踪代码,确保容量为2的n次幂,使capacity为大于initialCapacity的最小的2的n次幂。
(3)当我们往hashmap中put元素的时候,先根据key的hash值得到这个元素在数组中的位置(即下标),然后就可以把这个元素放到对应的位置中了。如果这个元素所在的位子上已经存放有其他元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。从hashmap中get元素时,首先计算key的hashcode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素。


21、ConcurrentHashMap 的工作原理及代码实现
在hashMap的基础上,ConcurrentHashMap将数据分为多个segment,默认16个,然后每次操作对一个segment加锁,避免多线程锁得几率,提高并发效率。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值