Java中的集合

 

Java中的集合 - 教程

 

Java中的集合几乎用于每个应用程序。Java Collections Framework是Java编程语言的核心部分之一。Java Collections教程将详细介绍Java Collections Framework

 

Java中的集合

  1. 什么是Java Collections Framework?
  2. Java集合接口
  3. Java集合类
  4. 收藏班
  5. 同步包装
  6. 不可修改的包装
  7. 线程安全集合
  8. 集合API算法
  9. Java 8 Collections API功能
  10. Java 10 Collections API更改
  11. Java 11 Collections API更改
  12. 坚果壳中的集合类

 

什么是Java Collections Framework?

集合就像是将多个项目组合在一个单元中的容器。例如; 一罐巧克力,名单等。几乎每种编程语言都使用集合,当Java到达时,它也带有少量的Collection类; 矢量堆栈哈希表数组。Java 1.2提供了Collections Framework,它是以标准方式表示和操作java中的集合的体系结构。Java Collections Framework包含以下部分:

  • 接口:Java Collections Framework接口提供表示集合的抽象数据类型。java.util.Collection是Collections Framework的根接口。它位于Collections框架层次结构的顶部。它包含了一些重要的方法,如size()iterator()add()remove()clear(),每一个集合类必须实现。其他一些重要的接口是java.util.Listjava.util.Setjava.util.Queuejava.util.Map。Map是唯一不从Collection接口继承的接口,但它是Collections框架的一部分。所有集合框架接口都存在于java.util包中。
  • 实现类:Java中的集合为集合提供了核心实现类。我们可以使用它们在java程序中创建不同类型的集合。一些重要的集合类是ArrayListLinkedListHashMapTreeMapHashSetTreeSet。这些类解决我们大部分的编程需求,但如果我们需要一些特殊的集合类,我们可以扩展它们来创建我们的自定义集合类。

    Java 1.5中想出了允许修改集合在遍历它,他们中的一些是线程安全的集合类CopyOnWriteArrayListConcurrentHashMapCopyOnWriteArraySet。这些类位于java.util.concurrent包中。所有集合类存在于java.utiljava.util.concurrent包。

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

下面的类图显示了Collections Framework层次结构。为简单起见,我只包括常用的接口和类。
Java,Java Collections Framework中的集合

 

Java Collections Framework的优点

Java Collections框架具有以下优点:

  • 减少开发工作量 - 它几乎包含所有常见类型的集合以及迭代和操作数据的有用方法。因此,我们可以更专注于业务逻辑而不是设计我们的集合API。
  • 提高质量 - 使用经过良好测试的核心集合类可以提高程序质量,而不是使用任何家庭开发的数据结构。
  • 可重用性和互操作性
  • 减少工作量 - 如果我们使用核心集合API类,学习任何新的API。

Java集合接口

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

为了保持核心集合接口的数量可管理,Java平台不为每个集合类型的每个变体提供单独的接口。如果调用了不受支持的操作,则集合实现会抛出一个UnsupportedOperationException

集合界面

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

接口有方法告诉你集合中有多少元素(sizeisEmpty),以检查给定对象是否在collection(contains)中,从集合中添加和删除元素(addremove),并提供迭代器集合(iterator)。

Collection接口还提供了对整个收集工作批量操作方法- ,containsAlladdAllremoveAll,。retainAllclear

这些toArray方法是作为集合和旧API之间的桥梁提供的,这些API期望输入数组。

迭代器接口

Iterator接口提供迭代任何Collection的方法。我们可以使用iterator方法从Collection中获取iterator实例。Iterator取代了EnumerationJava Collections Framework。迭代器允许调用者在迭代期间从底层集合中删除元素。集合类中的迭代器实现了迭代器设计模式

设置界面

Set是一个不能包含重复元素的集合。该界面对数学集抽象进行建模,并用于表示集合,例如卡片组。

Java平台包含三个通用Set实现:HashSetTreeSet,和LinkedHashSet。Set接口不允许随机访问Collection中的元素。您可以使用迭代器或foreach循环遍历Set的元素。

列表界面

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

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

List strList = new ArrayList<>(); //add at last strList.add(0, "0"); //add at specified index strList.add(1, "1"); //replace strList.set(1, "2"); //remove strList.remove("1");

-集合类列表提供了一些有用的算法sortshufflereversebinarySearch等。

队列接口

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

队列通常(但不一定)以FIFO(先进先出)方式对元素进行排序。除了优先级队列之外,优先级队列根据提供的比较器或元素的自然顺序对元素进行排序。无论使用什么顺序,队列的头部是通过调用删除或轮询删除的元素。在FIFO队列中,所有新元素都插入队列的尾部。

出列接口

线性集合,支持两端插入和移除元素。名称deque是“双端队列”的缩写,通常发音为“deck”。大多数Deque实现对它们可能包含的元素数量没有固定限制,但是此接口支持容量限制的deques以及没有固定大小限制的deques。

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

地图界面

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

Java平台包含三个通用Map实现:HashMapTreeMap,和LinkedHashMap

地图的基本操作是putgetcontainsKeycontainsValuesize,和isEmpty

ListIterator接口

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

Java ListIterator没有当前元素; 它的光标位置总是位于调用previous()返回的元素和调用next()返回的元素之间。

SortedSet接口

SortedSet是一个按升序维护其元素的Set。提供了几个额外的操作以利用订购。排序集用于自然排序的集合,例如单词列表和成员资格卷。

SortedMap接口

以升序键顺序维护其映射的映射。这是SortedSet的Map模拟。排序映射用于自然排序的键/值对集合,例如字典和电话目录。

Java集合类

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

HashSet类

Java HashSet是由HashMap支持的Set接口的基本实现。它不保证集合的迭代顺序并允许null元素。

这个类提供了固定的时间表现为基本操作(addremovecontainssize),假定哈希函数将分散的桶中正确的元素。我们可以为此集合设置初始容量和负载因子。负载因子是在其容量自动增加之前允许哈希映射获得的完整程度的度量。

TreeSet类

NavigableSet基于a 的实现TreeMap。元素按照它们的自然顺序排序,或者根据Comparator设置的创建时间提供,具体取决于使用的构造函数。

参考:Java Comparable Comparator

此实现为基本操作(添加,删除和包含)提供了有保证的log(n)时间成本。

请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致。(有关与equals一致的精确定义,请参阅Comparable或Comparator。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的。

ArrayList类

Java ArrayList是List接口的可调整大小的数组实现。实现所有可选列表操作,并允许所有元素,包括null。除了实现List接口之外,此类还提供了一些方法来操作内部用于存储列表的数组的大小。(这个类大致相当于Vector,除了它是不同步的。)

size,isEmpty,get,set,iterator和listIterator操作以恒定时间运行。添加操作以分摊的常量时间运行,即添加n个元素需要O(n)时间。所有其他操作都以线性时间运行(粗略地说)。与LinkedList实现相比,常数因子较低。

进一步阅读:Java ArrayList和Iterator

LinkedList类

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

对于双向链表,所有操作都可以预期。索引到列表中的操作将从开头或结尾遍历列表,以较接近指定索引为准。

HashMap类

基于哈希表的Map接口实现。此实现提供所有可选的映射操作,并允许空值和空键。HashMap类大致相当于Hashtable,除了它是不同步的并允许null。此类不保证地图的顺序。

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

进一步阅读:HashMap vs ConcurrentHashMap

TreeMap类

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

此实现为containsKey,get,put和remove操作提供有保证的log(n)时间成本。算法是Cormen,Leiserson和Rivest的算法导论中的算法的改编。

请注意,如果此有序映射要正确实现Map接口,则TreeMap维护的排序(如任何有序映射,以及是否提供显式比较器)必须与equals一致。(有关与equals一致的精确定义,请参见Comparable或Comparator。)这是因为Map接口是根据equals操作定义的,但是有序映射使用compareTo(或compare)方法执行所有键比较,因此从排序映射的角度来看,通过此方法被视为相等的键是相等的。即使排序与equals不一致,也可以很好地定义有序映射的行为。它只是不遵守Map接口的一般合同。

PriorityQueue类

队列按FIFO顺序处理它的元素,但有时我们希望根据优先级处理元素。在这种情况下我们可以使用PriorityQueue,我们需要在实例化PriorityQueue时提供Comparator实现。PriorityQueue不允许空值,并且它是无限制的。有关这方面的更多详细信息,请转到Java Priority Queue,您可以使用示例程序检查它的使用情况。

收藏班

Java Collections类仅包含对集合进行操作或返回集合的静态方法。它包含对集合进行操作的多态算法,“包装器”,它返回由指定集合支持的新集合,以及其他一些可能的结果。

此类包含用于集合框架算法的方法,例如二进制搜索,排序,重排,反向等。

同步包装

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

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

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

不可修改的包装

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

  • 在构建集合后使集合不可变。在这种情况下,最好不要维护对支持集合的引用。这绝对保证了不变性。
  • 允许某些客户端以只读方式访问您的数据结构。您保留对支持集合的引用,但分发对包装器的引用。通过这种方式,客户可以查看但不能修改,同时保持完全访问权限。

这些方法是;

public static Collection unmodifiableCollection(Collection<? extends T> c); public static Set unmodifiableSet(Set<? extends T> s); public static List unmodifiableList(List<? extends T> list); public static <K,V> Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> m); public static SortedSet unmodifiableSortedSet(SortedSet<? extends T> s); public static <K,V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K, ? extends V> m);

线程安全集合

Java 1.5 Concurrent package(java.util.concurrent)包含线程安全的集合类,允许在迭代时修改集合。通过设计迭代器是快速失败并抛出ConcurrentModificationException。有些班是CopyOnWriteArrayListConcurrentHashMapCopyOnWriteArraySet

阅读这些帖子以更详细地了解它们。

集合API算法

Java Collections Framework提供常用的算法实现,例如排序和搜索。Collections类包含这些方法实现。大多数这些算法都在List上工作,但其中一些算法适用于各种集合。

排序

排序算法重新排序List,以便其元素根据排序关系按升序排列。提供了两种形式的操作。简单形式采用List并根据其元素的自然顺序对其进行排序。排序的第二种形式除了List之外还使用Comparator并使用Comparator对元素进行排序。

洗牌

随机播放算法会破坏列表中可能存在的任何顺序跟踪。也就是说,该算法基于来自随机源的输入重新排序列表,使得假设公平的随机源,所有可能的排列以相等的可能性发生。该算法在实现机会游戏时很有用。

搜索

binarySearch算法搜索已排序List中的指定元素。该算法有两种形式。第一个采用List和要搜索的元素(“搜索关键字”)。此表单假定List按照其元素的自然顺序按升序排序。除了List和搜索键之外,第二种形式还使用Comparator,并假定List按照指定的Comparator按升序排序。排序算法可用于在调用binarySearch之前对List进行排序。

组成

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

  • frequency:计算指定元素在指定集合中出现的次数
  • disjoint:确定两个集合是否不相交; 也就是说,它们是否不包含任何共同的元素

最小值和最大值

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

Java 8 Collections API功能

Java 8最大的变化与Collection API有关。一些重要的变化和改进是:

  1. 引入用于顺序和并行处理的Stream API,您应该阅读Java Stream API Tutorial以获取更多详细信息。
  2. 可迭代接口已使用forEach()默认方法进行扩展,以迭代集合。
  3. Lambda表达式和功能接口主要用于Collection API类。

Java 10 Collections API更改

  1. List.copyOf,Set.copyOf和Map.copyOf方法用于创建不可修改的集合。
  2. Collectors类获取了各种收集不可修改集合的方法(Set,List,Map)。这些方法名称是UnmodifiableList,toUnmodifiableSet和toUnmodifiableMap。

让我们看一下这些新的Java 10 Collections API方法用法的示例。

package com.journaldev.collections; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class JDK10CollectionFunctions { public static void main(String[] args) { // 1. List, Set, Map copyOf(Collection) method List<String> actors = new ArrayList<>(); actors.add("Jack Nicholson"); actors.add("Marlon Brando"); System.out.println(actors); // prints [Jack Nicholson, Marlon Brando] // New API added - Creates an UnModifiable List from a List. List<String> copyOfActors = List.copyOf(actors); System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando] // copyOfActors.add("Robert De Niro"); Will generate // UnsupportedOperationException actors.add("Robert De Niro"); System.out.println(actors); // prints [Jack Nicholson, Marlon Brando, Robert De Niro] System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando] // 2. Collectors class toUnmodifiableList, toUnmodifiableSet, and // toUnmodifiableMap methods List<String> collect = actors.stream().collect(Collectors.toUnmodifiableList()); System.out.println(collect); } }

Java 11 Collections API更改

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

package com.journaldev.collections; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class JDK11CollectionFunctions { public static void main(String[] args) { /* * JDK 11 New Method in Collection interface * default <T> T[] toArray(IntFunction<T[]> generator) { * return toArray(generator.apply(0)); } */ List<String> strList = new ArrayList<>(); strList.add("Java"); strList.add("Python"); strList.add("Android"); String[] strArray = strList.toArray(size -> new String[size]); System.out.println(Arrays.toString(strArray)); strArray = strList.toArray(size -> new String[size + 5]); System.out.println(Arrays.toString(strArray)); strArray = strList.toArray(size -> new String[size * 3]); System.out.println(Arrays.toString(strArray)); } }

输出:

 [Java, Python, Android] [Java, Python, Android, null, null] [Java, Python, Android]

坚果壳中的集合类

下表提供了常用集合类的基本细节。

下载URLJava集合类

✎编辑标志

 

采集 订购 随机访问 核心价值 重复元素 空元素 线程安全
数组列表 ✅ ✅ ❌ ✅ ✅ ❌
链表 ✅ ❌ ❌ ✅ ✅ ❌
HashSet的 ❌ ❌ ❌ ❌ ✅ ❌
TreeSet中 ✅ ❌ ❌ ❌ ❌ ❌
HashMap中 ❌ ✅ ✅ ❌ ✅ ❌
TreeMap的 ✅ ✅ ✅ ❌ ❌ ❌
向量 ✅ ✅ ❌ ✅ ✅ ✅
哈希表 ❌ ✅ ✅ ❌ ❌ ✅
属性 ❌ ✅ ✅ ❌ ❌ ✅
✅ ❌ ❌ ✅ ✅ ✅
的CopyOnWriteArrayList ✅ ✅ ❌ ✅ ✅ ✅
的ConcurrentHashMap ❌ ✅ ✅ ❌ ❌ ✅
CopyOnWriteArraySet ❌ ❌ ❌ ❌ ✅ ✅