集合相关知识
基础知识
-
List Set Map都是接口,前两个继承至Collection接口,Map独立接口
- List:允许重复、有序对象,可以插入null
- Set:不允许重复,可以插入null、无序
- Map:使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复。每个键只能映射一个值
-
Map集合的数据结构针对键有效,跟值无关,Collection集合的数据结构针对元素有效。
-
Set:元素不可以重复
- HashSet:
- 实现Set接口
- 无序、唯一、非同步
- 允许元素为NULL
- 初始容量影响性能
- 底层是HashMap,通过hashCode()和equals()来保证唯一性
- LinkedHashSet:
- 迭代是有序的
- 允许为NULL
- 底层实际上是一个HashMap+双向链表实例(实际是LinkedHashMap)
- 非同步
- 性能比HashSet要差,业务要维护一个双向链表
- TreeSet:
- 实现NavigableSet接口
- 可以实现排序功能
- 得出实际上是一个TreeMap实例
- 非同步
- 底层是红黑树(唯一,有序)自然排序和比较器排序来保证元素排序,
- HashSet:
-
List:有序,可重复,查询多用ArrayList,增删多用LinkedList
-
ArrayList:动态数组,空间浪费在预留,默认初始容量为10,扩容1.5倍
源码阅读:https://blog.csdn.net/issunmingzhi/article/details/102795492
-
优点:底层结构是数组,查询快,增删慢(需要数组的拷贝复制,navite方法由C/C++实现)
关于增删慢不是绝对的,慢是慢在需要数组的拷贝与复制,如果一直增删末尾的话更快,删除中间的位置也是更快,但是一般来说都是慢的
-
缺点:线程不安全,效率高
-
-
Vector:(过时)Object数组,使用较少几乎被ArrayList代替,两倍的扩容导致消耗更多内存
- 优点:底层结构是数组,查询快,增删慢
- 缺点:线程安全,效率低
-
LinkedList:
- 优点:底层数据结构是双向链表(方便往前遍历),查询慢,增删快。
- 缺点:线程不安全,效率高,不支持高效地随机访问,空间浪费在存储前后驱
-
-
Map:
-
Hashtable:(过时)无序,方法是同步的,线程安全,效率低,不允许null,默认初始大小为11,扩容2n+1;
-
LinkedHashMap:
- 继承自HashMap
- 迭代有序
- 非同步
-
HashMap:
- 实现原理:
- 由数据和链表组成,数组是hashmap的主体,链表主要是为了解决哈希冲突而存在的,如果定位到的数组位置不含链表,那么对于查找、添加等操作很快,只需要一次寻址即可;如果定位到的数组存在链表,对于添加操作,其时间复杂度为o,首先遍历链表,存在即覆盖;对于查找操作来讲,还需遍历链表,然后通过key对象的equals方法逐一查找。所以性能考虑,hahsMap中的链表出现越少,性能才会更好。
- 是Hashtable的轻量级实现。底层结构是一个数组,数组中的每一项都是一条链表,无序,方法不是同步的,线程不安全,效率高,允许null(key和value都允许),能在查询和修改方便继承了数组的线性查找和链表的寻址修改;无contains方法;初始容量为16每次扩容为2n。当链表长度大于阈值8时将链表转化为红黑树,从而减少搜索时间
源码阅读:https://blog.csdn.net/issunmingzhi/article/details/102958877
- 实现原理:
-
TreeMap:有序,基于红黑树,非线程安全
-
-
Queue:PriorityQueue
-
迭代器Iterator:用于顺序访问集合对象的元素,无需知道集合对象的底层实现。Iterator 是可以遍历集合的对象,为各种容器提供了公共的操作接口,隔离对容器的遍历操作和底层实现,从而解耦。缺点是增加新的集合类需要对应增加新的迭代器类,迭代器类与集合类成对增加。
如何选用与使用
- 根据需要确定集合的类型。如果是单列的集合,我们考虑用Collection下的子接口ArrayList和Set。如果是映射,我们就考虑用Map
- 确定用哪个子类
- 去找Tree红黑树类型的
- 去找Linked双向链表结构的
- 去找线程安全的集合类使用
- 是否需要同步
- 迭代时是否需要有序(插入顺序有序)
- 是否需要排序(自然顺序或者手动排序)
- 估算存放集合的数据量有多大,无论是List还是map,它们实现动态增长,都是有性能消耗的,在初始化时选择一个合理的容量会减少动态增长时的消耗
- 使用泛型,避免在运行时出现ClassCastException
- 尽可能使用Collections工具类,或者获取只读、同步或空的集合,而非自己实现
面试知识
-
ArrayList和Vector的区别
- 共同点:都实现了List接口,都是有序集合,底层是数组。可以按位置索引号取出某个元素,运行元素重复和允许为NULL
- 区别
- 同步性:
- ArrayList是非同步的
- Vector是同步的
- 即便需要同步的时候,我们可以使用Collections工具类来构件出同步的ArrayList而不用Vector
- 扩容大小
- Vector增长原来的一倍
- ArrayList增长原来的0.5倍
- 同步性:
-
HashMap和Hashtable的区别:
- 共同点:从存储结构和实现来讲基本上都是相同的,都是实现Map接口
- 区别:
- 同步性:
- HashMap是非同步的,线程不安全(通过修改数据时锁住整个HashTable)
- Hashtable是同步的,线程安全
- 是否允许为null
- HashMap允许为null
- Hashtable不允许为null
- contain方法
- Hashtable有contains方法
- HashMap把Hashtable的contains方法去掉了,改成了containsValue和containsKey
- 继承不同
- HashMap继承自AbstractMap
- Hashtable继承自Dictionary
- 同步性:
-
List和Map区别
- 共同点:没啥
- 不同点:
- 存储结构不同
- List是存储单列的集合
- Map存储的是key-value键值对的集合
- 元素是否可重复
- List允许元素重复
- Map不允许key重复
- 是否有序
- List集合是有序的(存储有序)
- Map集合时无须的(存储无序)
- 存储结构不同
-
Collection和Collections的区别
- Collection是集合的上级接口,继承它的有Set和List接口,接口的意义是为各种具体的集合提供了最大化的统一操作方式
- Collections是集合的工具类,提供了一系列的静态方法对集合的搜索、查找、同步等操作
-
ArrayList,LinkedList的存储性能和特性
首先ArrayList的底层是数组,LinkedList的底层是双向链表
- ArrayList它支持以角标位置进行索引出对应的元素(随机访问),而LinkedList则需要遍历整个链表来获取对应的元素。因此一般来说ArrayList的访问速度是要比LinkedList要快的
- ArrayList由于是数组,对于删除和修改而言消耗是比较大(复制和移动数组实现),LinkedList是双向链表删除和修改只需要修改对应的指针即可,消耗是很小的。因此一般来说LinkedList的增删速度是要比ArrayList要快的
-
Enumeration和Iterator接口的区别
- Iterator的方法名比Enumeration更科学
- Iterator有fail-fast机制,比Enumeration更安全,当一个集合正在被遍历的时候,它会阻止其他线程去修改集合
- Iterator能够删除元素,Enumeration并不能删除元素
-
Listlterator特点
- 继承Iterator接口,它用于遍历List集合的元素
- 可以实现双向遍历,添加元素,设置元素
-
Iterator 和 ListIterator 有什么区别
-
相同点:都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用
-
不同点:
-
使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。
-
ListIterator有add方法,可以向List中添加对象,而Iterator不能。
-
ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator不可以。
-
ListIterator可以定位当前索引的位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
-
都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。
-
-
-
并发集合类是什么?
- java1.5并发包(java.util.concurrent)包含了线程安全集合类,允许在迭代时修改集合
- 迭代器被实际为fail-fast的,会抛出ConcurrentModificationException
- 一部分类为
- CopyOnWriteArrayList
- ConcurrentHashMap
- CopyOnWriteArraySet
-
java中HashMap的key值要是为类对象则该类需要满足什么条件
- 需要同时重写该类的hashCode()方法和它的equals()方法
- 在源码中,在插入元素的时候是先算出改对象的hashCode。如果hashCode相等的话,那么表明该对象是存储在同一个位置上的
- 如果调用equals()方法,两个key相同,则替换元素
- 如果调用equals()方法,两个key不相等,则说明该hashCode仅仅是碰巧相同,此时是散列冲突,将新增的元素放在桶子上
- 需要同时重写该类的hashCode()方法和它的equals()方法
-
Array和ArrayList区别:
- Array:
- 可以包含基本类型和对象类型
- 大小固定
- ArrayList
- 只能包含对象类型
- 大小动态变化
- 提供了更多的方法和特性
- Array:
-
在Queue中
- poll()和remove()有什么区别都是从队列中删除第一个元素。如果队列元素为空,调用remove() 的行为与 Collection 接口的版本相似会抛出异常,但是新的 poll() 方法在用空集合调用时只是返回 null**。因此新的方法更适合容易出现异常条件的情况。
- add()和offer()区别:**add()**和offer()都是向队列中添加一个元素。一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,调用 add() 方法就会抛出一个 unchecked 异常,而调用 offer() 方法会返回 false。因此就可以在程序中进行有效的判断!