news 2026/6/15 13:26:42

【Java SE 基础学习打卡】36 数组的常见操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Java SE 基础学习打卡】36 数组的常见操作

目录

  • 前言
  • 一、数组元素的查找:线性查找(翻收纳盒找东西)
    • 1.1 生活化类比
    • 1.2 核心原理
    • 1.3 代码示例(找指定成绩,返回索引)
    • 1.4 线性查找的特点(新手记)
  • 二、数组元素的排序:冒泡排序(让大元素 “浮” 到末尾)
    • 2.1 生活化类比
    • 2.2 核心原理(升序排序)
    • 2.3 基础代码实现(冒泡排序升序)
    • 2.4 冒泡排序优化(避免无效循环)
  • 三、数组元素的增删改:长度固定也能 “灵活操作”
    • 3.1 最简单:元素修改(直接替换)
    • 3.2 数组新增元素(扩容思路)
    • 3.3 数组删除元素(前移覆盖)
    • 3.4 关键提醒:数组增删的本质
  • 四、数组的拷贝:System.arraycopy ()(备份收纳盒)
    • 4.1 方法参数详解(新手记牢)
    • 4.2 代码示例(拷贝全部 / 部分元素)
    • 4.3 应用场景(新手常用)
    • 4.4 避坑提醒:数组拷贝的边界校验
  • 五、新手必避的 5 个 “操作致命坑”
    • 5.1 坑 1:冒泡排序内层循环条件写错
    • 5.2 坑 2:新增 / 删除元素时直接修改原数组
    • 5.3 坑 3:线性查找返回布尔值,不返回索引
    • 5.4 坑 4:数组拷贝时目标数组未初始化
    • 5.5 坑 5:删除元素时忽略索引合法性校验
  • 总结

前言

上一节咱们掌握了数组元素的访问和遍历,现在要落地到实际编程场景:比如从成绩数组里找有没有 95 分的学生(查找)、把成绩按从低到高排好序(排序)、给数组新增一个学生成绩(新增)、删掉无效的成绩(删除)、备份一份成绩数组(拷贝)。

新手容易觉得 “数组长度固定” 就没法增删元素,也容易被冒泡排序的 “相邻交换” 绕晕,这一节咱们就用 “整理收纳盒里的东西” 作为类比,把数组的查找、排序、增删改、拷贝这 4 个核心操作讲透,每个操作都给可运行的代码,还会讲优化思路和避坑点,让新手能直接落地使用!

一、数组元素的查找:线性查找(翻收纳盒找东西)

数组查找是 “从一堆元素里找指定值”,最基础的是线性查找(也叫顺序查找),适合无序数组,原理简单易懂。

1.1 生活化类比

想从装满成绩纸条的收纳盒里找 “95 分” 的纸条:

  • 从第一个纸条开始,逐个打开看;

  • 找到就停下,没找到就翻到最后一个;

  • 核心:按顺序遍历,逐个匹配,适合杂乱的收纳盒(无序数组)。

1.2 核心原理

遍历数组的每个元素,和目标值逐一比较:

  • 匹配成功:返回该元素的索引;

  • 遍历结束仍未匹配:返回 - 1(约定俗成的 “未找到” 标识)。

1.3 代码示例(找指定成绩,返回索引)

publicclassArraySearch{// 线性查找方法:arr是数组,target是要找的目标值publicstaticintlinearSearch(int[]arr,inttarget){// 遍历数组,逐个匹配for(inti=0;i<arr.length;i++){if(arr[i]==target){returni;// 找到,返回索引}}return-1;// 没找到,返回-1}publicstaticvoidmain(String[]args){int[]scores={90,85,95,88,92};inttarget=95;intindex=linearSearch(scores,target);if(index!=-1){System.out.println("找到"+target+"分,索引是:"+index);}else{System.out.println("没找到"+target+"分");}}}

执行结果:

找到95分,索引是:2

1.4 线性查找的特点(新手记)

  • 优点:简单,无需数组有序,代码易写;

  • 缺点:效率低,数组越长,遍历次数越多(最坏要遍历全部元素);

  • 适用场景:小容量数组、无序数组。

二、数组元素的排序:冒泡排序(让大元素 “浮” 到末尾)

排序是把数组元素按指定顺序(升序 / 降序)排列,冒泡排序是新手必学的基础排序算法,核心是 “相邻元素比较交换,大的元素逐步往后移,像气泡上浮一样”。

2.1 生活化类比

把收纳盒里的成绩纸条按 “从低到高” 摆好:

  • 从第一个纸条开始,和旁边的纸条比,分数高的往右挪;

  • 第一轮比完,最高分的纸条会到最右边(像气泡浮到顶部);

  • 第二轮只比前 n-1 个纸条,确定次高分的位置;

  • 重复直到所有纸条排好。

2.2 核心原理(升序排序)

  1. 外层循环:控制排序轮数,共需数组长度-1轮(最后一个元素不用比);

  2. 内层循环:每轮遍历未排序的元素,相邻元素比较,若前 > 后则交换;

  3. 每轮结束:当前未排序部分的最大值 “浮” 到末尾。

2.3 基础代码实现(冒泡排序升序)

publicclassArrayBubbleSort{// 冒泡排序方法:传入int数组,按升序排序publicstaticvoidbubbleSort(int[]arr){// 外层循环:控制轮数,共arr.length-1轮for(inti=0;i<arr.length-1;i++){// 内层循环:每轮比较到“未排序的最后一位”,即arr.length-1-ifor(intj=0;j<arr.length-1-i;j++){// 前一个元素 > 后一个,交换位置(升序)if(arr[j]>arr[j+1]){// 临时变量存值,完成交换inttemp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;}}}}publicstaticvoidmain(String[]args){int[]scores={90,85,95,88,92};System.out.println("排序前:");for(intscore:scores){System.out.print(score+" ");// 输出:90 85 95 88 92}bubbleSort(scores);// 调用排序System.out.println("\n排序后(升序):");for(intscore:scores){System.out.print(score+" ");// 输出:85 88 90 92 95}}}

2.4 冒泡排序优化(避免无效循环)

如果数组提前排好序,基础版还会继续循环,优化思路:加 “是否交换” 的标志位,没交换说明已排好,直接结束。

publicstaticvoidbubbleSortOptimize(int[]arr){for(inti=0;i<arr.length-1;i++){booleanisSwapped=false;// 标志位:本轮是否交换过for(intj=0;j<arr.length-1-i;j++){if(arr[j]>arr[j+1]){inttemp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;isSwapped=true;// 标记有交换}}if(!isSwapped){break;// 本轮没交换,说明已排好,直接退出}}}

三、数组元素的增删改:长度固定也能 “灵活操作”

数组长度一旦创建就不能改,但可以通过 “新建数组 + 拷贝元素” 实现增删,修改则直接通过索引赋值即可。

3.1 最简单:元素修改(直接替换)

修改是数组最基础的操作,直接通过 “数组名 [索引] = 新值” 替换,无需复杂逻辑。

publicclassArrayModify{publicstaticvoidmain(String[]args){int[]scores={90,85,95};// 修改索引1的元素(85分→92分)scores[1]=92;System.out.println("修改后数组:");for(intscore:scores){System.out.print(score+" ");// 输出:90 92 95}}}

3.2 数组新增元素(扩容思路)

核心逻辑:新建一个 “长度 + 1” 的数组,拷贝原数组所有元素,最后把新元素放到末尾。

publicclassArrayAdd{// 数组新增元素:arr原数组,newVal新增值publicstaticint[]addElement(int[]arr,intnewVal){// 1. 新建长度+1的数组int[]newArr=newint[arr.length+1];// 2. 拷贝原数组元素到新数组for(inti=0;i<arr.length;i++){newArr[i]=arr[i];}// 3. 新元素放到新数组末尾newArr[arr.length]=newVal;// 4. 返回新数组(原数组不变)returnnewArr;}publicstaticvoidmain(String[]args){int[]scores={90,85,95};int[]newScores=addElement(scores,88);// 新增88分System.out.println("新增后数组:");for(intscore:newScores){System.out.print(score+" ");// 输出:90 85 95 88}}}

3.3 数组删除元素(前移覆盖)

核心逻辑:找到要删除元素的索引,把该索引后面的元素逐个往前移,最后把末尾元素置为默认值(或新建长度 - 1 的数组)。

publicclassArrayDelete{// 数组删除元素:arr原数组,delIndex要删除的索引publicstaticint[]deleteElement(int[]arr,intdelIndex){// 校验索引合法性if(delIndex<0||delIndex>=arr.length){System.out.println("索引不合法,删除失败");returnarr;}// 1. 新建长度-1的数组int[]newArr=newint[arr.length-1];// 2. 拷贝删除索引前的元素for(inti=0;i<delIndex;i++){newArr[i]=arr[i];}// 3. 拷贝删除索引后的元素(往前移一位)for(inti=delIndex;i<newArr.length;i++){newArr[i]=arr[i+1];}returnnewArr;}publicstaticvoidmain(String[]args){int[]scores={90,85,95,88};int[]newScores=deleteElement(scores,2);// 删除索引2的95分System.out.println("删除后数组:");for(intscore:newScores){System.out.print(score+" ");// 输出:90 85 88}}}

3.4 关键提醒:数组增删的本质

数组长度固定,所谓 “增删” 其实是创建新数组 + 拷贝原元素,原数组不会改变,新手不要试图直接修改原数组的长度。

四、数组的拷贝:System.arraycopy ()(备份收纳盒)

数组拷贝是 “复制一份数组的全部 / 部分元素”,Java 提供了System.arraycopy()方法,比手动 for 循环拷贝效率更高。

4.1 方法参数详解(新手记牢)

System.arraycopy(源数组,源起始索引,目标数组,目标起始索引,拷贝长度);
  • 源数组:要拷贝的原数组;

  • 源起始索引:从原数组的哪个索引开始拷贝;

  • 目标数组:拷贝到的新数组;

  • 目标起始索引:新数组从哪个索引开始接收;

  • 拷贝长度:要拷贝的元素个数。

4.2 代码示例(拷贝全部 / 部分元素)

publicclassArrayCopy{publicstaticvoidmain(String[]args){int[]scores={90,85,95,88,92};// 示例1:拷贝全部元素(备份数组)int[]copyAll=newint[scores.length];System.arraycopy(scores,0,copyAll,0,scores.length);System.out.println("拷贝全部元素:");for(intscore:copyAll){System.out.print(score+" ");// 输出:90 85 95 88 92}// 示例2:拷贝部分元素(拷贝索引1到3的元素,共3个)int[]copyPart=newint[3];System.arraycopy(scores,1,copyPart,0,3);System.out.println("\n拷贝部分元素:");for(intscore:copyPart){System.out.print(score+" ");// 输出:85 95 88}}}

4.3 应用场景(新手常用)

  • 数组扩容 / 缩容:新增 / 删除元素时,拷贝原数组元素到新数组;

  • 数组备份:避免原数组修改影响数据;

  • 截取数组片段:只拷贝需要的部分元素。

4.4 避坑提醒:数组拷贝的边界校验

拷贝前要确保:

  • 拷贝长度 ≤ 源数组剩余元素个数(源起始索引 + 拷贝长度 ≤ 源数组长度);

  • 拷贝长度 ≤ 目标数组剩余空间(目标起始索引 + 拷贝长度 ≤ 目标数组长度);否则会抛出ArrayIndexOutOfBoundsException

五、新手必避的 5 个 “操作致命坑”

5.1 坑 1:冒泡排序内层循环条件写错

  • 错误示例:

    // 内层循环没减i,重复比较已排好的元素for(intj=0;j<arr.length-1;j++){}
  • 避坑:固定写j < arr.length - 1 - i,每轮少比较已排好的 i 个元素。

5.2 坑 2:新增 / 删除元素时直接修改原数组

  • 错误示例:

    // 以为能直接给原数组新增元素,实际编译报错scores.length=scores.length+1;
  • 避坑:增删必须创建新数组,原数组长度无法修改。

5.3 坑 3:线性查找返回布尔值,不返回索引

  • 错误示例:

    // 只能判断有没有,没法知道位置,实用性低publicstaticbooleansearch(int[]arr,inttarget){for(inti=0;i<arr.length;i++){if(arr[i]==target)returntrue;}returnfalse;}
  • 避坑:优先返回索引(找到返回索引,没找到返回 - 1),更灵活。

5.4 坑 4:数组拷贝时目标数组未初始化

  • 错误示例:

    int[]copyAll=null;System.arraycopy(scores,0,copyAll,0,scores.length);// 空指针异常
  • 避坑:拷贝前必须初始化目标数组,且长度足够。

5.5 坑 5:删除元素时忽略索引合法性校验

  • 错误示例:

    // 传入负数索引或超出长度的索引,运行时报错deleteElement(scores,-1);
  • 避坑:删除前先校验delIndex >= 0 && delIndex < arr.length

总结

这一节咱们掌握了数组的 4 个核心常见操作,记住 3 个核心点:

  1. 查找:线性查找适合无序数组,找到返回索引、没找到返回 - 1;

  2. 排序:冒泡排序核心是 “相邻比较交换,每轮确定一个最大值”,加标志位可优化;

  3. 增删改拷贝:修改直接赋值,增删需新建数组,拷贝优先用 System.arraycopy ()。

这些操作是数组实操的基础,后续学习二维数组、集合等内容都会用到,掌握好这些,处理批量数据就会更灵活。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 15:53:01

01.初识 Python —— 为什么它是新手入门的首选语言?

目录前言一、Python 是什么&#xff1f;—— 从名字到核心定义1.1 名字里的小彩蛋1.2 技术层面的核心定位二、Python 的 “闪光点”—— 10 个让它脱颖而出的核心优势2.1 语法简单&#xff0c;上手零压力2.2 动态类型&#xff0c;写代码更自由2.3 编程范式多样&#xff0c;适配…

作者头像 李华
网站建设 2026/6/15 13:23:04

ClickHouse 高分笔记

1. 原理 实时数据分析数据库 ClickHouse 介绍开源OLAP引擎&#xff08;ClickHouse、Doris、Presto、ByConity&#xff09;性能对比分析ClickHouse 原理&#xff1a;如何为列式存储构建快速 UPDATE I&#xff1a;特别设计的专用引擎ClickHouse 原理&#xff1a;深入理解数据分片…

作者头像 李华
网站建设 2026/6/15 13:25:16

基于改进条件扩散模型的电阻抗成像图像重建与敏感度先验融合

摘要&#xff1a;电阻抗成像&#xff08;EIT&#xff09;以低成本、实时性和无创性在医学与工业领域具有广泛前景&#xff0c;但其逆问题高度非线性、病态&#xff0c;导致成像质量与泛化性受限。本文面向两条互补技术路线&#xff1a;一是条件扩散重建&#xff08;CDEIT&#…

作者头像 李华
网站建设 2026/6/14 14:32:38

SpringBoot 中处理接口传参时常用的注解

SpringBoot 接收前端参数的核心注解都基于 Spring MVC&#xff0c;主要解决不同位置参数&#xff08;URL 路径、请求头、请求体、URL 参数等&#xff09;的绑定问题&#xff0c;下面按使用场景分类说明&#xff1a;1. 路径参数&#xff08;URL 中 /{xxx} 形式&#xff09;&…

作者头像 李华
网站建设 2026/6/13 3:04:41

为什么现代 C++ 更推荐用引用,而不是指针?

现代 C&#xff08;C11 及以后&#xff09;强烈推荐优先使用引用&#xff08;references&#xff09;而不是裸指针&#xff08;raw pointers&#xff09;&#xff0c;核心原因可以用一句话概括&#xff1a; 引用在表达意图、安全性、可读性和现代设计模式上都比裸指针更优秀&a…

作者头像 李华
网站建设 2026/6/12 21:25:19

白盒测试 接口测试 自动化测试

一、什么是白盒测试 白盒测试是一种测试策略&#xff0c;这种策略允许我们检查程序的内部结构&#xff0c;对程序的逻辑结构进行检查&#xff0c;从中获取测试数据。白盒测试的对象基本是源程序&#xff0c;所以它又称为结构测试或逻辑驱动测试&#xff0c;白盒测试方法一般分为…

作者头像 李华