首页 > 编程语言 >java集合框架的详细学习

java集合框架的详细学习

时间:2024-12-18 23:56:16浏览次数:9  
标签:java 框架 队列 元素 接口 线程 数组 集合

 集合框架和数组的区别

为什么引入集合概念

使用数组具有局限性:是一种固定大小的数据结构,其元素类型和数量在创建时就已经确定,并且无法更改,不使用就浪费了。

为了解决数组的局限性,引入容器类的概念。容器可以根据需要动态地增加或减少元素。此外,集合框架还提供了丰富的操作方法,如添加、删除、查找、排序等,使得操作数据更加便捷。

区别:

1.存储方式
  • 数组:数组是一种固定大小的数据结构,其元素类型和数量在创建时就已经确定,并且无法更改。数组通过索引来访问元素,索引从0开始,直到数组长度减1。

  • 集合框架:集合框架提供了多种数据结构,如列表(List)、集合(Set)、映射(Map)等,这些数据结构可以根据需要动态地改变大小。集合框架中的容器类可以存储不同类型的对象,并通过迭代器(Iterator)或增强的for循环进行遍历。

2. 灵活性
  • 数组:数组的灵活性较差,一旦创建,其大小就不能改变。如果需要存储更多元素,必须创建一个新的数组,并将旧数组的元素复制到新数组中。

  • 集合框架:集合框架提供了多种灵活的容器类,这些容器类可以根据需要动态地增加或减少元素。此外,集合框架还提供了丰富的操作方法,如添加、删除、查找、排序等,使得操作数据更加便捷。

3. 数据类型
  • 数组:数组中的元素类型必须相同,这是由数组在创建时指定的数据类型决定的。

  • 集合框架:集合框架中的容器类可以存储不同类型的对象,甚至可以是空对象(null)。此外,集合框架还提供了泛型支持,可以在创建容器时指定元素类型,从而避免类型转换错误。

4. 内存管理
  • 数组:数组是静态分配的,即在创建时就分配了固定大小的内存空间。如果数组过大,会浪费内存资源;如果数组过小,则无法满足存储需求。

  • 集合框架:集合框架中的容器类通常是动态分配的,即根据实际需要动态地分配内存空间。这样可以更有效地利用内存资源,避免内存浪费。

5. 迭代方式
  • 数组:数组的迭代通常使用传统的for循环或增强的for循环(foreach)。

  • 集合框架:集合框架提供了迭代器(Iterator)接口和增强的for循环(foreach)来遍历容器中的元素。迭代器提供了一种统一的方式来遍历不同类型的集合容器,而增强的for循环则提供了一种更简洁的语法来遍历集合容器中的元素。

6. 线程安全性
  • 数组:数组本身是线程不安全的,即多个线程可以同时访问和修改同一个数组的元素,这可能导致数据不一致的问题。

  • 集合框架:集合框架中的部分容器类(如Vector、Hashtable等)是线程安全的,它们内部使用了同步机制来确保线程安全。然而,大多数容器类(如ArrayList、HashMap等)并不是线程安全的。如果需要线程安全的集合容器,可以使用Collections类中的静态方法将非线程安全的容器类包装成线程安全的容器类,或者使用Java并发包(java.util.concurrent)中的并发集合类。

JAVA集合框架图

(为方便理解,下图转载自菜鸟教程,地址是:Java 集合框架 | 菜鸟教程

集合遍历的主要方法:

  • 用for循环遍历
  • 迭代器遍历
  • 用增强型for循环

for循环遍历

 List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");
 
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

迭代器遍历

 Set<String> set = new HashSet<>();
        set.add("X");
        set.add("Y");
        set.add("Z");
 
        Iterator<String> setIterator = set.iterator();
        while (setIterator.hasNext()) {
            System.out.println(setIterator.next());
        }
 

增强型for循环

List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");
 
        for (String item : list) {
            System.out.println(item);
        }

1.Collection接口

  • Collection接口继承自Iterable接口
  • Collection:这是集合框架的根接口,提供了集合的基本操作,如添加、删除、遍历等。这个接口本身并不直接实现任何功能,而是由它的子接口(如List、Set和Queue)来提供具体的实现。同时也是Deque的接口,但是Deque不是Collection的直接子接口,Deque是Queue的直接子接口。
  • 不能直接实例化Collection接口,而是需要使用它的实现类,如ArrayListLinkedListHashSet

接口主要方法:

  • boolean add(E e):向集合中添加一个元素。如果集合因为调用而发生变化(即该元素尚未存在于集合中),则返回true。
  • boolean remove(Object o):从集合中移除一个指定的元素。如果集合包含指定的元素,则移除它并返回true。
  • boolean contains(Object o):检查集合是否包含指定的元素。
  • int size():返回集合中的元素数量。
  • boolean isEmpty():检查集合是否为空。
  • Iterator<E> iterator():返回一个迭代器,用于遍历集合中的元素。
  • Object[] toArray():返回一个包含集合中所有元素的数组。
  • <T> T[] toArray(T[] a):返回一个包含集合中所有元素的数组,其运行时类型与指定数组的类型相同(如果数组足够大以容纳集合中的所有元素;否则,返回一个具有指定类型的新数组,其长度为集合的大小)。
  • boolean containsAll(Collection<?> c):检查集合是否包含指定集合中的所有元素。
  • boolean addAll(Collection<? extends E> c):将指定集合中的所有元素添加到该集合中(可选操作)。
  • boolean removeAll(Collection<?> c):从集合中移除指定集合中包含的所有元素(可选操作)。
  • boolean retainAll(Collection<?> c):仅保留集合中包含在指定集合中的元素(可选操作)。
  • void clear():从集合中移除所有元素(可选操作)。

 2.List接口

这是Collection接口的子接口,代表一个有序、可重复的集合。List集合中的每个元素都有其对应的顺序索引,因此可以通过索引来访问元素。

接口的实现类:

1.ArrayList类:

基于数组实现,因此具有较快的随机访问速度。但ArrayList在添加或删除元素时可能需要移动其他元素,因此性能可能受到影响。
 

import java.util.ArrayList; // 引入 ArrayList 类

ArrayList<E> objectName =new ArrayList<>();  // 初始化

 E: 泛型数据类型。

以下情况使用 ArrayList :

  • 频繁访问列表中的某一个元素。
  • 只需要在列表末尾进行添加和删除元素操作。

2.LinkedList类

这也是List接口的一个实现类,但它基于链表实现。LinkedList在添加或删除元素时性能较好,因为只需要修改相邻元素的指针。但LinkedList的随机访问速度较慢。

以下情况使用 LinkedList :

  • 你需要通过循环迭代来访问列表中的某些元素。
  • 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。

LinkedList 实现了 Queue 接口,可作为队列使用。

LinkedList 实现了 List 接口,可进行列表的相关操作。

LinkedList 实现了 Deque 接口,可作为队列使用。

LinkedList 实现了 Cloneable 接口,可实现克隆。

3.Set接口

这也是Collection接口的子接口,但Set集合中的元素是无序的,且不允许重复。Set接口主要用于判重和去重操作。不能通过get方法得到index(下标)。

 接口的实现类:

1.HashSet类

  • 这是Set接口的一个实现类,它基于哈希表实现。HashSet提供了较快的查找和添加速度,但不保证元素的顺序。HashSet允许存储null值。
  • HashSet 是无序的,即不会记录插入的顺序。
  • HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。
  • HashSet 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类。

import java.util.HashSet; // 引入 HashSet 类
HashSet<String> sites = new HashSet<String>();

2.LinkedHashSet类

主要特性:
  • 有序性LinkedHashSet 维护元素的插入顺序。
  • 唯一性:像 HashSet 一样,LinkedHashSet 不允许有重复元素。
  • 性能:由于底层使用了哈希表(HashMap),LinkedHashSet 提供了接近 O(1) 的时间复杂度来进行查找、插入和删除操作。
  • 迭代器LinkedHashSet 的迭代器按照元素的插入顺序返回元素。
  • 非同步LinkedHashSet 不是线程安全的,如果在多线程环境中使用,需要额外的同步机制。
使用场景:
  • 需要维护元素插入顺序的集合。
  • 需要快速查找、插入和删除操作的集合。

3.TreeSet类

这是SortedSet接口的实现类,它基于红黑树实现。TreeSet可以保证元素处于排序状态,支持自然排序和定制排序。但TreeSet的添加、删除和查找操作的时间复杂度为O(logN)。

主要特性:
  1. 排序TreeSet 维护元素的自然顺序(或者通过提供的比较器排序)。
  2. 唯一性TreeSet 不允许有重复元素。
  3. 性能TreeSet 的查找、插入和删除操作的时间复杂度通常是 O(log n),因为它基于红黑树实现。
  4. 迭代器TreeSet 的迭代器按照元素的排序顺序返回元素。
  5. 非同步TreeSet 不是线程安全的,如果在多线程环境中使用,需要额外的同步机制。
使用场景
  • 需要对集合中的元素进行排序的集合。
  • 需要快速查找、插入和删除操作的集合,同时这些操作需要保持元素的排序顺序。

 

4.Map接口

Map不是Collection的子接口,但它是Java集合框架中另一个重要的接口。Map接口用于存储键值对(key-value pairs),其中每个键都是唯一的,并且映射到一个值上。Map接口提供了对键值对的添加、删除、查找等操作。

  接口的实现类:

 1.HashMap:

主要特性:
  • HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
  • HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
  • HashMap 是无序的,即不会记录插入的顺序。

HashMap 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类。这点和HashSet类似

2.LinkedHashMap

主要特性:
  • LinkedHashMapHashMap的一个子类,它维护了一个双向链表来记录插入顺序或访问顺序。
  • 如果指定为访问顺序,则每次调用get方法后,该键值对会被移动到链表的末尾(这是“最近最少使用”(LRU)缓存策略的基础)。它同样允许一个null键和多个null值。

3.TreeMap:

主要特性:

  • TreeMap是基于红黑树实现的一个有序的Map
  • 它根据键的自然顺序进行排序,或者根据创建TreeMap时提供的Comparator进行排序。
  • TreeMap不允许null键,但允许null值。

4.ConcurrentHashMap:

主要特性:
  • ConcurrentHashMap是一个线程安全的哈希表,它允许并发的读取和一定量的并发写入。
  • Hashtable相比,ConcurrentHashMap提供了更高的并发性能,因为它在内部使用了分段锁(在Java 8及更高版本中,这一实现细节有所改变,但总体上仍然是高并发的)。
  • 它不允许null键和null值。

5.Queue接口

代表一个队列集合——先进先出

 常用方法:

  • add(E e):将元素e添加到队列的尾部,如果队列已满,则抛出IllegalStateException。
  • offer(E e):将元素e添加到队列的尾部,如果队列已满,则返回false。
  • put(E e):将元素e添加到队列的尾部,如果队列已满,则阻塞当前线程直到队列有空间。
  • remove():移除并返回队列头部的元素,如果队列为空,则抛出NoSuchElementException。
  • poll():移除并返回队列头部的元素,如果队列为空,则返回null。
  • take():移除并返回队列头部的元素,如果队列为空,则阻塞当前线程直到队列有元素。
  • element():返回队列头部的元素但不移除它,如果队列为空,则抛出NoSuchElementException。
  • peek():返回队列头部的元素但不移除它,如果队列为空,则返回null。

 接口的实现类:

  1. LinkedList
    • LinkedList实现了Deque接口,而Deque是Queue的子接口,因此LinkedList也可以作为Queue使用。
    • LinkedList是一个基于链表结构的双向队列,允许在队列的两端进行插入和删除操作。
  2. PriorityQueue
    • PriorityQueue是一个基于优先级堆的无界优先级队列。
    • 元素按照优先级顺序被移除,而不是按照它们被添加的顺序。
    • PriorityQueue不保证同优先级元素的顺序。
  3. ArrayDeque
    • ArrayDeque是一个基于数组的双端队列。
    • 它不是线程安全的,并且性能通常比LinkedList好,特别是在作为栈或队列使用时。
  4. ConcurrentLinkedQueue
    • ConcurrentLinkedQueue是一个基于链接节点的、线程安全的无界队列。
    • 它支持高效的并发访问,并且不需要在访问时进行同步。
  5. ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueueDelayQueueSynchronousQueue(均为阻塞队列):
    • 这些队列都实现了BlockingQueue接口,该接口扩展了Queue接口以支持阻塞操作。
    • 阻塞队列在尝试添加元素到已满的队列或从空队列中移除元素时,线程会被阻塞,直到操作可以成功完成。

6.Deque接口

Deque接口代表一个双端队列,它允许在队列的两端进行插入和删除操作。Deque接口继承自Queue接口,并扩展了其功能,使其能够更高效地在两端进行操作。

常用方法:

  • addFirst(E e):在队列的开头插入元素e。
  • addLast(E e):在队列的末尾插入元素e。
  • offerFirst(E e):在队列的开头插入元素e,如果队列已满,则返回false(对于ArrayDeque,这永远不会发生,因为它是无界的)。
  • offerLast(E e):在队列的末尾插入元素e,如果队列已满,则返回false(同样,对于ArrayDeque,这永远不会发生)。
  • removeFirst():移除并返回队列的第一个元素。
  • removeLast():移除并返回队列的最后一个元素。
  • pollFirst():移除并返回队列的第一个元素,如果队列为空,则返回null。
  • pollLast():移除并返回队列的最后一个元素,如果队列为空,则返回null。
  • getFirst():获取但不移除队列的第一个元素。
  • getLast():获取但不移除队列的最后一个元素。
  • peekFirst():获取但不移除队列的第一个元素,如果队列为空,则返回null。
  • peekLast():获取但不移除队列的最后一个元素,如果队列为空,则返回null。

接口的实现类:

  1. ArrayDeque
    • ArrayDeque是一个基于数组的双端队列实现,它不是线程安全的。
    • 它提供了在队列两端进行高效插入和删除操作的能力。
    • 由于它是基于数组的,因此它避免了链表节点所需的额外内存开销,并且通常具有比LinkedList更好的性能。
  2. LinkedList
    • 虽然LinkedList主要被看作是一个链表实现的List,但它也实现了Deque接口。
    • 这意味着LinkedList也可以作为双端队列使用,允许在队列的两端进行插入和删除操作。
    • 然而,由于LinkedList是基于链表的,它的性能可能不如ArrayDeque,特别是在需要大量随机访问的情况下。

标签:java,框架,队列,元素,接口,线程,数组,集合
From: https://blog.csdn.net/m0_69185019/article/details/144530667

相关文章

  • JAVA领域驱动设计DDD在B端营销系统的实践15
     1背景通过营销活动实现客户/用户拉新、留存和促活是业界普遍采用的方法。为实现商户增长和留存,美团核心本地商业/商业增值技术部也构建了相应的营销系统来支撑商户的线上营销运营。在系统建设过程中,面临着业务体量大、行业跨度大、场景多样、客户结构复杂,需求多变等挑战。......
  • ZZNUOJ_1341:简单密码破解(C/C++/Java)
    题目描述密码是我们生活中非常重要的东东,我们的那么一点不能说的秘密就全靠它了。哇哈哈. 接下来渊子要在密码之上再加一套密码,虽然简单但也安全。 假设渊子原来一个BBS上的密码为zvbo941987,为了方便记忆,他通过一种算法把这个密码变换成YUANzi1987,这个密码是他的名......
  • JAVA中的包,抽象类
    什么是包java中的package就是一个类库单元,包内含有一组类,它们在单一的名称空间之下被组织在了一起,这个名称空间就是包名srcdao------>数据库相关的model------>>实体内容service----->业务util-------->工具包的作用1.把功能相似或相关的类或接口组织在一个包中,方便类......
  • 关于java中方法的那些事
    文章目录前言一、什么是方法?方法的完整格式是啥?二、方法如何使用?三、为什么要用方法?四、如果方法不需要接收数据处理,不需要返回数据,应该怎么办?要注意什么?五、方法使用时的常见问题六、定义方法重点关注的是哪几点?七、什么是方法重载?八、方法重载需要注意什么?九、方法重载......
  • JAVA领域驱动设计DDD在B端营销系统的实践
     1背景通过营销活动实现客户/用户拉新、留存和促活是业界普遍采用的方法。为实现商户增长和留存,美团核心本地商业/商业增值技术部也构建了相应的营销系统来支撑商户的线上营销运营。在系统建设过程中,面临着业务体量大、行业跨度大、场景多样、客户结构复杂,需求多变等挑战。......
  • flask框架美食网毕设源码+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容美食网毕业设计相关内容说明一、选题背景关于美食网的研究,现有研究主要以美食的展示与推广为主。在国内外,美食类网站众多,如国外的Yelp,国内的大众......
  • flask框架魔方教学网站毕设源码+论文
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、选题背景关于魔方教学网站的研究,现有研究主要以魔方的解法技巧、魔方的历史文化等实体内容为主,专门针对魔方教学网站这一特定平台的研究较少。......
  • 【Redis篇】Set和Zset 有序集合基本使用
    目录Set基本命令saddSMEMBERSSISMEMBER SCARD返回值:SPOPSMOVESREM集合间操作交集: 并集:差集:​编辑 内部编码使用场景:Zset有序集合Zset基本命令ZADDZCARD ZCOUNT ZRANGEZREVRANGEZRANGEBYSCOREZPOPMAXBZPOPMAX​编辑ZPOPMINZRANKZREVRANK......
  • 好用的java工具类整理
    一、封装树形菜单数据表结构必须有parentId,以便于实现无限级分类,如下:实体类@Schema(description="系统菜单实体类")@DatapublicclassSysMenuextendsBaseEntity{ @Schema(description="父节点id") privateLongparentId; @Schema(description="节点标题"......
  • javaweb知识点总结
    HTML1.HTML是一种超文本标记语言,可存储文字,图片,视频等等2.HTML依靠浏览器解析运行3.HTML有自己的预定义标签4.HTML由三部分组成,遵循W3C标准结构:HTML表现:CSS行为:JavaScript基础知识:1.颜色标签文字2.HTML文档不区分大小写3.HTMl语法松散#有时语法错误,功能仍正常基础......