1.常见的集合有哪些?
Collection接口的子接口:Set接口和List接口
Map接口的实现类主要有:HashMap、TreeMap、HashTable、ConcurrontHashMap、Properties等
Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等
List接口的实现类主要有:ArrayList、LinkedList、Stact、Vector等
2.常见的集合底层实现
ArrayList的底层实现是数组;
LinkedList底层实现是双向链表;
HashMap和HashTable的原理相同,java8版本之后如果同一位置哈希冲突大于8则链表变成红黑树
HashTable底层是链地址法组成的哈希表(即数组+单向链表组成)
HashSet底层是HashMap
LinkedHashMap底层修改自HashMap,包含一个维护插入顺序的双向链表
TreeMap的底层是红黑树
LinkedHashSet底层是LinkedHashMap
TreeSet底层是treeMap
3.HashMap和HashTable的区别
HashMap没有考虑同步,是线程不安全的;HashTable使用了Synchronized关键字,是线程安全的;HashMap允许K/V都为null;HashTable不允许。
4.ConcurrontHashMap和HashTable的区别?
ConcurrontHashMap结合了HashMap和HashTable的优势,HashMap没有考虑同步,HashTable考虑了同步的问题。但是HashTable在每次同步执行时都要锁住整个结构。ConcurrontHashMap锁的方式是稍微细粒度的
5.ConcurrontHashMap的实现原理
jdk1.7 :【数组(Segment) + 数组(HashEntity) + 链表(HashEntity节点)】
ConcurrontHashMap(分段锁)对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率
Segment是一种可重入锁ReentrantLock,在ConcurrontHashMap里扮演锁的角色,HashEntity则用于存储键值对数据。
jdk1.8 :Node数组+链表 / 红黑树
利用CAS+Synchronized来保证并发更新的安全,底层依然采用数组+链表+红黑树的存储结构
6.ArrayList和Vector的区别
Vector是线程安全的,ArrayuList是线程不安全的
Vector在数组满时增长为原来的两倍,而ArrayList在数组达到容量的一半时,增长为原来的1.5倍
7.ArrayList和LinkedList的区别
linkedList是基于链表的数据结构;ArrayList是基于数组的数据结构;LinkedList在插入和删除时效率更高,ArrayList的查询效率更高
8.HashMap的默认初始化长度是多少?
在jdk中默认长度是16,并且默认长度和扩容后的长度都是2的幂次方
9.谈谈对HashMap构造方法中初始容量、加载因子的理解
初始容量代表了哈希表中桶的初始数量,即Entity<K,V>[] table的初始长度
加载因子是哈希表在其容器自动增加之前可以达到多满的一种饱和度百分比,其衡量了一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之俞小
10.java集合框架是什么,说出一些集合框架的优点?
每种编程语言中都有集合,最初的java版本包含集中集合类:Vector、Stark、HashTable、Array。随着集合的广泛使用,java1.2提出了囊括所有集合接口、实现和算法的集合框架。在保证线程安全的情况下使用泛型和并发集合类,java已经经历了很久,它还包括在java并发包中,阻塞接口以及他们的实现。集合框架的部分有点如下:
(1)使用核心集合类降低开发成本,而非实现我们自己的集合类
(2)随着使用经过严格测试的集合框架类,代码质量会提高
(3)通过使用jdk附带的集合类,可以降低代码维护成本
11.集合框架中的泛型有什么优点?
java1.5引入了泛型,所有的集合接口和实现都大量使用。泛型允许我们为集合提供一个可以容纳的对象类型,因此,如果你添加其他类型的任何元素,他会在编译期报错。这避免了在运行时出现ClassCastException,因为你将会在编译时得到报错信息。泛型也使得代码整洁,我们不需要使用显示转换和instanceOf操作符。它也会给运行时带来好处,因为不会产生类型检查的字节码指令。
12.为何Collection不从Cloneable和Serializable接口继承?
Collection指定一组对象,对象即为他的元素。如何维护这些元素有Collection的具体实现决定。例如,一些如List的Collection实现允许重复的元素,而其他的如Set就不允许。很多Collection实现有一个共有的clone()方法。然而,把它放到集合的所有实现中也是没有意义的,这是因为Collection是一个抽象表现,重要的是实现。
当与具体实现打交道时,克隆或序列化的含义才会发挥作用,所以,具体实现,应该决定如何对他进行克隆或者序列化,或它是否可以被克隆或序列化。
在所有的实现中授权克隆和序列化,最终导致更少的灵活性和更多的限制。特定的实现应该决定它是否可以被克隆和序列化。
13.为何Map接口不继承Collection接口?
尽管Map接口和他的实现也是集合框架的一部分,但Map不是集合,集合也不是Map;因此,Map继承Collection毫无意义,反之亦然。如果Map继承Collection接口,那么元素去哪儿?Map包含key-value对,他提供抽取key或value列表集合的方法,但是他不适合“一组对象”规范。
14.Iterator是什么?
Iterator提供遍历任何Collection的接口。我们可以从一个Collection中使用迭代器方法来获取迭代器实例。迭代器取代了java集合框架的Enumeration。迭代器允许调用者在迭代过程中移除元素。
15.Enumeration和Iterator接口的区别?
Enumeration的速度是Iterator的两倍,也是用更少的内存。Enumeration是非常基础的,也满足了基础的需要。但是与Enumeration相比,Iterator更安全,因为当一个集合正在被遍历的时候,他会阻止其他线程去修改集合。
迭代器取代了java集合中的Enumeration。迭代器允许调用者在迭代过程中移除元素,而Enumeration不能做到。为了是他的更能更加清晰,迭代器方法名已经经过改善。
16.Iterator和ListIterator之间的区别?
(1)我们可以使用Iterator来遍历Set和List集合,而ListIterator只能遍历List。
(2)Iterator只可以向前遍历,而ListIterator可以双向遍历。
(3)ListIterator从Iterator接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
17.fail-fast与fail-safe有什么区别?
Iterator的fail-fast属性与当前的集合共同起作用,因此他不会受到集合中任何改动的影响。java.util包中的所有集合类都被设计为fail-fast的,而java.util.concurront中的集合类都是fail-safe的。fail-dast迭代器抛出ConcurrontModifactionException,而fail-safe从不抛出concurrontModifcationException。
18.hashCode()和equals()方法有何重要性?
HashMap使用Key对象的HashCode()和equals() 方法去决定key-value对的索引。当我们试着从hashMap中获取值的时候,这些方法也会被用到。如果这些方法没有被正确的实现,在这种情况下,两个不同key也许会产生相同的hashCode()和equals()输出,HashMap将会认为他们是相同的,然后覆盖他们,而非把他们存储到不同的地方。同样的,所有不允许存储重复数据的集合类都使用hashCode()和equals()去查找重复,所以正确实现他们非常重要。
equals()和hashCode()的实现应该遵循以下规则:
(1)如果o1.equals(o2) 为true,那么o1.hashCode() == o2.hashCode() 总是为true
(2)如果o1.hashCode() == o2.hashCode(),并不意味着o1.equals(o2) 会为true
19.我们能否用任何类做map的key?
我们可以使用任何类作为map的key,然而在使用之前,需要考虑以下几点:
(1)如果类重写了equals()方法,它也应该重写hashCode()方法;
(2)类的所有实例需要遵循与equals()和hashCode()相关的规则;
(3)如果一个类中没有使用equals()方法,你就不应该在hashCode()中使用它。
(4)用户定义key类的最佳实践是使之为不可变的,这样,hashCode()值可以被缓存起来,拥有更好的性能。不可变的类也可以确保hashCode()和equals()在未来不会变,这样就会解决与可变相关 的问题了。
20.如何选用HashMap或TreeMap?
对于在map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是最好的选择。基于你的Collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。
21.哪些集合类提供对元素的随机访问?
ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问
22.BlockingQueue是什么?
Java.util.concurrent.BlockingQueue是一个队列,在进行检索或移除一个元素的时候,它会等待队列变为非空; 当在添加一个元素时,它会等待队列中的可用空间。BlockingQueue接口是Java集合框架的一部分,主要用于实现生产者-消费者模式。 我们不需要担心等待生产者有可用的空间,或消费者有可用的对象,因为它都在BlockingQueue的实现类中被处理了。 Java提供了集中BlockingQueue的实现,比如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue等。
23.队列和栈是什么,列出他们的区别?
栈和队列两个都被用来预存储数据。java.util.Queue是一个接口,他的实现类在java的并发包中。队列允许先进先出(FIFO)检索元素,但并非总是这样,Deque接口允许从两端检索元素。
栈与队列很相似,但它允许对元素进行后进先出(LIFO)进行检索。
Stack是一个扩展自Vector的类,而Queue是一个接口。
24.Collections类是什么?
java.util.Collections是一个工具类仅包含静态方法,他们操作或返回集合。它包含操作集合的多态算法,返回一个由指定集合支持的新集合和其他一些内容,这个类包含集合框架算法的方法,比如折半搜索、排序、混编和逆序等。
25.Comparable和Comparator接口有何区别?
Comparable和Comparator接口被用来对对象集合或者数组进行排序。Comparable接口被用来提供对象的自然排序,我们可以使用它来提供基于单个逻辑的排序。
Comparator接口被用来提供不同的排序算法,我们可以选择需要使用Comparator来对给定的对象集合进行排序。