集合的特点
集合的特点主要有如下两点:
- 对象封装数据,对象多了也需要存储。集合用于存储对象
- 对象的个数确定可以使用数组,对象的个数不确定的可以用集合。因为集合是可变长度的。
数据结构
- 容器中用于存储数据的方式
使用一个体系的原则:参阅顶层内容,建立底层对象
使用集合框架的好处
- 容量自增长;
- 提供了高性能的数据结构和算法,是编码更轻松,提高了程序速度和质量;
- 允许不同API之间的互操作,API之间可以来回传递集合;
- 可以方便地扩展或改写集合,提高代码复用性和可操作性。
- 通过使用JDK自带的集合类,可以降低代码维护和学习新API成本。
常用的集合类有哪些?
Map接口和Collection接口是所有集合框架的父接口: 1.Collection接口的子接口包括:Set接口和List接口 2.Map接口的实现类主要有:HashMap、Hashtable、TreeMap、ConcurrentHashMap以及Properties等。 3.Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等 4.List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等。
List、Set、Map三者的区别?
Java容器分为Collection和Map两大类。 Collection集合的子接口有Set、List、Queue三种子接口,我们常用List、Set。 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
集合框架底层数据结构
Collection
- List
- ArrayList:Object数组
- Vector:Object数组
- LinkedList:双向循环链表 2.Set
- HashSet(无序、唯一):基于HashMap实现的,底层采用HashMap来保存元素
- LinkedHashSet:LinkedHashSet继承于HashSet,并且其内部是通过LinkedHashMap来实现的。有点类似于我们之前说的LinkedHashMap其内部是基于HashMap实现一样,不过还是有点点区别的。
- TreeSet(有序、唯一):红黑树(自平衡的排序二叉树) Map
- HashMap:JDK1.8之前由数据+链表组成,数组为主体、链表则是用于解决哈希冲突,JDK1.8之后链表部分发生变化,当链表长度大于阈值(默认为8)时,链表转为红黑树,减少搜索时间。
- LinkedHashMap:继承自HashMap,在此基础上增加一条双向链表,实现了保持键值对的插入顺序。同时对链表进行相应的操作,实现了访问顺序相关逻辑。
- HashTable:数组+链表组成,数组为主体、链表则是用于解决哈希冲突。
- TreeMap:红黑树(自平衡的排序二叉树)
那些集合类是线程安全的
- Vector:比ArrayList多个同步化机制(线程安全),但不推荐使用,因为效率较低。
- statck:堆栈类,先进后出。
- HashTable:比HashMap多个线程安全。
- enumeration:枚举,相当于迭代器。
怎么确保一个集合不能被修改
创建一个只读集合,这样任何改变集合的操作都会抛出异常。
Collection接口
List接口 代器Iterator是什么
Iterator接口可以遍历任何Collection的接口。 我们可以从一个Collection中使用迭代器方法来获取迭代器实例。 迭代器取代了Java集合框架中的Enumeration,迭代器允许调用者在迭代过程中移除元素。
Iterator怎么使用?有什么特点?
List list = new ArrayList<>();
Iterator it = list.iterator();
while(it.hasNext()){
String obj = it.next();
System.out.println(obj);
}
Iterator的特点:
- 只能单向遍历,更为安全,可以确保当前遍历的集合元素被更改时,抛出Concurrent Modification Exception 异常。
如何遍历时移除 Collection 中的元素
正确代码
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
it.remove();
}
常见错误代码
for(Integer i : list){
list.remove(i);
}
运行以上错误代码会报 Concurrent Modification Exception 异常。 原因:Java一般不允许一个线程遍历Collection时,另一个线程修改它。
Iterator和ListIterator 有什么区别?
- Iterator可以遍历Set和List集合,而ListIterator只能遍历List。
- Iterator只能单向遍历,而List Iterator可以双向遍历(向前/后遍历)。
- List Iterator实现Iterator接口,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
对List集合有几种遍历方式?最佳实践是什么?
遍历方式有一下几种:
- for循环遍历:基于计数器。在集合外维护一个计数器,依次读取元素,直至最后元素停止。
- 迭代器遍历:Iterator,Iterator是面向对象的一种设计模式,目的是屏蔽不同数据集合,统一遍历集合的接口。Java在Collection中支持了Iterator模式。
- foreach循环遍历:foreach内部采用Iterator的方式实现,使用时不用显示声明Iterator或计数器。优点:代码简洁、不易出错;缺点:只能做简单的遍历,不能在遍历时操作数据集合,如删除、替换。 最佳实践:Java Collection 框架中提供RandomAccess接口,用来标记List实现是否支持Random Access。
- 如果数据集合实现类该接口,意味着它支持Random Access,按位置读取元素的平均时间复杂度为O(1), 如ArrayList。
- 如果没有实现该接口,表示不支持Random Access,如LinkedList。 推荐的做法就是,支持 Random Access 的列表可用for循环遍历,否则建议用Iterator或foreach遍历。