java.util 包中提供了一些集合类,这些集合类又被称为容器。提到容器不难想到数组,集合类与数组的不同之处是,数组的长度是固定的,集合的长度是可变的;数组用来存放基本类型的数据,集合用来存放对象的引用。常用的集合有 List 集合、Set 集合和 Map 集合,其中 List 与 Set 继承了 Collection 接口,各接口还提供了不同的实现类。
集合接口类特性:
Set 和 List 的区别:
Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
Set 检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List 和数组类似,可以动态增长,根据实际存储的数据的长度自动增长 List 的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变。
Collection 接口是层次结构中的根接口。构成 Collection 的单位称为元素。Collection 接口通常不能直接使用,但该接口提供了添加元素、删除元素、管理数据的方法。由于 List 接口与 Set 接口都继承了 Collection 接口,因此这些方法对 List 集合与 Set 集合是通用的。
方法 | 描述 |
---|---|
add(E e) | 将指定的对象添加到该集合中 |
remove(Object o) | 将指定的对象从该集合中移除 |
isEmpty() | 返回 boolean 值,用于判断当前集合是否为空 |
iterator() | 返回在此 Collection 的元素上进行迭代的迭代器。用于遍历集合中的对象 |
size() | 返回 int 型值,获取该集合中元素的个数 |
通常遍历集合,都是通过迭代器(Iterator)来实现。Collection接口中的iterator()方法可返回在此Collection进行迭代的迭代器。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Muster {
public static void main(String[] args) {
Collection<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
// 创建迭代器
Iterator<String> it = list.iterator();
ss
// 判断是否有下一个元素
while (it.hasNext()) {
String str = it.next(); // 获取集合中元素
System.out.println(str);
}
}
}
输出结果:
a
b
c
List 接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问 List 中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口的常用实现类有 ArrayList 与 LinkedList。
ArrayList 类实现了可变的数组,允许保存所有元素,包括 null,并可以根据索引位置对集合进行快速的随机访问;缺点是向指定的索引位置插入对象或删除对象的速度较慢。
ArrayList 继承了 AbstractList 类,并实现了 List 接口。
常用方法
方法 | 描述 |
---|---|
add() | 将元素插入到指定位置的 arraylist 中 |
addAll() | 添加集合中的所有元素到 arraylist 中 |
clear() | 删除 arraylist 中的所有元素 |
clone() | 复制一份 arraylist |
contains() | 判断元素是否在 arraylist |
get() | 通过索引值获取 arraylist 中的元素 |
indexOf() | 返回 arraylist 中元素的索引值 |
removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
remove() | 删除 arraylist 里的单个元素 |
size() | 返回 arraylist 里元素数量 |
isEmpty() | 判断 arraylist 是否为空 |
subList() | 截取部分 arraylist 的元素 |
set() | 替换 arraylist 中指定索引的元素 |
sort() | 对 arraylist 元素进行排序 |
toArray() | 将 arraylist 转换为数组 |
toString() | 将 arraylist 转换为字符串 |
ensureCapacity() | 设置指定容量大小的 arraylist |
lastIndexOf() | 返回指定元素在 arraylist 中最后一次出现的位置 |
retainAll() | 保留 arraylist 中在指定集合中也存在的那些元素 |
containsAll() | 查看 arraylist 是否包含指定集合中的所有元素 |
trimToSize() | 将 arraylist 中的容量调整为数组中的元素个数 |
removeRange() | 删除 arraylist 中指定索引之间存在的元素 |
replaceAll() | 将给定的操作内容替换掉数组中每一个元素 |
removeIf() | 删除所有满足特定条件的 arraylist 元素 |
forEach() | 遍历 arraylist 中每一个元素并执行特定操作 |
import java.util.ArrayList;
public class Muster {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
// 将指定索引位置的元素删除,集合的索引从0开始
list.remove(1);
// 遍历集合
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
输出结果:
a
c
使用总结
LinkedList 类采用链表结构保存对象。这种结构的优点是便于向集合中插入和删除对象,需要向集合中插入、删除对象时,使用 LinkedList 类实现的 List 集合的效率较高;但对于随机访问集合中的对象,使用 LinkedList 类实现 List 集合的效率较低。
LinkedList 继承了 AbstractSequentialList 类,并实现了 Queue、List、Deque、Cloneable、ava.io.Serializable 接口。
常用方法
方法 | 描述 |
---|---|
public boolean add(E e) | 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public void add(int index, E element) | 向指定位置插入元素。 |
public boolean addAll(Collection c) | 将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。 |
public boolean addAll(int index, Collection c) | 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。 |
public void addFirst(E e) | 元素添加到头部。 |
public void addLast(E e) | 元素添加到尾部。 |
public boolean offer(E e) | 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerFirst(E e) | 头部插入元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerLast(E e) | 尾部插入元素,返回是否成功,成功为 true,失败为 false。 |
public void clear() | 清空链表。 |
public E removeFirst() | 删除并返回第一个元素。 |
public E removeLast() | 删除并返回最后一个元素。 |
public boolean remove(Object o) | 删除某一元素,返回是否成功,成功为 true,失败为 false。 |
public E remove(int index) | 删除指定位置的元素。 |
public E poll() | 删除并返回第一个元素。 |
public E remove() | 删除并返回第一个元素。 |
public boolean contains(Object o) | 判断是否含有某一元素。 |
public E get(int index) | 返回指定位置的元素。 |
public E getFirst() | 返回第一个元素。 |
public E getLast() | 返回最后一个元素。 |
public int indexOf(Object o) | 查找指定元素从前往后第一次出现的索引。 |
public int lastIndexOf(Object o) | 查找指定元素最后一次出现的索引。 |
public E peek() | 返回第一个元素。 |
public E element() | 返回第一个元素。 |
public E peekFirst() | 返回头部元素。 |
public E peekLast() | 返回尾部元素。 |
public E set(int index, E element) | 设置指定位置的元素。 |
public Object clone() | 克隆该列表。 |
public Iterator descendingIterator() | 返回倒序迭代器。 |
public int size() | 返回链表元素个数。 |
public ListIterator listIterator(int index) | 返回从指定位置开始到末尾的迭代器。 |
public Object[] toArray() | 返回一个由链表元素组成的数组。 |
public T[] toArray(T[] a) | 返回一个由链表元素转换类型而成的数组。 |
import java.util.LinkedList;
public class Muster {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<String>();
list.add("a");
list.add("b");
list.add("c");
list.addFirst("d"); // 在头部添加元素
list.addLast("e"); // 在尾部添加元素
// 遍历集合
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
输出结果:
d
a
b
c
e
使用总结
Set 集合中的对象不按特定的方式排序,只是简单地把对象加入集合中,但 Set 集合中不能包含重复对象。Set 集合由 Set 接口和 Set 接口的实现类组成。Set 接口继承了 Collection 接口,因此包含 Collection 接口的所有方法。
Set 接口常用的实现类有 HashSet 与 TreeSet。
HashSet 类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 Set 的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
该类实现了 Set 接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为 null 的元素,但最多只能一个。
import java.util.HashSet;
public class Muster {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
set.add("a");
set.add("b");
set.add("c");
set.add("a"); // 重复的元素不会被添加
set.remove("b"); // 删除元素
// 可以使用 for-each 来迭代 HashSet 中的元素
for (String i : set) {
System.out.println(i);
}
}
}
输出结果:
a
c
TreeSet 类不仅实现了 Set 接口,还实现了 java.util.SortedSet 接口,因此,TreeSet 类实现的 Set 集合在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序,即可以通过比较器对用 TreeSet 类实现的 Set 集合中的对象进行排序。
该类实现了Set接口,可以实现排序等功能。
TreeSet 类增加的方法
方法 | 描述 |
---|---|
first() | 返回此 Set 中当前第一个(最低)元素 |
last() | 返回此 Set 中当前最后一个(最高)元素 |
comparator() | 返回对此 Set 中的元素进行排序的比较器。如果此 Set 使用自然排序,则返回 null |
headSet(E toElement) | 返回一个新的 Set 集合,新集合是 toElement(不包括)之前的所有对象 |
subSet(E fromElement, E fromElement) | 返回一个新的 Set 集合,是 fromElement(包含)对象与 fromElement(不包含)对象之间的所有对象 |
tailSet(E fromElement) | 返回一个新的 Set 集合,新集合包含对象 fromElement(包含)之后的所有对象 |
import java.util.TreeSet;
public class Muster {
public static void main(String[] args) {
TreeSet<String> set = new TreeSet<String>();
set.add("a");
set.add("c");
set.add("b");
// TreeSet 实现了自动排序功能
for (String i : set) {
System.out.println(i);
}
}
}
输出结果:
a
b
c
Map 集合没有继承 Collection 接口,其提供的是 key 到 value 的映射。Map 中不能包含相同的 key,每个 key 只能映射一个 value。key 还决定了存储对象在映射中的存储位置,但不是由 key 对象本身决定的,而是通过一种“散列技术”进行处理,产生一个散列码的整数值。散列码通常用作一个偏移量,该偏移量对应分配给映射的内存区域的起始位置,从而确定存储对象在映射中的存储位置。Map 集合包括Map 接口以及 Map 接口的所有实现类。
Map 接口常用方法
方法 | 描述 |
---|---|
put(K key, V value) | 向集合中添加指定的 key 与 value 的映射关系 |
containsKey(Object key) | 如果此映射包含指定 key 的映射关系,则返回 true |
containsValue(Object Value) | 如果此映射将一个或多个 key 映射到指定值,则返回 true |
get(Object key) | 如果存在指定的 key 对象,则返回该对象对应的值,否则返回 null |
keySet() | 返回该集合中的所有 key 对象形成的 Set 集合 |
values() | 返回该集合中所有值对象形成的 Collection 集合 |
Map 接口常用的实现类有 HashMap 和 TreeMap。建议使用 HashMap 类实现 Map 集合,因为由 HashMap 类实现的 Map 集合添加和删除映射关系效率更高。HashMap 是基于哈希表的 Map 接口的实现,HashMap 通过哈希码对其内部的映射关系进行快速查找;而TreeMap 中的映射关系存在一定的顺序,如果希望 Map 集合中的对象也存在一定的顺序,应该使用 TreeMap 类实现 Map 集合。
HashMap 类是基于哈希表的 Map 接口的实现,此实现提供所有可选的映射操作,并允许使用 null 值和 null 键,但必须保证键的唯一性。HashMap 通过哈希表对其内部的映射关系进行快速查找。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap 继承于 AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
常用方法
方法 | 描述 |
---|---|
clear() | 删除 hashMap 中的所有键/值对 |
clone() | 复制一份 hashMap |
isEmpty() | 判断 hashMap 是否为空 |
size() | 计算 hashMap 中键/值对的数量 |
put() | 将键/值对添加到 hashMap 中 |
putAll() | 将所有键/值对添加到 hashMap 中 |
putIfAbsent() | 如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。 |
remove() | 删除 hashMap 中指定键 key 的映射关系 |
containsKey() | 检查 hashMap 中是否存在指定的 key 对应的映射关系。 |
containsValue() | 检查 hashMap 中是否存在指定的 value 对应的映射关系。 |
replace() | 替换 hashMap 中是指定的 key 对应的 value。 |
replaceAll() | 将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。 |
get() | 获取指定 key 对应对 value |
getOrDefault() | 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值 |
forEach() | 对 hashMap 中的每个映射执行指定的操作。 |
entrySet() | 返回 hashMap 中所有映射项的集合集合视图。 |
keySet() | 返回 hashMap 中所有 key 组成的集合视图。 |
values() | 返回 hashMap 中存在的所有 value 值。 |
merge() | 添加键值对到 hashMap 中 |
compute() | 对 hashMap 中指定 key 的值进行重新计算 |
computeIfAbsent() | 对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hasMap 中 |
computeIfPresent() | 对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。 |
import java.util.HashMap;
public class Muster {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "a");
map.put(2, "c");
map.put(3, "b");
map.remove(2); // 删除指定 key 对应的键值对
// 输出 key 和 value
for (Integer i : map.keySet()) {
System.out.println(i + " : " + map.get(i));
}
// 返回所有 value 值
for (String value : map.values()) {
// 输出每一个 value
System.out.println(value);
}
}
}
输出结果:
1 : a
3 : b
a
b
使用总结
TreeMap 类不仅实现了 Map 接口,还实现了 java.util.SortedMap 接口,因此,集合中的映射关系具有一定的顺序。但在添加、删除和定位映射关系时,TreeMap 类比 HashMap 类性能稍差。由于 TreeMap 类实现的 Map 集合中的映射关系是根据键对象按照一定的顺序排列的,因此不允许键对象是 null。
Java 提供了一个操作 List、Set 和 Map 等集合的工具类:Collections,该工具类提供了大量方法对集合进行排序、查询和修改等操作,还提供了将集合对象置为不可变、对集合对象实现同步控制等方法。
这个类不需要创建对象,内部提供的都是静态方法。
排序方法
方法 | 描述 |
---|---|
static void reverse(List> list) | 反转列表中元素的顺序。 |
static void shuffle(List> list) | 对List集合元素进行随机排序。 |
static void sort(List list) | 根据元素的自然顺序 对指定列表按升序进行排序 。 |
static void sort(List list, Comparator super T> c) | 根据指定比较器产生的顺序对指定列表进行排序。 |
static void swap(List> list, int i, int j) | 在指定List的指定位置i,j处交换元素。 |
static void rotate(List> list, int distance) | 当distance为正数时,将List集合的后distance个元素“整体”移到前面; 当distance为负数时,将list集合的前distance个元素“整体”移到后边。该方法不会改变集合的长度。 |
import java.util.ArrayList;
import java.util.Collections;
public class Muster {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(3);
list.add(-2);
list.add(9);
list.add(5);
list.add(-1);
list.add(6);
System.out.println(list); // [3, -2, 9, 5, -1, 6]
Collections.reverse(list); // 集合元素的次序反转
System.out.println(list); // [6, -1, 5, 9, -2, 3]
Collections.sort(list); // 排序:按照升序排序
System.out.println(list); // [-2, -1, 3, 5, 6, 9]
Collections.swap(list, 2, 5); // 根据下标进行交换
System.out.println(list); // [-2, -1, 9, 5, 6, 3]
Collections.rotate(list, 2); // 后两个整体移动到前边
System.out.println(list); // [6, 3, -2, -1, 9, 5]
Collections.shuffle(list); // 随机排序
System.out.println(list); // 每次输出的次序不固定
}
}
查找替换方法
方法 | 描述 |
---|---|
static int binarySearch(List extends Comparable super T>>list, T key) | 使用二分搜索法搜索指定列表,以获得指定对象在List集合中的索引。 |
static Object max(Collection coll) | 根据元素的自然顺序,返回给定collection 的最大元素。 |
static Object max(Collection coll,Comparator comp) | 根据指定比较器产生的顺序,返回给定 collection 的最大元素。 |
static Object min(Collection coll) | 根据元素的自然顺序,返回给定collection 的最小元素。 |
static Object min(Collection coll,Comparator comp) | 根据指定比较器产生的顺序,返回给定 collection 的最小元素。 |
static void fill(List super T> list, T obj) | 使用指定元素替换指定列表中的所有元素。 |
static int frequency(Collection> c, Object o) | 返回指定 collection 中等于指定对象的出现次数。 |
static int indexOfSubList(List> source, List> target) | 返回指定源列表中第一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。 |
static int lastIndexOfSubList(List> source, List> target) | 返回指定源列表中最后一次出现指定目标列表的起始位置;如果没有出现这样的列表,则返回 -1。 |
static boolean replaceAll(List list, T oldVal, T newVal) | 使用一个新值替换List对象的所有旧值oldVal |
import java.util.ArrayList;
import java.util.Collections;
public class Muster {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(3);
list.add(-2);
list.add(9);
list.add(5);
list.add(-1);
list.add(6);
System.out.println(list); // [3, -2, 9, 5, -1, 6]
// 输出最大元素
System.out.println(Collections.max(list)); // 9
// 输出最小元素
System.out.println(Collections.min(list)); // -2
// 将list中的-2用1来代替
System.out.println(Collections.replaceAll(list, -2, 1));
System.out.println(list); // [3, 1, 9, 5, -1, 6]
list.add(9);
// 判断9在集合中出现的次数
System.out.println(Collections.frequency(list, 9)); // 2
// 对集合进行排序
Collections.sort(list);
System.out.println(list); // [-1, 1, 3, 5, 6, 9, 9]
// 只有排序后的list集合才可用二分法查询
System.out.println(Collections.binarySearch(list, 3)); // 2
}
}
同步控制
方法 | 描述 |
---|---|
static Collection synchronizedCollection(Collection c) | 返回指定 collection 支持的同步(线程安全的)collection。 |
static List synchronizedList(List list) | 返回指定列表支持的同步(线程安全的)列表。 |
static |
返回由指定映射支持的同步(线程安全的)映射。 |
static Set synchronizedSet(Set s) | 返回指定 set 支持的同步(线程安全的)set。 |
import java.util.*;
public class Muster {
public static void main(String[] args) {
// 创建四个同步的集合对象
Collection c = Collections.synchronizedCollection(new ArrayList());
List list = Collections.synchronizedList(new ArrayList());
Set set = Collections.synchronizedSet(new HashSet());
Map map = Collections.synchronizedMap(new HashMap());
}
}
不可变集合
方法 | 描述 |
---|---|
emptyXxx() | 返回一个空的、不可变的集合对象。 |
singletonXxx() | 返回一个只包含指定对象(只有一个或一个元素)的不可变的集合对象。 |
unmodifiableXxx() | 返回指定集合对象的不可变视图。 |
import java.util.*;
public class Muster {
public static void main(String[] args) {
// 创建一个空的、不可改变的List对象
List<String> unmodifiableList = Collections.emptyList();
System.out.println(unmodifiableList); // []
// unmodifiableList.add("java"); // 异常
// 创建一个只有一个元素,且不可改变的Set对象
Set<String> unmodifiableSet = Collections.singleton("a");
System.out.println(unmodifiableSet); // [a]
// unmodifiableSet.add("b"); // 异常
//创建一个普通Map对象
Map map = new HashMap();
map.put("a", 1);
map.put("b", 2);
// 返回普通Map对象对应的不可变版本
Map unmodifiableMap = Collections.unmodifiableMap(map);
// unmodifiableMap.put("c", 3); // 异常
}
}