一、常见集合
Map接口和Collection接口是所有集合框架的父接口
1、Collection接口是集合类的根接口
Java中没有提供这个接口的直接的实现类,但是却让其被继承产生了两个接口,就是Set和List
Set 中不能包含重复的元素
List 是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式
2、Map是Java.util包中的另一个接口
Map接口和Collection接口没有关系,是相互独立的,但是都属于集合类的一部分
Map包含了key-value对。Map不能包含重复的key,但是可以包含相同的value
3、Iterator
所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含以下三种方法:
(1)hasNext()是否还有下一个元素
(2)next()返回下一个元素
(3)remove()删除当前元素
1、Collection接口的子接口包括:Set接口和List接口
Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等
List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等
2、Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及
Properties等
二、Map、List、Set接口和类简介
1、List(有序、可重复)
List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。
2、Set(无序、不能重复)
Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。
3、Map(键值对、键唯一、值不唯一)
Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。
对比如下:
三、常见的集合底层实现
ArrayList底层是数组。
LinkedList底层是双向链表。
HashMap底层与HashTable原理相同,Java 8版本以后如果同一位置哈希冲突大于8则链表
变成红黑树。
HashTable底层是链地址法组成的哈希表(即数组+单项链表组成)。
HashSet底层是HashMap。
LinkedHashMap底层修改自HashMap,包含一个维护插入顺序的双向链表。
TreeMap底层是红黑树。
LinkedHashSet底层是LinkedHashMap。
TreeSet底层是TreeMap。
四、HashMap与HashTable的区别
HashMap没有考虑同步,是线程不安全的;Hashtable使用了synchronized关键字,是线程安全的
HashMap允许K/V都为null;后者K/V都不允许为null
五、ConcurrentHashMap和Hashtable的区别
ConcurrentHashMap 结合了 HashMap 和 HashTable 二者的优势。HashMap 没有考虑同
步,HashTable 考虑了同步的问题。但是 HashTable 在每次同步执行时都要锁住整个结构。
ConcurrentHashMap 锁的方式是稍微细粒度的
六、ConcurrentHashMap实现原理
JDK1.7 : 【数组(Segment) + 数组(HashEntry) + 链表(HashEntry节点)】
ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁
容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访
问率。
Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,
HashEntry则用于存储键值对数据。
JDK1.8 : Node数组+链表 / 红黑树
利用CAS+Synchronized来保证并发更新的安全,底层依然采用数组+链表+红黑树的存储结
构
七、ArrayList 和 Vector 的区别
Vector 是线程安全的,ArrayList 是线程不安全的。
Vector在数据满时增长为原来的两倍,而 ArrayList在数据量达到容量的一半时,增长为原容量
的1.5倍。
八、ArrayList和LinkedList的区别
LinkedList基于链表的数据结构;ArrayList基于动态数组的数据结构
LinkedList 在插入和删除数据时效率更高,ArrayList 查询效率更高
九、HashMap 默认的初始化长度是多少
在JDK中默认长度是16,并且默认长度和扩容后的长度都必须是 2 的幂
十、Java集合框架
每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector、Stack、HashTable和
Array。随着集合的广泛使用,Java1.2提出了囊括所有集合接口、实现和算法的集合框架。在
保证线程安全的情况下使用泛型和并发集合类,Java已经经历了很久。它还包括在Java并发包
中,阻塞接口以及它们的实现。集合框架的部分优点如下:
(1)使用核心集合类降低开发成本,而非实现我们自己的集合类。
(2)随着使用经过严格测试的集合框架类,代码质量会得到提高。
(3)通过使用JDK附带的集合类,可以降低代码维护成本。
(4)复用性和可操作性。
十一、集合框架中的泛型
Java1.5引入了泛型,所有的集合接口和实现都大量地使用它。泛型允许我们为集合提供一个可
以容纳的对象类型,因此,如果你添加其它类型的任何元素,它会在编译时报错。这避免了在
运行时出现ClassCastException,因为你将会在编译时得到报错信息。泛型也使得代码整
洁,我们不需要使用显式转换和instanceOf操作符。它也给运行时带来好处,因为不会产生类
型检查的字节码指令
十二、Collection不从Cloneable和Serializable接口继承
Collection接口指定一组对象,对象即为它的元素。如何维护这些元素由Collection的具体实
现决定。例如,一些如List的Collection实现允许重复的元素,而其它的如Set就不允许。很多
Collection实现有一个公有的clone方法。然而,把它放到集合的所有实现中也是没有意义
的。这是因为Collection是一个抽象表现。重要的是实现。
当与具体实现打交道的时候,克隆或序列化的语义和含义才发挥作用。所以,具体实现应该决
定如何对它进行克隆或序列化,或它是否可以被克隆或序列化。
在所有的实现中授权克隆和序列化,最终导致更少的灵活性和更多的限制。特定的实现应该决
定它是否可以被克隆和序列化
十三、Map接口不继承Collection接口
尽管Map接口和它的实现也是集合框架的一部分,但Map不是集合,集合也不是Map。因此,
Map继承Collection毫无意义,反之亦然。
如果Map继承Collection接口,那么元素去哪儿?Map包含key-value对,它提供抽取key或
value列表集合的方法,但是它不适合“一组对象”规范。
十四、Iterator
Iterator接口提供遍历任何Collection的接口。我们可以从一个Collection中使用迭代器方法
来获取迭代器实例。迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者在迭
代过程中移除元素
十五、Enumeration和Iterator接口的区别
Enumeration的速度是Iterator的两倍,也使用更少的内存。Enumeration是非常基础的,
也满足了基础的需要。但是,与Enumeration相比,Iterator更加安全,因为当一个集合正在
被遍历的时候,它会阻止其它线程去修改集合。
迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者从集合中移除元素,而
Enumeration不能做到。为了使它的功能更加清晰,迭代器方法名已经经过改善
十六、Iterater和ListIterator之间区别
(1)我们可以使用Iterator来遍历Set和List集合,而ListIterator只能遍历List。
(2)Iterator只可以向前遍历,而LIstIterator可以双向遍历。
(3)ListIterator从Iterator接口继承,然后添加了一些额外的功能,比如添加一个元素、替
换一个元素、获取前面或后面元素的索引位置
十七、hashCode()和equals()方法
HashMap使用Key对象的hashCode()和equals()方法去决定key-value对的索引。当我们试
着从HashMap中获取值的时候,这些方法也会被用到。如果这些方法没有被正确地实现,在
这种情况下,两个不同Key也许会产生相同的hashCode()和equals()输出,HashMap将会认
为它们是相同的,然后覆盖它们,而非把它们存储到不同的地方。同样的,所有不允许存储重
复数据的集合类都使用hashCode()和equals()去查找重复,所以正确实现它们非常重要。
equals()和hashCode()的实现应该遵循以下规则:
(1)如果o1.equals(o2),那么o1.hashCode() == o2.hashCode()总是为true的。
(2)如果o1.hashCode() == o2.hashCode(),并不意味着o1.equals(o2)会为true。
十八、能否使用任何类作为Map的key
我们可以使用任何类作为Map的key,然而在使用它们之前,需要考虑以下几点:
(1)如果类重写了equals()方法,它也应该重写hashCode()方法。
(2)类的所有实例需要遵循与equals()和hashCode()相关的规则。请参考之前提到的这些规
则。
(3)如果一个类没有使用equals(),你不应该在hashCode()中使用它。
(4)用户自定义key类的最佳实践是使之为不可变的,这样,hashCode()值可以被缓存起
来,拥有更好的性能。不可变的类也可以确保hashCode()和equals()在未来不会改变,这样
就会解决与可变相关的问题了
十九、选用HashMap还是TreeMap
对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要
对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许
向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历
二十、哪些集合类提供对元素的随机访问?
ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问
二十一、队列和栈区别
栈和队列两者都被用来预存储数据。java.util.Queue是一个接口,它的实现类在Java并发包
中。队列允许先进先出(FIFO)检索元素,但并非总是这样。Deque接口允许从两端检索元
素。
栈与队列很相似,但它允许对元素进行后进先出(LIFO)进行检索。
Stack是一个扩展自Vector的类,而Queue是一个接口
二十二、Collections类
Java.util.Collections是一个工具类仅包含静态方法,它们操作或返回集合。它包含操作集合
的多态算法,返回一个由指定集合支持的新集合和其它一些内容。这个类包含集合框架算法的
方法,比如折半搜索、排序、混编和逆序等
二十三、Comparable和Comparator接口区别
Comparable和Comparator接口被用来对对象集合或者数组进行排序。Comparable接口被
用来提供对象的自然排序,我们可以使用它来提供基于单个逻辑的排序。
Comparator接口被用来提供不同的排序算法,我们可以选择需要使用的Comparator来对给
定的对象集合进行排序