4. 数组与集合

news2024/11/17 21:22:04

数据结构是管理和组织数据的基础,它直接影响到程序的性能和效率。在本章中,我们将深入探讨与数组和集合相关的知识。这些数据结构在Java编程中至关重要,无论是处理简单的线性数据还是复杂的多维数据,合理使用这些结构都能大大提高代码的效率和可维护性。

4.1. 数组

数组是一种用于存储相同类型数据的线性数据结构,作为固定大小的容器,每个元素在内存中按顺序排列,并可通过索引访问。数组一旦创建,其大小便不可更改,可以用于存储任何数据类型的元素,如整数、浮点数或字符串。

Java数组结构根据维度分为一维和多维两种类型,本文将重点介绍这两种数据类型的应用。

4.1.1 一维数组

一维数组(Single-Dimensional Array)是最基本的数组形式,呈现为一个线性结构。可以将一维数组理解为一列数据或是一个具有单个索引的数组。

一维数组适用于存储和顺序访问相同类型的数据,例如,当需要存储一个班级中所有学生的考试成绩时,一维数组是一个理想的选择。以下代码示例展示了如何使用一维数组来管理学生成绩:

// 创建一个包含5个学生分数的一维数组
int[] scores = new int[5];
scores[0] = 85;
scores[1] = 90;
scores[2] = 78;
scores[3] = 92;
scores[4] = 88;

// 访问数组中的元素
System.out.println("第一个学生的分数是: " + scores[0]);

这段代码展示了如何使用一维数组来存储学生成绩,并通过索引访问具体的分数。

4.1.2 多维数组

多维数组(Multi-Dimensional Array)是数组的扩展形式,允许在一个数组中存储多个数组。最常见的多维数组是二维数组,它可以被视为一个矩阵或表格数据的集合,每个元素可以通过多个索引来访问。

多维数组适用于表示需要多维数据结构的场景,例如,存储一个班级中多个学生的多次考试成绩,或者表示一个棋盘游戏的状态。以下代码示例展示了如何使用二维数组来存储和访问学生的多个考试成绩:

// 创建一个3x4的二维数组,表示3个学生的4次考试分数
int[][] scores = {
    {85, 90, 78, 92}, // 第一个学生的分数
    {88, 76, 91, 85}, // 第二个学生的分数
    {78, 85, 88, 90}  // 第三个学生的分数
};

// 访问二维数组中的元素
System.out.println("第二个学生的第三次考试分数是: " + scores[1][2]);

在这个示例中,二维数组被用来存储3个学生的4次考试成绩。通过指定行和列的索引,可以轻松访问和操作特定学生的特定成绩。这种结构非常适合需要在多个维度上管理数据的场景,如表格数据、图像处理或多层嵌套的集合等。

在实际应用中,三维及更高维数组的使用相对少见,通常用于特定领域的复杂数据处理。我们以三维数组为例,三维数组可以看作是多个二维数组的集合通常用于更复杂的数据表示需求,如表示多层结构的数据、存储3D图形数据,或记录时间序列数据中的变化。以下是三维数组的示例:

// 创建一个2x3x4的三维数组,表示2个班级中3个学生的4次考试分数
int[][][] scores = {
    {
        {85, 90, 78, 92}, // 班级1,学生1的分数
        {88, 76, 91, 85}, // 班级1,学生2的分数
        {78, 85, 88, 90}  // 班级1,学生3的分数
    },
    {
        {82, 89, 77, 90}, // 班级2,学生1的分数
        {80, 75, 93, 87}, // 班级2,学生2的分数
        {79, 84, 86, 91}  // 班级2,学生3的分数
    }
};

// 访问三维数组中的元素
System.out.println("班级2中学生1的第三次考试分数是: " + scores[1][0][2]);

在这个示例中,三维数组被用来存储两个班级中学生的多次考试成绩。通过三个索引,你可以精确定位到某个班级中某个学生在某次考试中的成绩。

在实际编程中,超过三维的数组应用较少,因为随着维度的增加,数据的管理和理解难度也会显著增加。通常在处理非常高维度的数据时,开发者会使用专门的数据结构或数据库,而不是直接使用多维数组。

4.2. 集合框架概述

Java编程语言提供了一系列内置的数据结构和算法,使我们在开发过程中无需从零开始设计数据结构。这些数据结构和算法经过高度优化,构成了Java集合框架的核心。集合框架为数据的排序、插入、删除、更新和搜索等操作提供了高效的解决方案。它还通过定义接口和类,为这些功能的实现提供了统一的操作方法。下图为集合框架的层次结构:

  1. 以上框架图来源于:https://data-flair.training/blogs/collection-framework-in-java/

集合框架的核心接口包括CollectionMapIterable接口。

Collection是Java集合框架中最基本的接口,是许多其他集合接口的父接口。Collection本身并不直接提供实现,而是定义了一组通用操作,如添加、删除和遍历元素。ListSetQueue都是Collection接口的子接口,它们根据不同的需求扩展了Collection接口的功能。

4.2.1. List接口

List接口是Collection接口的一个子接口,表示一个有序的集合。List中的元素按照插入顺序排列,并且允许包含重复的元素。这意味着你可以在List中存储多个相同的元素。常见的实现类包括ArrayListLinkedListVectorList提供了通过索引访问元素的功能,使得可以高效地插入、删除和访问元素。

4.2.2. Set接口

Set接口也是Collection接口的子接口,但与List不同,Set不允许存储重复的元素。Set用于需要确保集合中所有元素唯一的场景。常见的实现类有HashSetLinkedHashSetTreeSet。由于Set不维护元素的顺序,因此通常无法通过索引访问元素,不过TreeSet实现了SortedSet接口,能够按照自然顺序或指定的比较器进行排序。

4.2.3. Quene接口

Queue主要用于按特定顺序处理元素,通常是先进先出(FIFO, First-In-First-Out)的顺序。Queue适用于需要按顺序处理任务或请求的场景。常见的实现类包括LinkedListPriorityQueueArrayDeque。虽然Queue通常遵循FIFO顺序,但某些实现(如PriorityQueue)可以根据元素的优先级进行排序。Queue`不允许通过索引访问元素,元素的插入和移除通常只能在队列的两端进行。

4.2.4. Map接口

Map接口不同于Collection接口,它定义了一种键值对映射的集合结构。Map中的每个键(Key)都是唯一的,但键和值之间的映射关系可以是任意的。常见的实现类包括HashMapLinkedHashMapTreeMapMap提供了通过键快速查找对应值的功能,因此非常适合用于需要根据键进行高效查找的场景。Map不属于Collection的子接口,而是独立存在,因为它处理的是键值对,而不是单个元素。

4.3. 常用集合操作

在Java中,ListMapQueueSet是常用的集合接口,它们各自适用于不同的场景。以下分别介绍这些接口的常用操作及示例代码,并给出总结和应用场景的对比表格。

4.3.1 List

List接口表示一个有序的集合,允许重复的元素,并支持通过索引访问元素。常用操作包括添加、访问、更新和删除元素。

import java.util.ArrayList;
import java.util.List;

public class ListExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        
        // 添加元素
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");
        
        // 访问元素
        System.out.println("First element: " + list.get(0));
        
        // 更新元素
        list.set(1, "Blueberry");
        
        // 删除元素
        list.remove(2);
        
        // 遍历列表
        for (String fruit : list) {
            System.out.println(fruit);
        }
    }
}
4.3.2 Map

Map接口用于存储键值对,键是唯一的,常用于快速查找和更新值。常用操作包括添加、访问、更新和删除键值对。

import java.util.HashMap;
import java.util.Map;

public class MapExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        
        // 添加键值对
        map.put("Apple", 10);
        map.put("Banana", 20);
        map.put("Cherry", 30);
        
        // 访问值
        System.out.println("Apple count: " + map.get("Apple"));
        
        // 更新值
        map.put("Banana", 25);
        
        // 删除键值对
        map.remove("Cherry");
        
        // 遍历Map
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}
4.3.3 Queue

Queue接口通常用于按顺序处理元素,常见的操作包括添加、访问、移除和检查队列头部的元素。

import java.util.LinkedList;
import java.util.Queue;

public class QueueExample {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        
        // 添加元素到队列
        queue.offer("Task1");
        queue.offer("Task2");
        queue.offer("Task3");
        
        // 查看队列头部元素
        System.out.println("Head of queue: " + queue.peek());
        
        // 处理并移除队列中的元素
        System.out.println("Processing: " + queue.poll());
        
        // 遍历队列
        for (String task : queue) {
            System.out.println(task);
        }
    }
}
4.3.4 Set

Set接口用于存储不重复的元素,不维护元素的顺序。常见的操作包括添加、检查元素存在性和删除元素。

import java.util.HashSet;
import java.util.Set;

public class SetExample {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        
        // 添加元素
        set.add("Apple");
        set.add("Banana");
        set.add("Cherry");
        
        // 检查元素是否存在
        System.out.println("Set contains Banana: " + set.contains("Banana"));
        
        // 删除元素
        set.remove("Apple");
        
        // 遍历集合
        for (String fruit : set) {
            System.out.println(fruit);
        }
    }
}

下表总结了ListMapQueueSet各自的特点、常用操作及适用场景:

集合类型特点常用操作示例适用场景
List有序集合,允许重复元素,通过索引访问添加、访问、更新、删除元素需要按顺序存储和访问数据的场景,如待办事项列表、订单列表等。
Map键值对集合,键唯一,值可以重复添加、访问、更新、删除键值对需要通过键快速查找和更新值的场景,如字典、用户信息存储等。
Queue先进先出队列,按顺序处理元素添加、访问、移除头部元素任务调度、消息队列、按优先级处理任务的场景。
Set无序集合,不允许重复元素添加、检查存在性、删除元素需要确保元素唯一的场景,如学生ID集合、商品编号集合等。
4.4. 集合的线程安全

Java集合框架中大多数集合类默认不是线程安全的,在多线程环境中使用这些集合时,需要额外的处理来确保线程安全。开发者可以通过使用Collections类的同步集合方法将非线程安全的集合转换为线程安全集合,或者直接使用java.util.concurrent包中的并发集合类,以便更高效地处理并发访问。选择哪种方式取决于具体的使用场景和性能需求。

4.4.1. 同步

Java通过Collections类提供了一组静态方法,用于将非线程安全的集合转换为线程安全的同步集合。例如,Collections.synchronizedList()方法可以将一个List转换为线程安全的List。以下是一个示例:

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;

public class SynchronizedCollectionExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        List<String> synchronizedList = Collections.synchronizedList(list);
        
        synchronizedList.add("Apple");
        synchronizedList.add("Banana");

        // 使用同步集合时,手动同步访问
        synchronized (synchronizedList) {
            for (String item : synchronizedList) {
                System.out.println(item);
            }
        }
    }
}

在上面的示例中,ArrayList通过Collections.synchronizedList()方法转换为一个线程安全的List,这样在多线程环境中对集合的访问就不会导致数据不一致。

4.4.2.并发

Java还提供了java.util.concurrent包中的一组并发集合类,这些集合类设计用于高效地处理多线程环境下的并发访问。常见的并发集合类包括:

  • ConcurrentHashMap:一个线程安全的HashMap,允许多个线程并发地读写。
  • CopyOnWriteArrayList:一个线程安全的ArrayList,适合在读多写少的场景中使用。
  • ConcurrentLinkedQueue:一个线程安全的非阻塞队列,适用于高效的并发访问。
    以下是ConcurrentHashMap的使用示例:
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

public class ConcurrentCollectionExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new ConcurrentHashMap<>();
        
        map.put("Apple", 10);
        map.put("Banana", 20);

        // 并发集合类不需要手动同步
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

在上面的示例中,ConcurrentHashMap提供了对HashMap的线程安全实现,适用于高并发环境中频繁读写的场景。

关于更多关于线程的知识,我将在其他章节给大家进行分享。

小结

在本文中,探讨了Java中数组和集合的基础知识,涵盖了从一维数组到多维数组的应用场景,并详细讲解了Java集合框架中的主要接口及其常用操作。掌握这些数据结构和集合操作对提升代码的效率和可维护性至关重要,是Java开发中的核心技能。通过合理选择和使用这些工具,可以有效处理复杂的数据管理任务。

扩展阅读

Oracle官方文档-集合

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2066347.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

100个智能体实战技巧 | 如何让工作流也能处理图片

相信不少朋友都遇到过想要在工作流中处理图片但是却无从下手的情况 举个例子&#xff0c;扣子中有个插件叫OCR&#xff0c;是可以用来识别图中的文字的 然而作为一个插件&#xff0c;它只能在工作流中被调用&#xff0c;如下图 工作流 vs. 图像流 这就意味着&#xff0c;要使用…

Modal中的跳转用<Link>组件会报错?

在做链接跳转时&#xff0c;一般是用a标签或者link标签。但是当团队规范使用标签时&#xff0c;在modal&#xff08;antd的版本4&#xff09;中使用可能就有问题了。 报错内容是&#xff0c;发现link在使用时找不到路由上下文。因此报错。 原因&#xff1a;Link 组件在 return …

Vue3-响应式原理解析

vue3 与 vue2 主要差异之一无疑是响应式实现上的改变。本文主要阐述响应式原理的实现方式解析以及核心源码阅读的注释理解。 本文主要对响应式实现原理进行逻辑梳理,舍弃枯燥无味的代码,只用图解/文字进行功能描述,具体实现请自行阅读。保重!!! 如果问题,虚心求教,还请…

xxl_job任务调度简单使用

一、概念 任务调度是为了自动完成特定任务&#xff0c;在约定的特定时刻去执行任务的过程 如以下应用场景&#xff1a; 某电商平台需要每天上午10点&#xff0c;下午3点&#xff0c;晚上8点发放一批优惠券 某银行系统需要在信用卡到期还款日的前三天进行短信提醒 某财务系统…

UEditor百度富文本后端上传文件接口

UEditor百度富文本后端上传文件接口 直接上代码 接口&#xff1a; RequestMapping("/UEditorConfig")public String list(HttpServletRequest request, HttpServletResponse response) throws IOException {String config environment.getProperty("ueditor.c…

60%公司推行精益管理失败都源于同一原因,这个原因是...

精益管理在许多公司中已经成为提高运营效率、减少浪费、和提升客户满意度的重要方法。或者你觉得惊讶&#xff0c;根据我们的经验&#xff0c;超过60%的公司在实施精益管理失败&#xff0c;我们发现他们都有一个共同的原因&#xff0c;这个原因就是公司没有跟踪正确的指标&…

【图文并茂】ant design pro 如何优雅奇妙地把 crud 的 api 单独抽出来共用

我们写后台项目&#xff0c;经常要写增删改查的接口。 比如 角色 权限 我们不可能都写一个 api 比如 getRoles, getPermissions 这些请求列表的&#xff0c;都是一样的&#xff0c;只是路径不同 那么我们应该抽出来&#xff0c;放到一起&#xff0c;直接去调&#xff0c;只…

双向电表是什么电表?为什么光伏发电储能要求安装双向电能表!

双向电表是什么电表? 双向电表就在用电的时候假如是正转&#xff0c;那么向外送电的时候就是反转&#xff0c;也就是读数越来越小。反总是指反向总有功&#xff0c;反无是指反向总无功。 双向电表&#xff0c;也称为双向计量电能表&#xff0c;是一种能够计量用电和发电的电…

第三节:Nodify 添加连接关系

引言 Nodify有三层结构&#xff0c;编辑器Editor&#xff0c;节点Node和连接组件Connection&#xff0c;上节介绍了节点和编辑器&#xff0c;本节介绍连接组件。连接组件用于保存节点中连接端子的连接关系&#xff0c;并随节点的拖动改变。 1、连接组件 连接组件存储一个连接关…

海外媒体软文发稿【越南通讯社vnanet】官方媒体发布新闻稿

海外媒体软文发稿【越南通讯社vnanet】官方媒体发布新闻稿 越南通讯社(越南语&#xff1a;Thng tấn x Việt Nam&#xff1b;英语&#xff1a;Vietnam News Agency&#xff0c;简称VNA)&#xff0c;简称“越通社”是越南国家通讯社&#xff0c;始建于1945年9月2日。越通社是越…

JVM的内存模型和垃圾回收

JVM内存区域 内存模型图&#xff1a; 堆 线程共享。所有的对象实例以及数组都要在堆上分配。回收器主要管理的对象。 它的目的是存放对象实例。同时它也是GC所管理的主要区域&#xff0c;因此常被称为GC堆&#xff0c;又由于现在收集器常使用分代算法&#xff0c;Java堆中还…

纷享销客AI能力在线索精细化管理中的应用与实践

1、智能评分提高线索转换效率 企业可以经过后台模型配置&#xff0c;和对近1-2年内线索的相关属性进行整理分析&#xff0c;纷享销客AI可以总结出历史相似线索的转换概率&#xff0c;使销售人员可以集中精力在更容易转换的线索上&#xff0c;提高转化效率。 纷享销客AI的智能…

pdf如何转换为jpg图片?这几种转换方法简单又实用!

pdf如何转换为jpg图片&#xff1f;PDF&#xff0c;这一广泛应用于文档传输与存储的格式&#xff0c;虽极大地促进了信息的电子化流通&#xff0c;但在日常办公实践中&#xff0c;也逐渐显露出其局限性&#xff0c;尤其是在文件管理与网络分享方面&#xff0c;PDF的庞大体积常导…

fastadmin 时间选择器可选择具体的时分秒

预期要达到的样式,时间区间可以直接选择具体的时分秒 找到这个文件require-form.js 在pulic/assets/js 下面 找到datetimepicker 属性 设置为true var options {timePicker: true,autoUpdateInput: false,timePickerSeconds: true,timePicker24Hour: true,autoApply: true,lo…

Llama 3.1 70B与Mistral Large 2 128B深度对比

在人工智能的浩瀚宇宙中&#xff0c;两颗新星正在引发行业内的轰动。Meta 的 Llama-3.1-70B 和Mistral Large-2-128B&#xff0c;这两大 AI 巨头以其前所未有的计算能力和复杂性&#xff0c;正引领着智能算法的新浪潮。它们不仅仅是技术的集大成者&#xff0c;更是未来可能性的…

基于微信小程序的点餐小程序/基于微信小程序的订餐系统设计与实现

微信点餐小程序 摘 要 随着互联网技术不断地发展&#xff0c;网络成为了人们生活的一部分&#xff0c;而点餐系统作为网上应用的一个全新的体现&#xff0c;由于其特有的便捷性&#xff0c;已经被人们所接受。目前主流的点餐服务不仅不明确并且管理员管理起来不容易&#xff0…

公司最大的内卷,偷偷做单元测试

一位读者在看过我的《理解这八大优势&#xff0c;才算精通单元测试》后&#xff0c;问我&#xff1a;知道单元测试有好处&#xff0c;但实在没空写。看完文章后又想重新落实一下&#xff0c;有没有啥写好单元测试的技巧&#xff1f; 这位读者绝对不是第一个和我抱怨单元测试的…

安卓窗口window无法移除屏幕外超过屏幕边界?-wms源码层面深入剖析

背景 学习了上一节的窗口位置变化相关的内容后&#xff0c;在窗口移动过程过程中发现有一个限制问题&#xff0c;大家可以看一下如下动态图&#xff1a; 已经尽力把窗口想要拖到屏幕外面&#xff0c;但是一直拖到不生效&#xff0c;只能在屏幕内部进行移动&#xff0c;这个到…

智能叮咚门铃的功能,开启未来家居安全新篇章

在科技日新月异的今天&#xff0c;智能家居产品正逐步渗透到我们生活的每一个角落&#xff0c;其中&#xff0c;智能叮咚门铃作为家庭安防与便捷生活的重要一环&#xff0c;正经历着前所未有的功能升级与变革。 一、高清夜视&#xff0c;全天候守护 全新智能叮咚门铃配备了高清…

芒果/充电桩系统云快充1.5底层协议源码(源码)

充电桩系统云快充1.5底层协议源码&#xff08;源码&#xff09; 介绍 云快充协议云快充1.5协议云快充协议开源代码云快充底层协议云快充桩直连桩直连协议充电桩系统桩直连协议 软件架构 1、提供云快充底层桩直连协议&#xff0c;版本为云快充1.5&#xff0c;对于没有对接过…