Java 中的集合--你必须知道的一切

Java集合框架是Java编程语言的核心部分之一。集合几乎在每种编程语言中使用。大多数编程语言都支持各种类型的集合,如ListsetQueueStack等。

什么是Java集合框架?

集合就像将多个项组合在一个单元中的容器。例如,一罐巧克力,一份名单,等等。

集合在每种编程语言中都有使用,当Java到来时,它也有一些集合类- Vector ,** Stack** ,** Hashtable** ,** Array** 。

Java 1.2提供了集合框架 ,这是以标准方式在Java中表示和操作集合的架构。Java集合框架由以下部分组成:

1.接口

Java集合框架接口提供了表示集合的抽象数据类型。

_java.util.Collection_是集合框架的根接口。它位于集合框架层次结构的顶部。它包含一些重要的方法,如每个Collection类都必须实现的Size()、Iterator()、Add()、Remove()、Clear()。

其他一些重要的接口是java.util.List、java.util.Set、java.util.Queue和java.util.Map。Map是唯一一个不是从Collection接口继承的接口,但它是Collections框架的一部分。所有集合框架接口都存在于java.util包中。

2.实现类

Java集合框架为核心集合接口提供了实现类。我们可以使用它们在Java程序中创建不同类型的集合。

一些重要的集合类包括ArrayList、LinkedList、HashMap、TreeMap、HashSet和TreeSet。这些类解决了我们的大部分编程需求,但如果我们需要一些特殊的集合类,我们可以扩展它们来创建我们的定制集合类。

Java 1.5提出了线程安全的集合类,允许我们在迭代集合时修改它们。其中一些是CopyOnWriteArrayList、ConCurrentHashMap、CopyOnWriteArraySet。这些类位于java.util.current包中。

所有的集合类都存在于java.util和java.util.current包中。

3.算法

算法是提供一些常见功能的有用方法,例如搜索、排序和洗牌。

集合框架类图

下面的类关系图显示了集合框架的层次结构。为了简单起见,我只包括了常用的接口和类。

JAVA集合类Hierarchy

Java集合框架的好处

Java Collections框架有以下优点:

  • 减少开发工作量 -它提供了几乎所有常见类型的集合和用于迭代和操作数据的有用方法。因此,我们可以更多地专注于业务逻辑,而不是设计我们的集合API。
  • 更好的质量 -使用经过良好测试的核心集合类可以提高我们的程序质量,而不是使用任何自主开发的数据结构。
  • 可重用性和互操作性
  • 省力 维护,因为大家都知道Collection API类。

Java集合API接口

Java集合接口是Java集合框架的基础。请注意,所有核心集合接口都是泛型的;例如,公共接口Collection语法用于Generics,当我们声明集合时,我们应该使用它来指定它可以包含的对象类型。它通过在编译时对对象进行类型检查来帮助减少运行时错误。

为了使核心集合接口的数量易于管理,Java平台没有为每个集合类型的每个变体提供单独的接口。如果调用了不支持的操作,则集合实现将引发UnsupportedOperationException异常。

1.采集接口

这是集合层次结构的根。集合表示一组称为其元素的对象。Java平台不提供该接口的任何直接实现。

该接口有一些方法可以告诉您集合中有多少个元素(Size,isEmpty),检查给定对象是否在集合中(CONTAINS),在集合中添加和移除元素(Add,Remove),以及在集合上提供迭代器(Iterator)。

集合接口还提供了在整个集合上工作的批量操作方法--包含全部、添加全部、移除全部、保留全部、清除。

ToArray方法是作为集合和旧的API之间的桥梁提供的,这些API需要输入上的数组。

2.迭代器接口

Iterator接口提供了遍历Collection元素的方法。我们可以使用iterator()方法来获取iterator的实例。迭代器在Java集合框架中取代了枚举。迭代器允许调用方在迭代过程中从基础集合中移除元素。集合类中的迭代器实现 [迭代器设计模式](/community/tutorials/iterator-design-pattern-java)

3.设置接口

Set是不能包含重复元素的集合。该接口对数学集合抽象进行建模,并用于表示集合,例如一副纸牌。

JAVA平台包含三个通用的Set实现:HashSetTreeSetLinkedHashSet。Set接口不允许对集合中的元素进行随机访问。您可以使用迭代器或Foreach循环来遍历集合的元素。

4.列表接口

列表是一个有序集合,可以包含重复的元素。您可以从其索引中访问任何元素。列表更像是具有动态长度的数组。列表是最常用的集合类型之一。ArrayListLinkedList是List接口的实现类。

List接口提供了有用的方法来在特定索引处添加元素,基于索引删除/替换元素以及使用索引获取子列表。

 1List strList = new ArrayList<>();
 2
 3//add at last
 4strList.add(0, "0");
 5
 6//add at specified index
 7strList.add(1, "1");
 8
 9//replace
10strList.set(1, "2");
11
12//remove
13strList.remove("1");

Collection类为列表排序、置乱、反转、二进制搜索等提供了一些有用的算法。

5.提示接口

Queue是一个集合,用于在处理前保存多个元素。除了基本的收集操作外,队列还提供附加的插入、提取和检查操作。

队列通常(但不一定)以FIFO(先进先出)方式对元素进行排序。优先级队列是例外,它根据提供的比较器或元素的自然排序对元素进行排序。无论使用哪种排序,队列头都是将通过调用Remove或Poll删除的元素。在FIFO队列中,所有新元素都插入到队列的尾部。

6.

支持在两端插入和删除元素的线性集合。DQUE是双端队列的缩写,通常读作Deck。大多数Deque实现对它们可以包含的元素数量没有固定的限制,但该接口支持容量受限的Dequence以及没有固定大小限制的Dequence。

该接口定义了访问双队列两端的元素的方法。提供了插入、移除和检查元素的方法。

7.地图界面

Java Map是一个将键映射到值的对象。映射不能包含重复的键:每个键最多可以映射到一个值。

Java平台包含三个通用Map实现:HashMap、TreeMap和LinkedHashMap。

Map的基本操作有PUT、GET、CONTAINS Key、CONTAINS Value、SIZE和isEmpty。

8.ListIterator接口

用于列表的迭代器,允许程序员在任一方向上遍历列表,在迭代期间修改列表,并获得迭代器在列表中的当前位置。

[Java ListIterator](/community/tutorials/java-listiterator)没有当前元素;它的光标位置总是位于调用previous()返回的元素和调用next()返回的元素之间。

9.SortedSet接口

SortedSet是以升序维护其元素的集合。为了利用排序,还提供了几个附加操作。排序集合用于自然排序的集合,例如单词列表和成员名单。

10.SortedMap接口

按键升序维护其映射的映射。这是SortedSet的地图模拟。排序映射用于键/值对的自然有序集合,例如字典和电话簿。

Java集合类

Java集合框架附带了许多接口的实现类。最常见的实现是ArrayListHashMap和HashSet。Java 1.5包括并发实现;例如,ConCurrentHashMap和CopyOnWriteArrayList。通常,集合类不是线程安全的,并且它们的迭代器是快速失败的。在本节中,我们将了解常用的集合类。

1.HashSet类

[Java HashSet](/community/tutorials/java-hashset)是Set接口的基本实现,由[HashMap](/community/tutorials/java-hashmap)支持。它不保证集合的迭代顺序,并允许 null 元素。

这个类为基本操作(addemovetainssize)提供恒定的时间性能,假设散列函数将元素适当地分布在存储桶中。我们可以设置此集合的初始容量和负载率。负载系数是衡量哈希图在其容量自动增加之前可以达到的满度。

2.TreeSet类

基于TreeMapNavigableSet实现。根据所使用的构造函数,使用元素的自然顺序或通过在集合创建时提供的比较程序对元素进行排序。

参考:JAVA可比Comparator

该实现为基本操作(添加、删除和包含)提供了有保证的log(N)时间开销。

请注意,如果要正确实现Set接口,则Set维护的顺序(无论是否提供显式比较器)必须与EQUALS一致。(有关与相等一致的准确定义,请参阅可比或比较项。)这是因为set接口是根据equals操作定义的,而TreeSet实例使用其CompareTo(或Compare)方法执行所有元素比较,因此从set的角度来看,此方法认为相等的两个元素是相等的。

3. ArrayList类

JAVA ArrayList是List接口的可调整大小的数组实现。实现所有可选的列表操作,并允许所有元素,包括NULL。除了实现List接口外,此类还提供用于操作内部用于存储列表的数组大小的方法。(除了它是不同步的以外,这个类大致等同于向量。)

Size、isEmpty、Get、Set、Iterator和List迭代器操作在固定时间内运行。加法运算在分期恒定时间内运行,即添加n个元素需要O(N)时间。所有其他操作都在线性时间内运行(粗略地说)。与LinkedList实现相比,常量系数较低。

进一步阅读:[Java ArrayList和Iterator](/community/tutorials/copyonwritearraylist-java)

4.LinkedList类

实现双向链表的List和Deque接口。实现所有可选的列表操作,并允许所有元素(包括NULL)。

所有操作都按照双向链表的预期执行。索引到列表中的操作将从开始或结束处遍历列表,无论哪个更接近指定的索引。

5. HashMap类

基于哈希表的Map接口实现。该实现提供了所有可选的映射操作,并允许空值和空键。HashMap类大体上等同于Hashtable,只是它是不同步的,并且允许为空。这个类不保证映射的顺序。

该实现为基本操作(getput)提供了恒定的时间性能。它提供构造函数来设置集合的初始容量和负载系数。

进一步阅读:Hashmap vs ConcurrentHashMap

6.树形图类

一个基于红黑树的NavigableMap实现。根据使用的构造函数,映射根据其键的自然顺序进行排序,或者通过在映射创建时提供的比较器进行排序。

该实现为tainsKey、GET、PUT和REMOVE操作提供了有保证的log(N)时间开销。算法是对科曼、莱瑟森和里维斯特的算法导论中算法的改编。

请注意,与任何排序的映射一样,树映射维护的排序,无论是否提供显式比较器,如果该排序的映射要正确实现Map接口,则必须与等于一致。(有关与相等一致的准确定义,请参阅可比或比较项。)这是因为Map接口是根据equals操作定义的,但排序映射使用其CompareTo(或Compare)方法执行所有键比较,因此从排序映射的角度来看,此方法认为相等的两个键是相等的。排序映射的行为是明确定义的,即使它的排序与相等不一致;它只是不遵守Map接口的通用约定。

7. PriorityQueue类

队列按FIFO顺序处理其元素,但有时我们希望根据元素的优先级来处理元素。在这种情况下,我们可以使用PriorityQueue,并且在实例化PriorityQueue时需要提供一个比较器实现。PriorityQueue不允许空值,并且它是无界的。有关这一点的更多详细信息,请访问**JAVA优先级Queue** ,在那里您可以用一个示例程序检查它的用法。

收集类

Java Colltions class完全由对集合进行操作或返回集合的静态方法组成。它包含对集合进行操作的多态算法、返回由指定集合支持的新集合的包装器,以及其他一些零碎的东西。

此类包含用于集合框架算法的方法,如BINARY search,SORT,Shuffling,Reverse等。

同步包装器

同步包装器将自动同步(线程安全)添加到任意集合。六个核心集合接口--Collection、Set、List、Map、SortedSet和SortedMap--都有一个静态工厂方法。

1public static Collection synchronizedCollection(Collection c);
2public static Set synchronizedSet(Set s);
3public static List synchronizedList(List list);
4public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m);
5public static SortedSet synchronizedSortedSet(SortedSet s);
6public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m);

这些方法中的每一个都返回由指定集合备份的同步(线程安全)集合。

不可修改的包装器

不可修改的包装器通过拦截所有会修改集合的操作并抛出一个UnsupportedOperationException来取消修改集合的能力。它的主要用途是;

  • 在生成集合后使其不可变。在这种情况下,最好不要维护对支持集合的引用。这绝对保证了不变性。
  • 允许某些客户端只读访问您的数据结构。您保留对支持集合的引用,但传递对包装器的引用。这样,客户端可以查看但不能修改,而您可以保持完全访问权限。
1public static Collection unmodifiableCollection(Collection<? extends T> c);
2public static Set unmodifiableSet(Set<? extends T> s);
3public static List unmodifiableList(List<? extends T> list);
4public static <K,V> Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> m);
5public static SortedSet unmodifiableSortedSet(SortedSet<? extends T> s);
6public static <K,V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K, ? extends V> m);

线程安全集合类

Java 1.5并发包(java.util.concurent)包含线程安全的集合类,允许在迭代时修改集合。根据设计,迭代器是快速失败的,并抛出ConcurentModificationException异常。这些类中有CopyOnWriteArrayListConcurentHashMapCopyOnWriteArraySet

集合API算法

Java集合框架提供了常用的算法实现,如排序和搜索。集合类包含这些方法实现。这些算法大多工作在列表上,但也有一些算法适用于所有类型的集合。

1.排序

排序算法根据排序关系对列表进行重新排序,使其元素按升序排列。提供了两种形式的操作。简单形式获取一个列表,并根据其元素的自然顺序对其进行排序。排序的第二种形式除了接受列表之外,还接受一个比较器,并使用比较器对元素进行排序。

2.洗牌

混洗算法破坏了列表中可能存在的任何顺序痕迹。也就是说,该算法基于来自随机性来源的输入对列表重新排序,使得假设公平的随机性来源,所有可能的排列以相等的可能性发生。该算法在实现机会博弈时是有用的。

3.搜索

BinarySearch算法在排序列表中搜索指定的元素。该算法有两种形式。第一个获取要搜索的列表和元素()。

此表单假定列表按照其元素的自然顺序按升序排序。

第二种形式除了List和搜索关键字之外还需要一个Comparator,并假设列表根据指定的Comparator按升序排序。

排序算法可用于在调用binarySearch之前对列表进行排序。

4.组合物

频率和分离算法测试一个或多个集合的组成的某些方面。

  • 频率 :统计指定元素在指定集合中出现的次数
  • 不相交 :确定两个集合是否不相交;即它们是否不包含公共元素

5.最小值和最大值

min和max算法分别返回指定Collection中包含的最小和最大元素。这两种操作都有两种形式。简单形式只接受一个Collection,并根据元素的自然顺序返回最小(或最大)元素。

Java 8集合API功能

Java 8最大的变化与集合API有关。一些重要的变化和改进包括:

1.Stream API介绍,支持顺序处理和并行处理,请阅读Java Stream API教程了解更多详情。 2.Iterable接口扩展了forEach()默认方法,用于迭代集合。 3.Lambda API和函数接口对于Collection Expression类最有好处。

Java 10集合API变更

1.用于创建不可修改集合的List.CopyOf、Set.CopyOf和Map.CopyOf方法。 收集器类获取收集不可修改集合的各种方法(Set、List、Map)。这些方法名分别为toUnModifiableList、toUnModifiableSet和toUnModifiableMap。

让我们来看看这些新的Java 10集合API方法用法的示例。

 1package com.journaldev.collections;
 2
 3import java.util.ArrayList;
 4import java.util.List;
 5import java.util.stream.Collectors;
 6
 7public class JDK10CollectionFunctions {
 8
 9    public static void main(String[] args) {
10
11    	// 1. List, Set, Map copyOf(Collection) method
12    	List<String> actors = new ArrayList<>();
13
14    	actors.add("Jack Nicholson");
15    	actors.add("Marlon Brando");
16
17    	System.out.println(actors);
18    	// prints [Jack Nicholson, Marlon Brando]
19
20    	// New API added - Creates an UnModifiable List from a List.
21    	List<String> copyOfActors = List.copyOf(actors);
22
23    	System.out.println(copyOfActors);
24    	// prints [Jack Nicholson, Marlon Brando]
25
26    	// copyOfActors.add("Robert De Niro"); Will generate
27    	// UnsupportedOperationException
28
29    	actors.add("Robert De Niro");
30
31    	System.out.println(actors);
32    	// prints [Jack Nicholson, Marlon Brando, Robert De Niro]
33
34    	System.out.println(copyOfActors);
35    	// prints [Jack Nicholson, Marlon Brando]
36
37    	// 2. Collectors class toUnmodifiableList, toUnmodifiableSet, and
38    	// toUnmodifiableMap methods
39    	List<String> collect = actors.stream().collect(Collectors.toUnmodifiableList());
40    	System.out.println(collect);
41    }
42
43}

Java 11集合API更改

Collection接口新增默认方法toArray(IntFunction<T[]>生成器)。此方法返回一个包含此集合中所有元素的数组,使用提供的生成器函数来分配返回的数组。

 1package com.journaldev.collections;
 2
 3import java.util.ArrayList;
 4import java.util.Arrays;
 5import java.util.List;
 6
 7public class JDK11CollectionFunctions {
 8
 9    public static void main(String[] args) {
10
11    	/*
12    	 * JDK 11 New Method in Collection interface 
13    	 * default <T> T[] toArray(IntFunction<T[]> generator) {
14    	 * return toArray(generator.apply(0)); }
15    	 */
16
17    	List<String> strList = new ArrayList<>();
18    	strList.add("Java");
19    	strList.add("Python");
20    	strList.add("Android");
21
22    	String[] strArray = strList.toArray(size -> new String[size]);
23    	System.out.println(Arrays.toString(strArray));
24
25    	strArray = strList.toArray(size -> new String[size + 5]);
26    	System.out.println(Arrays.toString(strArray));
27
28    	strArray = strList.toArray(size -> new String[size * 3]);
29    	System.out.println(Arrays.toString(strArray));
30    }
31
32}

输出:

1[Java, Python, Android]
2[Java, Python, Android, null, null]
3[Java, Python, Android]

简而言之,集合类

下表提供了常用集合类的基本详细信息。

下载地址JAVA集合Classes

| 收集|订购|随机存取|键值|重复元素|Null元素|线程安全| | - -|- -|- -|- -|- -|- -|- -| | ArrayList| ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | | LinkedList| ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | | HashSet| ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | | TreeSet| ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | HashMap| ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | | TreeMap| ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | | 向量| ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | | Hashtable| ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | | 性能| ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | | 堆叠| ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | | CopyOnWriteArrayList| ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | | ConcurrentHashMap| ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | | CopyOnWriteArraySet| ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |

我希望本教程解释了Java集合框架中的大多数主题。请在评论中分享您的观点。

参考资料:ORACLE Documentation

Published At
Categories with 技术
Tagged with
comments powered by Disqus