目录
1.2.5 双端队列(ArrayDeque、LinkedList)
1、集合
定义:集合是用来存放对象的容器。
由来:当我们创建了很多对象并且想要使用,存放的位置可以使数组,但是在并不知道数量的情况下,就出现了集合来存放对象
java集合解决的问题:当需要快速的搜索成千上万的数据项,需要快速的在有序的序列中间插入或删除元素,建立键与值之间的关联,这时候java集合类库提供了大量的类和方法。
1.1 集合框架
Java的集合类库构成了集合类的框架。它为集合的实现者定义了大量的接口和抽象类,见下图(java集合框架图)。
Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。
1.1.1 集合接口
序号 | 接口描述 |
---|---|
1 | Collection 接口 Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。 Collection 接口存储一组不唯一,无序的对象。 |
2 | List 接口 List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。 List 接口存储一组不唯一,有序(插入顺序)的对象。 |
3 | Set Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。 Set 接口存储一组唯一,无序的对象。 |
4 | SortedSet 继承于Set保存有序的集合。 |
5 | Map Map 接口存储一组键值对象,提供key(键)到value(值)的映射。 |
6 | Map.Entry 描述在一个Map中的一个元素(键/值对)。是一个Map的内部类。 |
7 | SortedMap 继承于 Map,使 Key 保持在升序排列。 |
8 | Enumeration 这是一个传统的接口和定义的方法,通过它可以枚举(一次获得一个)对象集合中的元素。这个传统接口已被迭代器取代。 |
1.1.2 集合实现类
序号 | 类描述 |
---|---|
1 | AbstractCollection 实现了大部分的集合接口。 |
2 | AbstractList 继承于AbstractCollection 并且实现了大部分List接口。 |
3 | AbstractSequentialList 继承于 AbstractList ,提供了对数据元素的链式访问而不是随机访问。 |
4 | LinkedList 该类实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List。例如: LinkedList 查找效率低。 |
5 | ArrayList 该类也是实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用。ArrayList 增长当前长度的50%,插入删除效率低。 |
6 | AbstractSet 继承于AbstractCollection 并且实现了大部分Set接口。 |
7 | HashSet 该类实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个。 |
8 | LinkedHashSet 具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。 |
9 | TreeSet 该类实现了Set接口,可以实现排序等功能。 |
10 | AbstractMap 实现了大部分的Map接口。 |
11 | HashMap HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。 该类实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。 |
12 | TreeMap 继承了AbstractMap,并且使用一颗树。 |
13 | WeakHashMap 继承AbstractMap类,使用弱密钥的哈希表。 |
14 | LinkedHashMap 继承于HashMap,使用元素的自然顺序对元素进行排序. |
15 | IdentityHashMap 继承AbstractMap类,比较文档时使用引用相等。 |
1.1.3 迭代器
在集合中的基本接口都是Collection接口。这个接口有两个基本方法:
public interface Colletion<E>{
boolean add(E element);
Iterator<E>iterator();
}
add的方法是向集合中添加元素,而iterator方法是返回一个Iterator迭代器,最终使用迭代器对象依次访问集合中的元素。
迭代器Iterator的基本方法
返回 | 方法 |
---|---|
default void | forEachRemaining(Consumer<? super E> action) 对每个剩余元素执行给定的操作,直到所有元素都被处理或动作引发异常。 |
boolean | hasNext() 如果迭代具有更多元素,则返回 |
E | next() 返回迭代中的下一个元素。 |
default void | remove() 从底层集合中删除此迭代器返回的最后一个元素(可选操作)。 |
迭代器的使用:
Collection<String> collection = new ArrayList<String>();
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()){
String next = iterator.next();
//.......
}
java SE5之后开始使用for each用法,更加简洁
Collection<String> collection = new ArrayList<String>();
for (String str:collection) {
//.........
}
1.2 具体的集合
集合按照底层类型进行划分为:链表、数组列表、散列集、树集、队列、映射表。
1.2.1 链表(LinkedList)
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表的特点是:插入和删除快,查询慢。因为修改链表只需要将相邻的指针进行改变,所以速度快;查询需要遍历所有的数据,所以较慢。
底层使用链表的常用集合为LinkedList。
LinkedList类结构
LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
LinkedList 是 Java 集合框架中一个重要的实现,其底层采用的双向链表结构。和 ArrayList 一样,LinkedList 也支持空值和重复值。LinkedList 是非线程安全的集合类,并发环境下,多个线程同时操作 LinkedList,会引发不可预知的错误。
LinkedList最大的好处在于头尾和已知节点的插入和删除时间复杂度都是o(1)。但是涉及到先确定位置再操作的情况,则时间复杂度会变为o(n)。
LinkedList的底层节点为一个Node,信息都存放在对象中,Node类源码如下:(是一个内部类)
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
添加和删除首尾的节点时,直接将节点改变指针即可,时间复杂度为o(1),如下所示:
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
LinkedList的add方法是常用的方法,如果add(E element)时,直接插入到链表的尾部即可,但是如果使用
add(index,E element)方法就会增加开销,增大空间复杂度为o(n)。如下所示:
public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
}
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
1.2.2 数组列表(ArrayList)
数组列表的实现类常用的为ArrayList,它的底层结构是数组。它的特点是增删慢,查找快。注意:当想要使用vector时,因为vector时同步的,所以要多个线程访问时才推荐使用vector。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
1.2.3 散列集(HashSet)
链表和数组都可以按照意愿来给元素排列顺序,但是查看某个指定的元素时,不知道它的位置的时候,要遍历所有元素直到找到为止,将会消耗很多时间。
定义:一种数据结构,可以快速的访问所需要的对象,这个就叫散列表。散列表给每个对象计算一个整数,称之为散列码(hash code)。hashSet是使用的散列集。
在java中,散列表是由链表和数组构成,每个列表称之为“桶”。查找对象的方法就是:计算散列码,与桶的总数取余,找到保存元素的桶的索引,再去找这个元素的位置。
散列冲突:当我们存放数据的时候,可能到某个桶时,桶已经满了,这个叫做散列冲突。
唯一性:当使用add方法时,会检查该对象是否已经存在,具体比较如下:
使用Set集合是要去除重复元素,如果在存储的时候逐equals()比较,效率太低,哈希算法提高了去重复的效率,减少了使用equals()方法的次数,当HashSet对象调用add()方法存储对象时,会调用对象的HashCode()方法得到一个哈希值,然后在集合中查找是否有哈希值相同的对象,如果用,则调用equals()方法比较,如果没有则直接存入集合。
因此,如果自定义类对象存入集合去重复,需要重写equals()方法和HashCode()方法。
1.2.4 树集(TreeSet)
TreeSet类与散列集有些相似。树集是一个有序的集合,元素插入到集合后,遍历集合将是有序的元素。这种排序用的是一种算法:红黑树。(具体的红黑树后面学习)
红黑树规则:
1、每个结点都只能是红色或者黑色中的一种。
2、根结点是黑色的。
3、每个叶结点(NIL节点,空节点)是黑色的。
4、如果一个结点是红的,则它两个子节点都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点。
5、从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。
将元素添加到树中的速度要比散列表慢,但是唯一的特点就是可以排序,但是比链表和数组要快。对象的比较使用的是接口Comparable,所以要使用TreeSet的排序,对象要实现接口Comparable。
1.2.5 双端队列(ArrayDeque、LinkedList)
队列可以在头部删除、尾部增加,但是双端队列是可以在头部和尾部增加和删除,主要是实现的Deque接口。Deque 接口继承自 Queue接口,但 Deque 支持同时从两端添加或移除元素,因此又被成为双端队列。
1.2.6 映射表(HashMap、TreeMap)
映射表是存放键值对的形式来存在的。Java类库中提供了两个实现类:HashMap、TreeMap,两个类都实现了Map接口。
HashMap的键是由散列表来构成,TreeMap的键是由树的结构来形成。
在映射表中,键是唯一的,不能在同一个键中存放两个值。
1.3 常用方法
1.3.1 Collection的常用方法
返回值 | 方法名称 |
---|---|
boolean | add(E e) 确保此集合包含指定的元素(可选操作)。 |
boolean | addAll(Collection<? extends E> c) 将指定集合中的所有元素添加到此集合(可选操作)。 |
void | clear() 从此集合中删除所有元素(可选操作)。 |
boolean | contains(Object o) 如果此集合包含指定的元素,则返回 true 。 |
boolean | containsAll(Collection<?> c) 如果此集合包含指定 集合中的所有元素,则返回true。 |
boolean | equals(Object o) 将指定的对象与此集合进行比较以获得相等性。 |
int | hashCode() 返回此集合的哈希码值。 |
boolean | isEmpty() 如果此集合不包含元素,则返回 true 。 |
Iterator<E> | iterator() 返回此集合中的元素的迭代器。 |
default Stream<E> | parallelStream() 返回可能并行的 |
boolean | remove(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。 |
boolean | removeAll(Collection<?> c) 删除指定集合中包含的所有此集合的元素(可选操作)。 |
default boolean | removeIf(Predicate<? super E> filter) 删除满足给定谓词的此集合的所有元素。 |
boolean | retainAll(Collection<?> c) 仅保留此集合中包含在指定集合中的元素(可选操作)。 |
int | size() 返回此集合中的元素数。 |
default Spliterator<E> | spliterator() 创建一个 |
default Stream<E> | stream() 返回以此集合作为源的顺序 |
Object[] | toArray() 返回一个包含此集合中所有元素的数组。 |
<T> T[] | toArray(T[] a) 返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。 |
1.3.2 Map的常用方法
返回值 | 方法名 |
---|---|
void | clear() 从该Map删除所有的映射(可选操作)。 |
default V | compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) 尝试计算指定键的映射及其当前映射的值(如果没有当前映射, |
default V | computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) 如果指定的键尚未与值相关联(或映射到 |
default V | computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) 如果指定的密钥的值存在且非空,则尝试计算给定密钥及其当前映射值的新映射。 |
boolean | containsKey(Object key) 如果此映射包含指定键的映射,则返回 true 。 |
boolean | containsValue(Object value) 如果此Map将一个或多个键映射到指定的值,则返回 true 。 |
Set<Map.Entry<K,V>> | entrySet() 返回此Map中包含的映射的 |
boolean | equals(Object o) 将指定的对象与此映射进行比较以获得相等性。 |
default void | forEach(BiConsumer<? super K,? super V> action) 对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。 |
V | get(Object key) 返回到指定键所映射的值,或 |
default V | getOrDefault(Object key, V defaultValue) 返回到指定键所映射的值,或 |
int | hashCode() 返回此Map的哈希码值。 |
boolean | isEmpty() 如果此地图不包含键值映射,则返回 true 。 |
Set<K> | keySet() 返回此地图中包含的键的 |
default V | merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction) 如果指定的键尚未与值相关联或与null相关联,则将其与给定的非空值相关联。 |
V | put(K key, V value) 将指定的值与该映射中的指定键相关联(可选操作)。 |
void | putAll(Map<? extends K,? extends V> m) 将指定地图的所有映射复制到此映射(可选操作)。 |
default V | putIfAbsent(K key, V value) 如果指定的键尚未与某个值相关联(或映射到 |
V | remove(Object key) 如果存在(从可选的操作),从该地图中删除一个键的映射。 |
default boolean | remove(Object key, Object value) 仅当指定的密钥当前映射到指定的值时删除该条目。 |
default V | replace(K key, V value) 只有当目标映射到某个值时,才能替换指定键的条目。 |
default boolean | replace(K key, V oldValue, V newValue) 仅当当前映射到指定的值时,才能替换指定键的条目。 |
default void | replaceAll(BiFunction<? super K,? super V,? extends V> function) 将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。 |
int | size() 返回此地图中键值映射的数量。 |
Collection<V> | values() 返回此地图中包含的值的 |
1.3.3 工具类Collections的常用方法
-
此类仅由静态方法组合或返回集合。 它包含对集合进行操作的多态算法,“包装器”,返回由指定集合支持的新集合,以及其他一些可能的和最终的。
返回值 | 方法名称 |
---|---|
static <T> boolean | addAll(Collection<? super T> c, T... elements) 将所有指定的元素添加到指定的集合。 |
static <T> Queue<T> | asLifoQueue(Deque<T> deque) |
static <T> int | binarySearch(List<? extends Comparable<? super T>> list, T key) 使用二叉搜索算法搜索指定对象的指定列表。 |
static <T> int | binarySearch(List<? extends T> list, T key, Comparator<? super T> c) 使用二叉搜索算法搜索指定对象的指定列表。 |
static <E> Collection<E> | checkedCollection(Collection<E> c, 类<E> type) 返回指定集合的动态类型安全视图。 |
static <E> List<E> | checkedList(List<E> list, 类<E> type) 返回指定列表的动态类型安全视图。 |
static <K,V> Map<K,V> | checkedMap(Map<K,V> m, 类<K> keyType, 类<V> valueType) 返回指定地图的动态类型安全视图。 |
static <K,V> NavigableMap<K,V> | checkedNavigableMap(NavigableMap<K,V> m, 类<K> keyType, 类<V> valueType) 返回指定可导航地图的动态类型安全视图。 |
static <E> NavigableSet<E> | checkedNavigableSet(NavigableSet<E> s, 类<E> type) 返回指定的可导航集的动态类型安全视图。 |
static <E> Queue<E> | checkedQueue(Queue<E> queue, 类<E> type) 返回指定队列的动态类型安全视图。 |
static <E> Set<E> | checkedSet(Set<E> s, 类<E> type) 返回指定集合的动态类型安全视图。 |
static <K,V> SortedMap<K,V> | checkedSortedMap(SortedMap<K,V> m, 类<K> keyType, 类<V> valueType) 返回指定排序映射的动态类型安全视图。 |
static <E> SortedSet<E> | checkedSortedSet(SortedSet<E> s, 类<E> type) 返回指定排序集的动态类型安全视图。 |
static <T> void | copy(List<? super T> dest, List<? extends T> src) 将所有元素从一个列表复制到另一个列表中。 |
static boolean | disjoint(Collection<?> c1, Collection<?> c2) 如果两个指定的集合没有共同的元素,则返回 |
static <T> Enumeration<T> | emptyEnumeration() 返回没有元素的枚举。 |
static <T> Iterator<T> | emptyIterator() 返回没有元素的迭代器。 |
static <T> List<T> | emptyList() 返回空列表(immutable)。 |
static <T> ListIterator<T> | emptyListIterator() 返回没有元素的列表迭代器。 |
static <K,V> Map<K,V> | emptyMap() 返回空的地图(不可变)。 |
static <K,V> NavigableMap<K,V> | emptyNavigableMap() 返回空导航地图(不可变)。 |
static <E> NavigableSet<E> | emptyNavigableSet() 返回一个空导航集(immutable)。 |
static <T> Set<T> | emptySet() 返回一个空集(immutable)。 |
static <K,V> SortedMap<K,V> | emptySortedMap() 返回空的排序映射(immutable)。 |
static <E> SortedSet<E> | emptySortedSet() 返回一个空的排序集(immutable)。 |
static <T> Enumeration<T> | enumeration(Collection<T> c) 返回指定集合的枚举。 |
static <T> void | fill(List<? super T> list, T obj) 用指定的元素代替指定列表的所有元素。 |
static int | frequency(Collection<?> c, Object o) 返回指定集合中与指定对象相等的元素数。 |
static int | indexOfSubList(List<?> source, List<?> target) 返回指定源列表中指定目标列表的第一次出现的起始位置,如果没有此类事件,则返回-1。 |
static int | lastIndexOfSubList(List<?> source, List<?> target) 返回指定源列表中指定目标列表的最后一次出现的起始位置,如果没有此类事件则返回-1。 |
static <T> ArrayList<T> | list(Enumeration<T> e) 返回一个数组列表,其中包含由枚举返回的顺序由指定的枚举返回的元素。 |
static <T extends Object & Comparable<? super T>> | max(Collection<? extends T> coll) 根据其元素的 自然顺序返回给定集合的最大元素。 |
static <T> T | max(Collection<? extends T> coll, Comparator<? super T> comp) 根据指定的比较器引发的顺序返回给定集合的最大元素。 |
static <T extends Object & Comparable<? super T>> | min(Collection<? extends T> coll) 根据其元素的 自然顺序返回给定集合的最小元素。 |
static <T> T | min(Collection<? extends T> coll, Comparator<? super T> comp) 根据指定的比较器引发的顺序返回给定集合的最小元素。 |
static <T> List<T> | nCopies(int n, T o) 返回由指定对象的 n副本组成的不可变列表。 |
static <E> Set<E> | newSetFromMap(Map<E,Boolean> map) 返回由指定地图支持的集合。 |
static <T> boolean | replaceAll(List<T> list, T oldVal, T newVal) 将列表中一个指定值的所有出现替换为另一个。 |
static void | reverse(List<?> list) 反转指定列表中元素的顺序。 |
static <T> Comparator<T> | reverseOrder() 返回一个比较器,它对实现 |
static <T> Comparator<T> | reverseOrder(Comparator<T> cmp) 返回一个比较器,它强制指定比较器的反向排序。 |
static void | rotate(List<?> list, int distance) 将指定列表中的元素旋转指定的距离。 |
static void | shuffle(List<?> list) 使用默认的随机源随机排列指定的列表。 |
static void | shuffle(List<?> list, Random rnd) 使用指定的随机源随机排列指定的列表。 |
static <T> Set<T> | singleton(T o) 返回一个只包含指定对象的不可变集。 |
static <T> List<T> | singletonList(T o) 返回一个只包含指定对象的不可变列表。 |
static <K,V> Map<K,V> | singletonMap(K key, V value) 返回一个不可变的地图,只将指定的键映射到指定的值。 |
static <T extends Comparable<? super T>> | sort(List<T> list) 根据其元素的natural ordering对指定的列表进行排序。 |
static <T> void | sort(List<T> list, Comparator<? super T> c) 根据指定的比较器引起的顺序对指定的列表进行排序。 |
static void | swap(List<?> list, int i, int j) 交换指定列表中指定位置的元素。 |
static <T> Collection<T> | synchronizedCollection(Collection<T> c) 返回由指定集合支持的同步(线程安全)集合。 |
static <T> List<T> | synchronizedList(List<T> list) 返回由指定列表支持的同步(线程安全)列表。 |
static <K,V> Map<K,V> | synchronizedMap(Map<K,V> m) 返回由指定地图支持的同步(线程安全)映射。 |
static <K,V> NavigableMap<K,V> | synchronizedNavigableMap(NavigableMap<K,V> m) 返回由指定的可导航地图支持的同步(线程安全)可导航地图。 |
static <T> NavigableSet<T> | synchronizedNavigableSet(NavigableSet<T> s) 返回由指定的可导航集支持的同步(线程安全)可导航集。 |
static <T> Set<T> | synchronizedSet(Set<T> s) 返回由指定集合支持的同步(线程安全)集。 |
static <K,V> SortedMap<K,V> | synchronizedSortedMap(SortedMap<K,V> m) 返回由指定的排序映射支持的同步(线程安全)排序映射。 |
static <T> SortedSet<T> | synchronizedSortedSet(SortedSet<T> s) 返回由指定的排序集支持的同步(线程安全)排序集。 |
static <T> Collection<T> | unmodifiableCollection(Collection<? extends T> c) 返回指定集合的不可修改视图。 |
static <T> List<T> | unmodifiableList(List<? extends T> list) 返回指定列表的不可修改视图。 |
static <K,V> Map<K,V> | unmodifiableMap(Map<? extends K,? extends V> m) 返回指定地图的不可修改视图。 |
static <K,V> NavigableMap<K,V> | unmodifiableNavigableMap(NavigableMap<K,? extends V> m) 返回指定可导航地图的不可修改视图。 |
static <T> NavigableSet<T> | unmodifiableNavigableSet(NavigableSet<T> s) 返回指定的可导航集合的不可修改的视图。 |
static <T> Set<T> | unmodifiableSet(Set<? extends T> s) 返回指定集合的不可修改视图。 |
static <K,V> SortedMap<K,V> | unmodifiableSortedMap(SortedMap<K,? extends V> m) 返回指定排序映射的不可修改视图。 |
static <T> SortedSet<T> | unmodifiableSortedSet(SortedSet<T> s) 返回指定排序集的不可修改视图。 |