合集1.List、Map、Set这三个接口访问元素时,各自有什么特点?列表访问具有特定索引的元素,并且可以有重复的元素。Set不能存储重复的元素(使用对象的equals()方法来区分元素是否重复)。Map保存的是键值对(key-valuepair)映射关系,映射关系可以是一对一,也可以是多对一。Set和Map容器都有基于哈希存储和排序树的两个实现版本。基于哈希存储的版本理论上访问时间复杂度为O(1),而基于排序树版本的实现是插入或删除元素。会根据元素或者元素的key构建排序树,达到排序去重的效果。2、ArrayList、Vector、LinkedList的存储性能和特点ArrayList和Vector都是使用数组来存储数据。该数组的元素个数大于实际存储的添加和插入元素的数据。它们都允许直接通过序号索引元素,但是插入元素会涉及到数组元素移动等内存操作,所以查询数据快而插入数据慢。Vector中的方法加上了synchronized修饰,所以Vector是线程安全的容器,但是性能比ArrayList差,所以在Java中已经是遗留物了。容器。LinkedList采用双向链表进行存储(通过附加引用将内存中分散的内存单元关联起来,形成一个可以按序号索引的线性结构。与数组的连续存储方式相比,这种链式存储方式具有更高的memoryutilizationHigher),按序号索引数据需要向前或向后遍历,但插入数据时只需要记录此项的前后项,因此插入速度较快。Vector是遗留容器(Java早期版本提供的容器,另外,Hashtable、Dictionary、BitSet、Stack、Properties都是遗留容器),不推荐使用,但是因为ArrayList和LinkedListed都是非线程安全的,如果遇到多个线程操作同一个容器的场景,可以使用工具类Collections中的synchronizedList方法将其转化为线程安全的容器再使用(这就是装饰模式的应用),将现有对象传递给另一个在类的构造函数中创建新对象以增强实现)。3.List、Set、Map是否继承自Collection接口List,Set是,Map否。Map是一个键值对映射容器,与List、Set有明显区别。Set存储的是分散的元素,不允许有重复的元素(数学中的集合也是如此)。List是线性结构的容器,适用于通过索引访问元素的情况。4.Collection和Collections的区别Collection是集合类的上层接口。它的继承和接口主要有Set和List。Collections是集合类的辅助类。它提供了一系列静态方法来实现各种集合的查找、排序、线程安全等操作。5.ArrayList和LinkedListArrayList和LinkedList都实现了List接口。它们有以下区别:ArrayList是一个基于索引的数据接口,它的底层是一个数组。它可以对具有O(1)时间复杂度的元素执行随机访问。相应地,LinkedList以元素列表的形式存储其数据,每个元素与其上一个和下一个元素链接。在这种情况下,查找元素的时间复杂度为O(n)。与ArrayList相比,LinkedList的插入、添加、删除操作更快,因为当元素添加到集合中的任意位置时,不需要像数组那样重新计算大小或更新索引。LinkedList比ArrayList占用更多的内存,因为LinkedList为每个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。6、HashMap和HashtableHashMap和Hashtable都实现了Map接口,所以很多特性非常相似。但是,它们有以下区别:HashMap允许键和值都为null,而Hashtable不允许键或值为null。Hashtable是同步的,而HashMap不是。所以HashMap更适合单线程环境,而Hashtable适合多线程环境。HashMap提供了一个可以被应用程序迭代的键集合,因此,HashMap是快速失败的。另一方面,Hashtable提供了键的枚举(Enumeration)。Hashtable通常被认为是遗留类。7、快速失败(fail-fast)和安全失败(fail-safe)快速失败(fail-fast)用迭代器遍历一个集合对象时,如果集合对象的内容被修改(增删改查等),modification),并发修改异常将被抛出。原理:迭代器遍历时直接访问集合的内容,遍历时使用一个modCount变量。如果在遍历过程中集合的内容发生变化,则modCount的值也会发生变化。每当迭代器在遍历下一个元素之前使用hashNext()/next()时,它会检查modCount变量是否为预期的modCount值,如果是则返回遍历;否则,抛出异常并终止遍历。注意:这里抛出的异常是检测modCount!=expectedmodCount这个条件。如果在集合发生变化时修改后的modCount值只是设置为expectedmodCount值,则不会抛出异常。因此,您不能根据是否抛出此异常来编写并发操作。此异常仅建议用于检测并发修改错误。场景:java.util包下的集合类failfast,多线程下不能并发修改(迭代修改)。安全失效(fail-safe)是一种采用安全失效机制的集合容器。遍历时,不直接访问集合内容,而是先复制原始集合内容,在复制的集合上遍历。原理:由于迭代时遍历的是原集合的副本,遍历过程中对原集合所做的修改无法被迭代器检测到,因此不会触发ConcurrentModificationException。缺点:复制内容的好处是避免了ConcurrentModificationException,但同样,迭代器无法访问修改后的内容,即迭代器遍历的是开始遍历那一刻得到的集合的副本。在遍历过程中,原始迭代器不知道集合的变化。场景:java.util.concurrent包下的容器是safetofail,可以在多线程下并发使用和修改。Iterator的故障保护基于制作底层集合的副本,因此它不受源集合修改的影响。java.util包下的所有集合类都是fail-fast,java.util.concurrent包下的所有类都是fail-safe。快速失败迭代器将抛出ConcurrentModificationException,而失败安全迭代器永远不会抛出此类异常。8、Iterator和ListIterator的区别Iterator可以用来遍历Set和List集合,而ListIterator只能用来遍历List。Iterator只能向前遍历集合,ListIterator可以向前也可以向后。ListIterator实现了Iterator接口并包含了其他功能,例如:添加元素、替换元素、获取上一个元素和下一个元素的索引等。9.什么是迭代器?Iterator提供了统一的接口,以统一的方式遍历集合元素。Collection接口实现了Iterable接口。每个集合通过实现Iterable接口中的iterator()方法返回一个Iterator接口的实例,然后迭代集合中的元素。手术。注意:在迭代元素时,不能通过collection方法删除元素,否则会抛出ConcurrentModificationException。但是,您可以通过Iterator接口中的remove()方法删除它们。10、为什么集合类没有实现Cloneable和Serializable接口克隆?克隆(cloning)或序列化(serialization)的语义和意义与具体实现有关。因此,如何克隆或序列化,应该由集合类的具体实现类来决定。实现Serializable序列化的作用:将对象的状态保存在存储介质中,以便以后可以重写创建一个完全相同的副本;按值将对象从一个应用程序域发送到另一个应用程序域。实现Serializable接口的作用是将对象保存到字节流中,然后再恢复。所以你想如果你的对象没有被序列化,怎么通过网络传输呢?对于网络传输,必须要转换成字节流,所以在分布式应用中,就得实现序列化。如果您不需要分布式应用程序,则无需实现序列化。11、ConcurrentHashMapConcurrentHashMap是HashMap的线程安全版本,支持高效并发。在默认的理想状态下,ConcurrentHashMap可以支持16个线程进行任意数量的线程并发写操作和读操作。ConcurrentHashMap类包含两个静态内部类HashEntry和Segment。HashEntry用于封装映射表的key/value对;Segment用来充当一把锁,每个Segment对象守护着整个哈希映射表的几个bucket。每个桶都是一个由多个HashEntry对象链接的链表。ConcurrentHashMap实例包含多个Segment对象的数组。HashEntry用于封装哈希映射中的键值对。在HashEntry类中,key、hash和next字段都声明为final,value字段声明为volatile。staticfinalclassHashEntry
