集合和数组的区别
集合框架API
Collection
List
ArrayList
Vector
LinkedList
Set
HashSet
LinkedHashSet
TreeSet
Map
HashMap
LinkedHashMap
HashTable
TreeMap
Iterator迭代器接口
每一个集合都有自己的数据结构(就是容器中存储数据的方式),都有特定的取出自己内部元素的方式。为了便于操作所有的容器,取出元素,将容器内部的取出方式按照一个统一的规则向外提供,这个规则就是Iterator接口。
特别的,使用Iterator删除元素,不会出现并发异常,但没有添加元素方法;可以使用ListIterator对List集合边遍历边添加元素。
哈希表
哈希表其实就是数组,通过将元素的关键字key用哈希函数计算后在与数组大小取模得到存储地址。在ArrayList中元素判断都是直接通过equals,而在HashSet等中是通过HashCode和equals共同完成的,只有hashcode相等才去遍历比较equals,提高了比较效率。
List
List是有序的,也就是插入数据的顺序和取出的顺序是一样的;List也是可重复的。
ArrayList:数据结构是数组,线程不安全,默认大小10,扩容是原来的1.5倍,查询速度快。
LinkedList:数据结构是双向链表,线程不安全,增删速度快。
Vector:数据结构是数组,线程安全,默认大小10,扩容是原来的2倍,增删查询效率都不高。
Set
Set是无序的(LinkedHashSet是有序的),也就是插入数据的顺序跟取出的顺序不一样;Set元素不可重复。
HashSet:数据结构是哈希表(数组+链表);HashSet只去重。
LinkedHashSet:数据结构是哈希表;去重并保留插入顺序。
TreeSet:数据结构是二叉查找树(红黑树);去重并排序,所以需要元素对象实现Comparable接口。
Map
HashTable:数据结构是数组+链表;线程安全,修改时会锁住整张表;不可null键 null值;采用链地址法解决哈希冲突。
HashMap:数据结构是数组+链表;线程不安全;可一个null键多个null值;采用链地址法解决哈希冲突。
LinkedHashMap:跟HashMap类型,但会维护一个双向链表来保持插入的顺序是有序的。
TreeMap:数据结构是红黑树;对map的key可以进行排序。
经典问题
HashMap底层实现
HashMap设计的初衷是想像数组一样根据下标一次定位就能得到想要的数据,但又想像链表一样增删的效率高,而实现这个方法是通过一个hash函数对关键字进行计算得到一个范围内的存储位置值,然后取值、增删等只需要用这个hash函数去计算一下就能得到存储位置,效率很高。如果说没有哈希冲突的话,只需要数组就可以实现了,哈希冲突是因为用hash函数去计算关键字的时候可能会出现不同的关键字运算之后存储地址值相同,为了解决这种问题又一些哈希冲突解决方法,例如开放定址、再散列函数法、链地址法等,HashMap就是采用链地址法,核心实现是以一个数组作为存储主干,当出现哈希冲突,在冲突的地址上加上链表。所以HashMap的查找增删就是通过计算关键字的哈希值然后得到存储的地址,如果该地址没有链表那么时间复杂度就是1,如果有链表的话那就需要遍历链表,时间复杂度是n。如果要提高HashMap的查找效率可以增大容量或减小填充因子,但会对迭代造成效率下降。
如果用自定义的对象作为map的key,必须重写hashCode和equal方法。HashCode方法可以将一个对象计算得到一个地址值,作为数组下标,而equal方式是在对象的hashcode值相等,或者说数组中的地址相等时,去遍历链表的key是否相等。
HashMap、HashTable、ConcurrentHashMap区别
HashMap:
1.存储方式:数组+链表,可以一个null为key或多个null为value存储;初始容量16,填充因子0.75,扩容为原来的两倍。
2.线程安全和性能:是线程不安全的,性能相对高。
3.hash计算方式:将对象的hashcode再次hash计算得到存储地址。分布更均匀。
HashTable:
1.存储方式:数组+链表,不可以以null为key或value存储;初始容量11,填充因子0.75,扩容为原来容量*2+1。
2.线程安全和性能:线程安全,方法都添加了synchronized确保线程同步,每次查找都要锁住整张表,性能较差。
3.hash计算方式:对象关键字key的hashcode对数组长度取模直接得到。
ConcurrentHashMap:
1.存储方式:数组+链表,默认将hash分为16个桶。
2.线程安全和性能:线程安全的,将数据分段存储,每段有一个锁,这样可以允许多个段的数据被并发访问,读操作不加锁,性能相对较好。
Collection和Collections的区别
Collection是集合顶层接口,Collections是集合操作工具类,有排序、查找等静态方法方便调用。