Java面试八股文-集合篇

目录

1、三大集合的区别是什么?/介绍一下集合

2、ArrayList和LinkedList的区别是什么?

3、ArrayList和LinkedList使用场景

4、ArrayList如何去重?

5、HashMap的底层原理实现

6、HashMap和LinkedHashMap的区别

7、HashMap和Hashtable的区别

8、ConcurrentHashMap和Hashtable的区别

9、ConcurrentHashMap为什么是线程安全的?/ConcurrentHashMap线程安全的具体实现方式/底层具体实现/有没有了解过线程安全的HashMap?

10、Hashtable也是线程安全的,为什么不推荐使用Hashtable呢?

11、HashMap底层为什么要用红黑树呢?为什么不用平衡二叉树?

12、HashMap是线程安全的吗?为什么呢?

13、HashMap线程不安全会出现什么问题?

14、HashMap在遇到key冲突的时候是怎么处理的呢?

15、HashMap的遍历方式

16、HashMap什么时候退回回链表?

17、集合框架中的线程安全类你知道哪些?

18、Collection和Collections的区别是什么?


1、三大集合的区别是什么?/介绍一下集合

  • Collection

    • List:存储的元素是有序的、可重复的。

      • ArrayList

      • LinkedList

      • Vector

    • Set:存储的元素是无序的、不可重复的。

      • HashSet

        • LinkedHashSet

      • TreeSet

  • Map:使用键值对(key-value)存储,key是无序的、不可重复的,value是无序的、可重复的,每个键最多映射到一个值。

    • HashMap

    • TreeMap

    • Hashtable

2、ArrayList和LinkedList的区别是什么?

  • ArrayList和LinkedList都是线程不安全的

  • Arraylist底层使用的是Object数组,支持随机访问;LinkedList底层使用的是双向链表数据结构,不支持随机访问

  • 使用下标访问一个元素,ArrayList的时间复杂度是O(1),而LinkedList是O(n)。

3、ArrayList和LinkedList使用场景

  • 如果应用程序对数据有较多的随机访问,ArrayList对象要优于LinkedList对象。

  • 如果应用程序有更多的插入或者删除操作,较少的随机访问,LinkedList对象要优于ArrayList对象。

  • 不过如果在List靠近末尾的地方插入,那么ArrayList只需要移动较少的数据,而LinkedList则需要一直查找到列表尾部,反而耗费较多时间,这时ArrayList就比LinkedList要快。

4、ArrayList如何去重?

  • 利用HashSet唯一性的特点对ArrayList进行去重

  • 使用HashSet去重后会影响元素原有的位置,可以替换为LinkedHashSet保持元素原来的顺序

HashSet<String> objects = new HashSet<>(arr1);
//或
LinkedHashSet<Integer> hashSet = new LinkedHashSet<>(arr1);
  • 使用java8新特性stream进行List去重

  • 使用steam的distinct()方法返回一个由不同数据组成的流,通过对象的equals()方法进行比较。

List<Integer> listWithoutDuplicates = numbersList.stream().distinct().collect(Collectors.toList());
  • 利用List的contains方法循环遍历,重新排序,只添加一次数据,避免重复

for (String str : list) {
    if (!result.contains(str)) {
        result.add(str);
    }
}
  • 双重for循环去重

for (int i = 0; i < list.size(); i++) { 
    for (int j = 0; j < list.size(); j++) { 
        if(i!=j&&list.get(i)==list.get(j)) { 
            list.remove(list.get(j)); 
        } 
    } 
}

5、HashMap的底层原理实现

HashMap在jdk7中实现原理:

  • 在实例化以后,底层创建了长度是16的一维数组Entry[]table。

  • 首先,调用key所在类的hashCode()计算key的哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。

  • 如果这个位置上的数据为空,此时的key-value添加成功。----情况1

  • 如果这个位置上的数据不为空,意味着这个位置上以链表的形式存在一个或多个数据,比较key和已经存在的一个或多个数据的哈希值:

    • 如果key的哈希值与已经存在的数据的哈希值都不相同,这时key-value添加成功。----情况2

    • 如果key的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,调用key所在类的equals(key2)方法比较:

      • 如果equals()返回false:此时key-value添加成功。----情况3

      • 如果equals()返回true:使用value替换value2。

  • 补充:关于情况2和情况3:此时key-value和原来的数据以链表的方式存储。

  • 在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空)时,扩容。默认的扩容方式:扩容为原来容量的2倍,并将原来的数据复制过来。

HashMap在jdk8中相较于jdk7在底层实现方面的不同:

  • newHashMap():

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值