1. 集合和数组的区别
- 数组是固定长度的;集合可变长度的。
- 数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存 储引用数据类型。
- 数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同 数据类型。
2. 常用的集合类
Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue
3. List,Set,Map
Collection集合主要有List和Set两大接口 ,均为单列集合,而Map为双列集合。
- List:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重 复,可以插入多个 null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。
-
- 底层的数据结构:Arraylist是Object数组 ;Vector是Object数组 ;LinkedList是双向循环链表
- 特点:有序,可重复,有索引
- Set:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素, 只允许存入一个 null元素,必须保证元素唯一性。Set 接口常用实现类是 HashSet、 LinkedHashSet 以及 TreeSet。不同的实现底层数据结构不同,其特点也不尽相同。
-
- 底层的数据结构:
-
-
- HashSet基于哈希表实现的, 在JDK1.8之前是数组+链表,在JDK1.8之后是数组+链表+红黑树;
- LinkedHashSet同样也是基于哈希表(数组+链表+红黑树)实现的;与HashSet不同的是每个元素都多了一个双链表的机制记录前后元素的位置,基于此是有序的。
- TreeSet是基于红黑树实现的,无法对自定义对象进行排序,需要在其构造方法中传入Comparator接口自定义排序规则。
-
-
- 特点:HashSet:无序,不重复,无索引。LinkedHashSet:有序,不重复,无索引。Treeset: 可排序,不重复,无索引。
- Map:Map是一个键值对集合,存储键、值和之间的映射。 Key无序,唯一;value 不 要求有序,允许重复。 Map没有继承于Collection接口,从Map集合中检索元 素时,只要给出键对象,就会返回对应的值对 象。 Map 的常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、 ConcurrentHashMap
-
- 数据结构同Set集合,因为Set集合底层都是调用Map集合,只不过只用了key。
- map集合体系的特点:HashMap(由键决定特点):无序,不重复,无索引; (用的最多);LinkedHashMap(由键决定特点):有序,不重复,无索引。TreeMap(由键决定特点):按照大小默认升序排序,不重复,无索引。
4. ArrayList和LinkedList
4.1. ArrayList(有序,可重复,有索引)
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。ArrayList 继承了 AbstractList ,并实现了 List 接口。
ArrayList的底层实现是动态数组。
4.2. LinkedList(有序,可重复,有索引)
LinkedList类似于 ArrayList,是一种常用的数据容器。与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。
LinkedList的底层实现是双向链表,常见的链表有三种
4.3. ArrayList和LinkedList的使用场景(区别)
以下情况使用 ArrayList :
- 频繁访问列表中的某一个元素。
- 只需要在列表末尾进行添加和删除元素操作。
以下情况使用 LinkedList :
- 你需要通过循环迭代来访问列表中的某些元素。
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
数组和链表的效率对比:
5. HashSet和LinkedHashSet
Set系列集合本质就是Map,只不过只使用了key。HashSet在其源码无参构造中就是new HashMap<>( );而LinkedHashSet在源码中就是如下:HashSet是LinkedHashSet的父类。
HashSet是默认不能对内容一样的两个对象去重复,因为不同的对象hash值不一样而存到了不同的位置,此时应该重写该对象的HashCode和equals方法。
public LinkedHashSet() {
super(16, .75f, true);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
HashSet:无序,不重复,无索引。
LinkedHashSet:有序,不重复,无索引。
Treeset: 排序,不重复,无索引。
JDK8之前,哈希表=数组+链表
JDK8之后,哈希表=数组+链表+红黑树
5.1. HashSet
本质就是HashMap,只不过只使用了key
5.2. LinkedHashSet
本质上是LinkedHashMap,只使用key
6. HashMap和LinkedHashMap
- hashmap集合是一种增删改查数据,性能都较好的集合
- 但是它是无序,不能重复,没有索引支持的(由键决定特点)
- hashmap的键依赖hashcode方法和equals方法保证键的唯一
- 如果键存储的是自定义类型的对象,可以通过重写hashcode和equals方法,这样可以保证多个对象内容一样时,hashmap集合就能认为是重复的。
7. HashMap和HashTable
- HashTable是线程安全的,所有的方法中都加了synchronized关键字 。
- 继承的父类不同HashTable是继承于Dictionary抽象类,而HashMap是继承AbstractMap。
- hashTable默认为11,扩容为2n+1,而hashMap默认为16,扩容为2倍。如添加指定长度,table会直接使用,而map总会扩充为2的n次幂。
- 在散列算法(计算hash值)上,上HashTable会使用key对hashCode对长度取模,hashMap会做一些扰动来达到更好的分布。 下面的源码中体现出来了。
- HashTable中key,value都不允许为null,HashMap是允许的。HashMap源码如下:
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = key.hashCode();
....................
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}