文章目录
- 集合容器概述
- Collection接口
-
- List接口
-
- 1、迭代器 Iterator 是什么?
- 2、Iterator 怎么使用?有什么特点?
- 3、如何边遍历边移除 Collection 中的元素?
- 4、Iterator 和 ListIterator 有什么区别?
- 5、遍历一个 List 有哪些不同的方式?Java 中 List 遍历的最佳实践是什么?
- 6、说一下 ArrayList 的优缺点
- 7、如何实现数组和 List 之间的转换?
- 8、ArrayList 和 LinkedList 的区别是什么?
- 9、ArrayList 和 Vector 的区别是什么?
- 10、多线程场景下如何使用 ArrayList?
- 11、为什么 ArrayList 的 elementData 加上 transient 修饰?
- 12、List 和 Set 的区别
- Set接口
- Queue
- Map接口
-
-
- 1、说一下 HashMap 的实现原理?
- 2、HashMap在JDK1.7和JDK1.8中有哪些不同?HashMap的底层实现
- 3、HashMap的put方法的具体流程?
- 4、HashMap的扩容操作是怎么实现的?
- 5、HashMap是怎么解决哈希冲突的?
- 6、能否使用任何类作为 Map 的 key?
- 7、为什么HashMap中String、Integer这样的包装类适合作为key?
- 8、如果使用Object作为HashMap的Key,应该怎么办呢?
- 9、HashMap为什么不直接使用hashCode()处理后的哈希值直接作为table的下标?
- 10、HashMap 的长度为什么是2的幂次方?
- 11、HashMap 与 Hashtable 有什么区别?
- 12、如何决定使用 HashMap 还是 TreeMap?
- 13、HashMap 和 ConcurrentHashMap 的区别
- 14、ConcurrentHashMap 和 Hashtable 的区别?用哪个?
- 15、ConcurrentHashMap 底层具体实现知道吗?实现原理是什么?
-
- 辅助工具类
集合容器概述
1、什么是集合?
集合框架:用于存储数据的容器。
集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。
任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。
接口:表示集合的抽象数据类型。接口允许我们操作集合时不必关注具体实现,从而达到“多态”。在面向对象编程语言中,接口通常用来形成规范。
实现:集合接口的具体实现,是重用性很高的数据结构。
算法:在一个实现了某个集合框架中的接口的对象身上完成某种有用的计算的方法,例如查找、排序等。这些算法通常是多态的,因为相同的方法可以在同一个接口被多个类实现时有不同的表现。
有了集合,我们可以专注于程序上的业务逻辑,并不需要写代码是怎么存储查询的。
2、集合有什么特点?
- 对象封装数据,对象多了也需要存储。集合用于存储对象。
- 对象个数确定的可以使用数组,对象个数不确定的可以用集合。因为集合是可变长度的。
3、集合和数组的区别
- 数组是固定长度的;集合可变长度的。
- 数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。
- 数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型。
4、使用集合框架的好处
- 容量自增长;
- 提供了高性能的数据结构和算法,使编码更轻松,提高了程序速度和质量;
- 允许不同 API 之间的互操作,API之间可以来回传递集合;
- 可以方便地扩展或改写集合,提高代码复用性和可操作性;
- 通过使用JDK自带的集合类,可以降低代码维护和学习新API成本。
5、常用的集合类有哪些?
Collection接口和Map接口是所有集合框架的父接口。
- Collection接口的子接口包括:List和Set接口;
- List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等;
- Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等;
- Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等;
6、List,Set,Map三者的区别?各自的特点?
Java 容器分为 Collection 和 Map 两大类,Collection集合的子接口有Set、List、Queue三种子接口。我们比较常用的是Set、List,Map接口不是collection的子接口。
Collection集合主要有List和Set两大接口
- List:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重复,可以插入多个null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。
- Set:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set 接口常用实现类是 HashSet、LinkedHashSet 以及 TreeSet。
Map是一个键值对集合,存储键、值和之间的映射。 key无序,唯一;value 不要求有序,允许重复。Map没有继承于Collection接口,从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
Map 的常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap。
7、集合框架底层数据结构
(1)List
- ArrayList:Object数组;
- Vector:Object数组;
- LinkedList:双向循环链表。
(2)Set
- HashSet:基于 HashMap 实现的,底层采用 HashMap 来保存元素;
- LinkedHashSet:LinkedHashSet 继承 HashSet,并且其内部是通过 LinkedHashMap 来实现的。有点类似LinkedHashMap 其内部是基于 HashMap 实现一样,不过还是有一点点区别的。
- TreeSet:基于TreeMap实现的,红黑树(自平衡的排序二叉树)。
(3)Map
- HashMap:JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。
- LinkedHashMap:LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。
- HashTable:数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的。
- TreeMap:红黑树(自平衡的排序二叉树)。
8、哪些集合类是线程安全的?
- Vector:就比ArrayList多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
- Statck:Vector的子类,堆栈类,先进后出。
- Hashtable:就比HashMap多了个线程安全。
- Properties:Hashtable的子类。
- Enumeration:枚举,相当于迭代器,后来被Iterator替代。
9、Java集合的快速失败机制 “fail-fast”了解吗?
是java集合的一种错误检测机制,当多个线程对集合进行结构上的改变的操作时,有可能会产生 fail-fast 机制。
例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast机制。
原因:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedModCount值,是的话就返回遍历;否则抛出异常,终止遍历。
解决办法:
- 在遍历过程中,所有涉及到改变modCount值得地方全部加上synchronized,这显然有点不太合适。
- 使用CopyOnWriteArrayList来替换ArrayList。
10、怎么确保一个集合不能被修改?
可以使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 java.lang.UnsupportedOperationException 异常。
示例代码:
public static void main(String[] aargs) {
List<String> list = new ArrayList<>();
list.add("aaa");
Collection<String> clist = Collections.unmodifiableCollection(list);
clist.add("bbb"); // 运行时此行抛异常:UnsupportedOperationException
System.out.println(list. size());
}
11、集合层次结构图
Collection接口:
Map接口:
Collection接口
List接口
1、迭代器 Iterator 是什么?
Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。
2、Iterator 怎么使用?有什么特点?
示例代码:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
Iterator<String> it = list