Java - 数组详解(图解数组的基本操作)

时间:2022-09-07 20:38:36

目录

首先

什么是数组

数组是一组地址连续、长度固定的具有相同类型的数据的集合,通过数组下标我们可以指定数字中的每一个元素

数组的定义和内存分配

在Java中通过(类型名[] 数组名)或(类型名 数组名[])申明一个数组,其中(类型名[] 数组名)方式声明数组是Java特有也是推荐使用的

数组是一个特殊的对象,所以在使用前需要在内存中开辟一块内存空间用来存放数据,否则会抛出空指针异常,可以通过(new)关键字给数组分配内存,也可以使用通过在静态初始化(见下)时隐式的给数组分配与初始化元素个数相同的数组空间

定义了一个数组后可以通过(数组名[下标])的方式访问数组中的数据,通过(数组名[下标]=数据)为数组赋值

数组的赋值和访问

数组的赋值有两种:静态初始化、动态初始化

  • 静态初始化:通过(类型[] 数组名={元素,元素...})或(类型[] 数组名=[]{元素,元素...})的方式为数组初始化,数组将自动分配一个与元素个数相同的内存空间
  • 动态初始化:通过(类型[] 数组名=new 类型[大小])为数组分配内存,通过(数组名[下标]=数据)为数组初始化赋值

数组的注意事项

  1. 数组的类型可以是基本数据类型和引用类型
  2. 数组的长度不可变
  3. 数组的属性(数组名.length)获取的是数组的容量,而不是数组中存储元素的个数
  4. 数组的下标从0开始,最后一个元素的下标是(length-1)
public static void main(String[] args) {
int[] arr1={1,2,3};//定义一个int类型数组arr1,静态初始化数组,其数组长度为3
int[] arr2=new int[3];//定义一个长度为3的int类型数组arr2 int类型的数组其元素默认值是0
int[] arr3=new int[]{4,5,6};//定义一个int类型数组arr2,并静态初始化数组,其数组长度为3 //(数组名.lenth)获取数组的容量大小
System.out.println("arr1的长度为 : "+arr1.length+" - ["+arr1[0]+", "+arr1[1]+", "+arr1[2]+"]");
System.out.println("arr1的长度为 : "+arr2.length+" - ["+arr2[0]+", "+arr2[1]+", "+arr2[2]+"]");
System.out.println("arr1的长度为 : "+arr3.length+" - ["+arr3[0]+", "+arr3[1]+", "+arr3[2]+"]");
}

Java - 数组详解(图解数组的基本操作)

数组的内存图解

Java - 数组详解(图解数组的基本操作)

数组的遍历

我们常使用for循环或foreach遍历数组:见代码

 public static void main(String[] args) {

     int[] arr={1,2,3};
// 使用for循环遍历数组
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+", ");
}
System.out.println("\n-----快乐的分割线-----");
// 使用foreach遍历数组
/*
* foreach的用法
* for(数组类型 变量名 : 数组名){
* 通过 变量名 访问数组中的每个元素
* }
*/
for(int i : arr){
System.out.print(i+", ");
}
}

Java - 数组详解(图解数组的基本操作)


好了,经过了对数组的简单了解后,让我们看看对数组的基本操作

插入

我们知道,通过(数组名[下标]=数据)的方式能很容易的给数组的任一位置赋值,但是如果原位置本含有数据,此时就会将原有数据覆盖,也就造成了数据丢失

所以我们可以将插入位置及之后的所有实际使用元素都向后移动一位,这样插入位置就空出来(当然也需要有足够的剩余空间,不然也是不能插入的),我们就可以插入需要的数据啦。那么怎么将插入位置及之后的实际使用的元素都后移呢,只要我们从(实际存储的最后一个元素位置+1)开始,从后往前遍历数组,将数组的前一个值赋给后一个位置,直到插入位置,这样插入位置就空出来了

当然我们还有一个小问题,因为之前说过length属性只能获得数组的容量大小,而不是实际使用的空间大小,但是在插入过程中我们需要从(实际存储的最后一个元素位置+1)进行操作,也就是我们需要获得数组的实际使用空间,怎么办呢?很容易,只要定义一个变量用来记录数组中的元素个数,当插入元素时(个数+1),当删除元素时(个数-1)就可以了

为了更清楚的理解插入操作,先上图

Java - 数组详解(图解数组的基本操作)

上代码:

 public class ArrayOperate {

     /** 给数组一个容量 此处给个5*/
private int capacity = 5;
/** 定义一个数组 数组长度为capacity给定 5*/
private int[] arr = new int[capacity];
/** 用来存储数组的实际使用空间 */
private int count; /**
* 向数组中index下标处插入元素
*/
public boolean insert(int index,int inner){
//---------------------【在index下标处插入元素 - 关键代码】
if(this.count>=this.capacity){
// 当实际元素个数等于数组容量时 数组已满 不能插入
System.err.println("数组已满");
return false;
}
if(index<0||index>count){
// 当插入位置不在(0和count)之间时 不能插入数据
System.err.println("请在 0-"+count+"之间插入数据");
return false;
} for(int i=count;i>index;i--){
this.arr[i]=this.arr[i-1];// 数组元素依次向后移动
}
this.arr[index]=inner;//给数组index下标处赋值插入元素
count++;//插入数据后 实际大小需要+1
return true;
} /** 在数组的后面添加元素 */
public boolean append(int inner){
/*
* 在数组的后添加元素
* 我们可以这样写:
* if(this.count>=arr.length){
* return false;//先判断数组是否已满 如果满了就不允许插入元素了
* }
* if(index<0||index>count){
* return false;
* }
* arr[count]=inner;//为数组赋值【因为数组的下标是从0开始的,所以数组的实际添加的最后一个位置是count-1,所以如果需要在后面添加元素的话arr[count]就可以了】
* count++;
* return true;
*/ // 但是因为在之前实现了在数组index位置插入元素的方法 我们只需要调用该方法就可以了
// 在数组count位置插入元素
return insert(count,inner);
} public static void main(String[] args) { // 测试
ArrayOperate arrs=new ArrayOperate();
// 为数组初始化元素
arrs.append(12);
arrs.append(10);
arrs.append(5);
arrs.append(20);
System.out.println(Arrays.toString(arrs.arr));// 打印初始化的数组元素
// 在数组的第二位置插入16
arrs.insert(1, 16);
System.out.println(Arrays.toString(arrs.arr));// 打印插入后的数组元素 } }

Java - 数组详解(图解数组的基本操作)

删除

既然有插入操作自然有删除,与插入相似,我们只需要将移动数据的部分反过来就可以了

上图

Java - 数组详解(图解数组的基本操作)

上代码

     public boolean delete(int index){

         // 判断数组是否为空了 如果为空,则不能再删除元素
if(count==0){
System.err.println("数组以空");
return false;
}
// 判断输入的下标是否超过指定范围 超过则不能再删除数据
if(index<0||index>=count){
System.out.println("请在 0-"+(count-1)+"之间删除数据");
return false;
}
// 从index开始,将后一个元素赋值给前面,知道到最后一个实际元素
for(int i=index;i<count-1;i++){//当最后一个元素时 应该是 arr[length-2]=arr[length-1]; 所以应该(i<length-1)
this.arr[i]=this.arr[i+1];
}
// 给最后一个元素补0
// 并将元素使用长度-1
this.arr[--count]=0; return true;
} public boolean delete(){
/*
* 同样的 我们可以调用之间写的delete(index)方法删除最后一个元素
* 也可以这样写
* if(count<=0){
* return false;
* }
* if(index<0||index>=count){
* return false;
* }
* arr[--count]=0;
* return true;
*/
return this.delete(count-1);
}
 // 测试 -- 删除数组上的第二个元素
arrs.delete(1);
System.out.println(Arrays.toString(arrs.arr)); 

Java - 数组详解(图解数组的基本操作)

扩容

之前我们强调过,数组长度是固定的,那么我么怎么对数组进行扩容呢?其实只要重新创建一个数组,其长度比原有数组长度大n,并将原数组中的内容复制到新数组中,然后将新数组的地址引用赋给数组变量就能完成对原数组的扩容(不过因为每次都需要新创建一个数组并复制原数组的值,所以其性能会比较低)

看一个图

Java - 数组详解(图解数组的基本操作)

理解了这个,写代码就很容易了

     /** 给数组扩充addLength个长度 */
public boolean exCapacity(int addLength){
if(addLength<0){
// 如果输入的长度小于0,则禁止扩容 因为参数是负数 其新创建的数组的长度比原数组要小,在下面的复制操作中会下标越界
System.err.println("请输入大于0的整数");
return false;
}
// 创建一个临时数组 其长度为本数组长度+扩充长度
int[] tp=new int[this.arr.length+addLength];
for (int i = 0; i < this.arr.length; i++) {
tp[i]=this.arr[i];// 将原数组内容复制到新数组中
}
this.arr=tp;// 将新数组的地址引用赋给数组变量
this.capacity=this.arr.length;// 扩容后将数组的长度赋值给capacity
return true;
}

Java - 数组详解(图解数组的基本操作)

反转

在题目中我们经常会遇到将一个数组反转,那么我们先分析一个例子,[1,2,3]的反转数组为[3,2,1],[1,2,2,1]的反转数组为[1,2,2,1],此时看来,将[1,2,3]的1,3交换就变成了[3,2,1],将[1,2,2,1]的1和1交换,2和2交换同样变成了反转数组;将反转一个数组其实只需要在数组的中心位置将两边的对称位置的元素进行交换就可以了

看图

Java - 数组详解(图解数组的基本操作)

代码

     /** 反转数组 */
public void reverse(){
// 当为count时 只对实际存储的元素进行反转
// 当将count转换为arr.length时 会反转整个数组
for(int i=0;i<count/2;i++){
// 交换对称的两个元素
int a=arr[i];
arr[i]=arr[count-1-i];
arr[count-1-i]=a;
}
}

Java - 数组详解(图解数组的基本操作)

Java - 数组详解(图解数组的基本操作)

 最后附上源码

https://files.cnblogs.com/files/wangbingc/ArrayOperate.rar


今天先讲到这里,第一次写博客ヾ ^_^♪如果有什么不对的, 欢迎大家指正,谢谢ლ(╹◡╹ლ)

Java - 数组详解(图解数组的基本操作)的更多相关文章

  1. Java基础之 数组详解

    前言:Java内功心法之数组详解,看完这篇你向Java大神的路上又迈出了一步(有什么问题或者需要资料可以联系我的扣扣:734999078) 数组概念 同一种类型数据的集合.其实数组就是一个容器. 数组 ...

  2. &OpenCurlyDoubleQuote;全栈2019”Java第三十一章:二维数组和多维数组详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  3. &OpenCurlyDoubleQuote;全栈2019”Java第三十章:数组详解(下篇)

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  4. &OpenCurlyDoubleQuote;全栈2019”Java第二十九章:数组详解(中篇)

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. &OpenCurlyDoubleQuote;全栈2019”Java第二十八章:数组详解(上篇)

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. 3&period;awk数组详解及企业实战案例

    awk数组详解及企业实战案例 3.打印数组: [root@nfs-server test]# awk 'BEGIN{array[1]="zhurui";array[2]=&quot ...

  7. JavaScript进阶&lpar;十&rpar;Array 数组详解

    JS array 数组详解 数组的声明方法 arrayObj = new Array(); 的数组 ,并且第一位是5 数组的运算(传地址) var t2=new Array(); t2[0]=1; t ...

  8. Swift&lowbar;数组详解

    Swift_数组详解 点击查看源码 初始化 //初始化 fileprivate func testInit() { //空数组 var array = [Int]() print(array) arr ...

  9. &lpar;转&rpar;awk数组详解及企业实战案例

    awk数组详解及企业实战案例 原文:http://www.cnblogs.com/hackerer/p/5365967.html#_label03.打印数组:1. [root@nfs-server t ...

随机推荐

  1. mac homebrew的用法

    与 MacPorts 类似,OS X 下还有款包管理工具为 Homebrew,安装方法也很简单. ruby -e "$(curl -fsSL https://raw.github.com/H ...

  2. HDU5127 神坑题---vector 、 list 、 deque 的用法区别

    题意:三个操作 1  a b : 队列中加入(x = a, y = b); -1  a b : 队列中减去(x = a, y = b); 0  p q :从队列的数对中查询哪一对x,y能够让 p * ...

  3. java和linux的编码

    最近要使用中科院计算所的关键词工具NLPIR,用java调用,在windows下测试后放到linux下跑,就发现会有乱码. windows下默认是GBK,linux下是utf-8,因此在意料之中(尽管 ...

  4. mysql toolkit 用法&lbrack;备忘&rsqb; (转&rpar;

    命令列表 /usr/bin/pt-agent /usr/bin/pt-align /usr/bin/pt-archiver /usr/bin/pt-config-diff /usr/bin/pt-de ...

  5. MySQL timed&lowbar;mutexes

    提要: MySQL 5.5.39 Release版本正式从源码里删除了全局参数timed_mutexes.timed_mutexes原本用来控制是否对Innodb引擎的mutex wait进行 计时统 ...

  6. linux&lowbar;后台启动多个java -jar 程序,及关闭

    启动脚本 startup.sh #!/bin/bash x=$(($)) )) do java -jar /home/chenpenghui/crawler/crawler-hb/StartUpIp. ...

  7. Angular2&period;js——表单(下)

    这部分是接表单上部分的内容,主要内容有: 1.添加自定义的CSS来提供视觉反馈: 2.显示和隐藏有效性验证的错误信息: 3.使用ngSubmit处理表单提交: 4.禁用表单提交按钮. 添加自定义的CS ...

  8. Android:进程优先级

    进程优先级 优先级 服务 说明 高优先级 前台进程 ①该进程包含正在与用户进行交互的界面组件,比如一个Activity. ②进程服务被Activity调用,而且这个Activity正在与用户进行交互 ...

  9. PHP 异步使用swoole的可行性测试

    PHP的异步.并行.高性能网络通信引擎swoole框架,在一开始我就比较注意,原因无他,php在swoole未出的情况下在多线程调度上确实算得上没有较好的解决方案. 我以系统的注册流程举例,在比较复杂 ...

  10. Python大法之告别脚本小子系列—各类URL采集器编写

    本文作者:i春秋签约作家——阿甫哥哥 系列文章专辑:https://bbs.ichunqiu.com/forum.php?mod=collection&action=view&ctid ...