当前位置: 首页>后端>正文

集合三兄弟List,Set,Map傻傻理不清?掌握诀窍面面俱到

前言:

作为Java基础知识的核心部分,集合方面是面试时的重中之重,List、Set、map等相信大家都不会陌生,当然面试官也不会从简单的问题出发,因为他也已经问吐了,今天就聊一下集合在面试中的高级部分,别再傻傻分不清了!

集合三兄弟List,Set,Map傻傻理不清?掌握诀窍面面俱到,第1张
集合三兄弟List,Set,Map傻傻理不清?掌握诀窍面面俱到,第2张

第 1 种,普通 for 循环随机访问,通过索引值去遍历。

// 随机访问Listlist=newArrayList<>();intsize =list.size();for(inti =0; i < size; i++) {? ? ? ? value =list.get(i);? ? }

第 2 种,通过迭代器遍历。即通过 Iterator 去遍历。

// 迭代器遍历Iterator iter = list.iterator();while(iter.hasNext()) {? ? ? ? value = iter.next();? ? }

第 3 种,增强 for 循环遍历。

// 增强 for 循环for(String s :list) {? ? ? ? value = s;? ? }

第 4 种 forEach + lambda 循环遍历

list.forEach(p -> {? ? ? ? ? ? ? ? p.hashCode();? ? ? ? ? ? });

四种遍历比较

如果数据量比较少的话貌似四种循环耗时都差不多,但是随着数据量的增长会发现 foreach 的效率是最好的。但是从上面我们会发现一个奇怪的现象,第一次循环的时候forEach遍历的时间是最长的尽管数据量非常少也会这样。但是后面的耗时就正常了。如果放开测试里面的预热代码,每次跑出来的耗时也是正常的。

三、ArrayList和LinkedList的底层实现原理?他们为什么线程不安全?在多线程并发操作下,我们应该用什么替代?

1.ArrayList底层通过数组实现,ArrayList允许按序号索引元素,而插入元素需要对数组进行移位等内存操作,所以索引快插入较慢;(扩容方式)一旦我们实例化了ArrayList无参构造函数默认数组长度为10。add方法底层如果增加的元素超过了10个,那么ArrayList底层会生成一个新的数组,长度为原来数组长度的1.5倍+1,然后将原数组内容复制到新数组中,并且后续加的内容都会放到新数组中。当新数组无法容纳增加元素时,重复该过程;

2.LinkedList底层通过双向链表实现,取元素时需要进行前项或后项的遍历,插入元素时只需要记录本项的前后项即可,所以插入快查询慢;

3.ArrayList和LinkedList底层方法都没有加synchronized关键词,多线程访问时会出现多个线程先后更改数据造成得到的数据是脏数据;多线程并发操作下使用Vector来代替,Vector底层也是数组,但底层方法都加synchronized关键字使线程安全,效率较ArrayList差;

四、HashMap和HashTable有什么区别?其底层实现是什么?CurrentHashMap的锁机制又是如何?如果想将一个Map变为有序的,该如何实现?

1.区别:

(1)HashMap没有实现synchronized线程非安全,HashTable实现了synchronized线程安全;

(2)HashMap允许key和value为null,而HashTable不允许

2.底层原理:数组+链表实现

3.ConcurrentHashMap锁分段技术:HashTable效率低下的原因,是因为所访问HashTable的线程都必须竞争同一把锁,那假如容器中有多把锁,每一把锁用于锁住容器中的一部分数据,那么当多线程访问容器中不同的数据时,线程间就不会存在锁竞争,从而提高并发访问率;ConcurrentHashMap使用的就是锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个数据时,其他段的数据也能被其他线程访问;

4.实现TreeMap

五.ArryList 注意点

谨慎使用 ArrayList 中的 subList 方法

ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异常,即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList. 说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。

Listlist=newArrayList<>();list.add("1");list.add("1");list.add("2");? ? ? ? ArrayList strings =? (ArrayList)list.subList(0,1);运行结果:Exceptionin thread"main"java.lang.ClassCastException: java.util.ArrayList$SubList cannot be cast to java.util.ArrayList? at com.workit.demo.listener.ArrayListTest.main(ArrayListTest.java:29)

在 subList 场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、 删除均会产 ConcurrentModificationException 异常。

Listlist=newArrayList<>();list.add("1");list.add("1");list.add("2");List subList =list.subList(0,1);// 对原 List 增加一个值list.add("10");? ? ? ? subList.add("11");// 这一行会报 java.util.ConcurrentModificationException

初始化 List 的时候尽量指定它的容量大小。(尽量减少扩容次数)

最后:

针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。

下面的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2020收集的一些大厂的面试真题(都整理成文档,小部分截图),有需要的可以私信我【Java】

集合三兄弟List,Set,Map傻傻理不清?掌握诀窍面面俱到,第3张

https://www.xamrdz.com/backend/38f1941290.html

相关文章: