目录

首先

什么是数组

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

数组的定义和内存分配

在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]+"]");
}

数组的内存图解


数组的遍历

我们常使用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+", ");
}
}


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

插入

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

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

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

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

上代码:

 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));// 打印插入后的数组元素 } }

删除

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

上图

上代码

     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)); 

扩容

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

看一个图

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

     /** 给数组扩充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;
}

反转

在题目中我们经常会遇到将一个数组反转,那么我们先分析一个例子,[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交换同样变成了反转数组;将反转一个数组其实只需要在数组的中心位置将两边的对称位置的元素进行交换就可以了

看图

代码

     /** 反转数组 */
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;
}
}

 最后附上源码

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


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

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

  1. Java基础之 数组详解

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

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

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

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

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

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

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

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

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

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

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

  7. JavaScript进阶(十)Array 数组详解

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

  8. Swift_数组详解

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

  9. (转)awk数组详解及企业实战案例

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

随机推荐

  1. 使用cert-manager实现Ingress https

    什么是https 超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报 ...

  2. QString与LPWSTR之间的转换;

    QString 转换成 LPWSTR LPWSTR lpStr = (LPWSTR) QString("nihao").toStdWString().c_str();

  3. js实现点气球小游戏

    二话不说直接贴代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  4. atool-build 打包项目报JavaScript heap out of memory 错误

    出现这个问题的原因,是因为NodeJS给JavaScript设置了默认内存使用限制(32位系统下0.7GB,64位系统下1.4GB),就算我们的电脑内存是64GB的,在使用atool-build打包时 ...

  5. Java基础--面向对象编程3(继承)

    1.继承的作用 为了提取两个类中公共的代码,可以使用继承抽取重复性的代码到一个公共类中. 这个公共的类称为父类(super class),继承于父类的类称为子类(sub class). 2.java继 ...

  6. 编写高质量的Python代码系列(二)之函数

    Python中的函数具备多种特性,这可以简化编程工作.Python函数的某些性质与其他编程语言中的函数相似,但也有性质是Python独有的.本节将介绍如何用函数来表达亿图.提升可复用程度,并减少Bug ...

  7. Python 中使用 matplotlib 绘图中文字符显示异常的问题

    最近在使用 Python matplotlib 绘制图表时发现中文字符不能正确显示:比如在绘制折线图时,中文全部显示成▢▢▢的格式,虽然将数据改成英文就没什么问题,但是所有数据都这么做时不可行的,于是 ...

  8. SOA 和 微服务

    正在读 钟华 著的<<企业IT架构转型之道 - 阿里巴巴中台战略思想与架构实战>> 一书, 参考了网上的讨论,  对SOA和微服务有了一些新的认识. 知乎上的讨论: SOA 与 ...

  9. Oracle 11g 服务启动/关闭 及 DB dump 导入

    本地启动Oracle 服务脚本 由于本地机子安装了Oracle后,会自动启动一些默认的Oracle服务,这样子会导致机子比较慢.所以需要改成手动启动/关闭服务. 即用即开,不用就关. 开启的脚本: O ...

  10. 线程——自定义多线程task

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...