概述

java.util 包中提供了一些集合类,这些集合类又被称为容器。提到容器不难想到数组,集合类与数组的不同之处是,数组的长度是固定的,集合的长度是可变的;数组用来存放基本类型的数据,集合用来存放对象的引用。常用的集合有 List 集合、Set 集合和 Map 集合,其中 List 与 Set 继承了 Collection 接口,各接口还提供了不同的实现类。

在这里插入图片描述

集合接口类特性:

  • Collection 接口存储一组不唯一,无序的对象。
  • List 接口存储一组不唯一,有序(插入顺序)的对象。
  • Set 接口存储一组唯一,无序的对象。
  • Map 接口存储一组键值对象,提供key(键)到value(值)的映射。

Set 和 List 的区别:

  1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。

  2. Set 检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。

  3. List 和数组类似,可以动态增长,根据实际存储的数据的长度自动增长 List 的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变。

Collection接口

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集合

List 接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问 List 中的元素,第一个元素的索引为 0,而且允许有相同的元素。

List 接口的常用实现类有 ArrayList 与 LinkedList。

ArrayList

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

使用总结

  • ArrayList 可以存放 null。
  • ArrayList 本质上就是一个 elementData 数组。
  • ArrayList 区别于数组的地方在于能够自动扩展大小,其中关键的方法就是 gorw() 方法。
  • ArrayList 中 removeAll(collection c) 和 clear() 的区别就是 removeAll 可以删除批量指定的元素,而 clear 是全是删除集合中的元素。
  • ArrayList 由于本质是数组,所以它在数据的查询方面会很快,而在插入删除这些方面,性能下降很多,有移动很多数据才能达到应有的效果。
  • ArrayList 实现了RandomAccess,所以在遍历它的时候推荐使用 for 循环。

LinkedList

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

使用总结

  • LinkedList 本质上是一个双向链表,通过一个 Node 内部类实现的这种链表结构。
  • LinkedList 可以存放 null。
  • LinkedList 跟 ArrayList 相比较,在删除和增加等操作上性能好,而 ArrayList 在查询的性能上好。
  • LinkedList 从源码中看,它不存在容量不足的情况。
  • LinkedList 不光能够向前迭代,还能像后迭代,并且在迭代的过程中,可以修改值、添加值、还能移除值。
  • LinkedList 不光能当链表,还能当队列使用,这个就是因为实现了 Deque 接口。

Set集合

Set 集合中的对象不按特定的方式排序,只是简单地把对象加入集合中,但 Set 集合中不能包含重复对象。Set 集合由 Set 接口和 Set 接口的实现类组成。Set 接口继承了 Collection 接口,因此包含 Collection 接口的所有方法。

Set 接口常用的实现类有 HashSet 与 TreeSet。

HashSet

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

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集合

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

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

使用总结

  • hashMap 在 JDK1.8 以前是一个链表散列这样一个数据结构,而在 JDK1.8 以后是一个数组加链表加红黑树的数据结构。
  • hashMap 是一个能快速通过 key 获取到 value 值得一个集合,原因是内部使用的是 hash 查找值得方法。

TreeMap

TreeMap 类不仅实现了 Map 接口,还实现了 java.util.SortedMap 接口,因此,集合中的映射关系具有一定的顺序。但在添加、删除和定位映射关系时,TreeMap 类比 HashMap 类性能稍差。由于 TreeMap 类实现的 Map 集合中的映射关系是根据键对象按照一定的顺序排列的,因此不允许键对象是 null。

Collections工具类

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 <K,V> Map<K,V> synchronizedMap(Map<K,V> m)返回由指定映射支持的同步(线程安全的)映射。
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); // 异常
    }
}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐