肝了一整天,关于Java数组,你想知道的都在这里!

简介: 肝了一整天,关于Java数组,你想知道的都在这里!

1. 什么是数组


数组是一种线性结构的数据结构。线性结构在内存中是连续的,是用来储存同一类型的数据的集合

数组特点 :连续 ,每个元素都有下标 ,可以快速查找 ,但是从中间添加,删除就比较麻烦

数组本身是引用数据类型,即对象。但是数组可以存储基本数据类型,也可以存储引用数据类型。


2.数组的声明


在声明数组变量时 , 需要给定数组类型(数组中存储的数据类型必须和数组的类型相同)和数组变量的名字 。

//第一种声明方式 
//数组类型[] 数组变量名字;
int[] a;
//第二种声明方式
//数组类型 数组变量名字[];
int a[];

注意:

在Java语言中两种声明方法没有任何区别,但是大多数 Java 程序员喜欢使用第一种声明风格,因为它将数组类型与变量名分开了 。


3.数组的创建


上面的这条语句只声明了变量a,并没有将a初始化为一个真正的数组。应该使用 new 运算符创建数组。


1.声明数组的同时,根据指定的长度分配内存,但数组中元素值都为默认的初始化值(int 类型就是0,String 类型就是null,Boolean 类型就是false)。

int [] a = new int [10];

创建了一个可以存储10个整数的数组,用这种方法创建数组时等号右边的中括号中的值就是数组存储数据的数量,中括号中不要求一定是一个常量。

声明出的这个数组下标是0 ~ 9,而不是1~10,数组的下标是从0开始的。

数组创建好之后就可以给数组元素赋值。

可以使用一个循环:

int [] a = new int [10];
for ( int i = 0;i<10; i++){    
    a[i] = i; //给下标为 i 的元素赋值为 i
}

执行for循环前的元素:

image.png

执行完for循环之后的元素:

image.png


注意:

循环的时候必须注意循环次数,a[i]中的 i 要是超出了0~9,就会报错

image.png

当出现上面的这个错误提示时就要检查是不是数组索引越界。

有时我们不知道数组的长度是多少时(数组长度是变量),为防止索引越界,我们要想获得数组长度,可以使用a.length。

image.png

由于数组下标是从0开始,循环时 i 的最大值应该为a.length-1。


2.声明数组并分配内存,同时将其初始化

int [] a = new int[]{1, 2, 3, 4, 5};


3.与前一种方式相同,仅仅只是语法相对简略

int[] a = {1, 2, 3, 4, 5};

Java中允许数组长度为0,在特殊情况下长度为0可以给我们提供便利。


注意:


一旦创建了数组,就不能再改变它的大小。如果经常需要在运行过程中扩展数组的大小,就应该使用另一种数据结构——数组列表。

数组长度为0和null是不一样的,null表示是这个数组为空,该数组不指向任何对象。在数组不为null时才可以对数组进行某些操作,这一点需要格外注意。


4. for each 循环


Java 有一种功能很强的循环结构,可以用来依次处理数组中的每个元素(其他类型的元素集合也可以)而不必为指定下标值而分心 。我们经常称之为增强for循环。

//增强for循环的基本格式
for(数组元素的类型  临时变量名 :数组的名字){
     //执行语句
}

定义一个变量用于暂存集合中的每一个元素 , 并执行相应的语句。

例如:输出数组 a 中的每一个元素。

image.png

虽然一般的for循环也可以达到相同的目的,但我们要时刻注意下标,不能索引越界。

image.png

相比之下for each循环语句显得更加简洁、更不易出错。

注意:

for each 循环语句的循环变量将会遍历数组中的每个元素,而不需要使用下标值 。

如果需要处理一个集合中的所有元素,for each循环语句对传统循环语句所进行的改进让人轻松了很多。然而,在很多场合下,还是需要使用传统的for循环,例如, 如果不希望遍历集合中的每个元素,或者在循环内部需要使用下标值等。


除了我们一般使用的利用循环来输出数组中的元素外,有个更加简单的方式输出数组中的所有值,即利用Arrays类的toString方法。调用 Arrays.toString (a) , 返回一个包含数组元素的字符串,这些元素被放置在括号内,并用逗号分隔,例如:

image.png


注意:

在使用Arrays类之前要先导包:

import java.util.Arrays;


5.数组拷贝


在 Java 中,我们可以将一个数组变量拷贝给另一个数组变量。这时,两个变量将引用同一 个数组 。

int [] a = {1,2,3,4,5,6};
int [] b = a;

在这时,我们不管操作哪个数组变量,另一个也会改变。如下:

当拷贝工作完成后,俩个数组中的元素一样:

image.png


操作b数组后,俩个数组的情况:

image.png


操作a数组后,俩个数组的变化:

image.png


如果我们想要将一个数组的所有值拷贝到一个新的数组中去,就要使用Arrays类的copyOf方法 。这个方法通常用来增加数组的大小。

int[] b = Arrays.copyOf(a, a.length);//方法中第二个参数是数组b的长度

这样也可以达到和上面那种方式相同的结果:

image.png


如果我们单纯的想要拷贝一个新的数组,不需要扩容的话就直接用旧数组的长度当作新数组的长度。如果想要增加数组的大小的话,可以这样做:

int[] b = Arrays.copyOf(a, 2*a.length);

image.png

扩容后多余的数组元素,就为数据类型对应的默认初始化值。

如果新数组的长度比旧数组的长度小的话,就会只拷贝最前面的数据元素。如下:

image.png

注意:

Java 数组与 C++ 数组有些不同

int [] a = new int [100]; // Java

不同于

int a [100]; // C++语法

而等同于

int * a = new int [100]; // C++语法

而且需要注意的是Java没有指针运算,不能通过 a 加1得到数组的下一个元素 。


6.数组排序


1.Arrays 类中的 sort 方法

要想对数值型数组进行排序,Java中可以使用 Arrays 类中的 sort 方法

int [] a = {2,5,9,1,3,4};
Arrays.sort(a);
System.out.println(Arrays.toString(a));

如图所示:

image.png


2.冒泡排序

for (int i = 0; i < a.length-1; i++)      //决定循环的次数
{    
    for (int j = 0; j < a.length-i-1; j++)//每次循环比较的次数    
    {        
        if(a[j]>a[j+1])                   //从小到大排序        
        {            
            int temp=a[j];            
            a[j]=a[j+1];            
            a[j+1]=temp;                  //把大的放到后面
        }    
    }
}

冒泡排序就是重复遍历元素列,依次比较两个相邻的元素,如果后一个比前一个数小,就交换俩个位置,一直重复此动作,直到没有需要交换的元素。

image.png


3.选择排序

for (int i = 0; i < a.length-1; i++)      //决定循环的次数
{    for (int j = i+1; j < a.length; j++) //将索引j后移    
     {        
          if(a[i]>a[j])     //把第一个数和后面的每一个做比较,缺点是,条件每成立一次就交换一次                 {            
              int temp=a[i];            
              a[i]=a[j];            
              a[j]=temp;        
          }    
     }
}

这种选择排序就是需要交换的次数多,拿第一个元素和后面元素比较,遇到比它小的元素就交换一次,然后再拿交换后成为第一个的元素和后面的比较,可能后面还有更小的,还得再交换,和所有的元素比较完之后,再拿第二个元素和后面的比较,重复操作,直至比较完。到最后,交换元素操作就会进行很多次,针对这个问题进行优化。


优化后的选择排序:

for (int i = 0; i < a.length-1; i++)     //决定循环的次数
{    
     int minIndex = i;    
     for (int j = i+1; j < a.length; j++) //将索引j后移    
     {        
              if(a[minIndex]>a[j])        //把第一个数和后面的每一个做比较,将最小的值的索引记录 
              {            
                   minIndex=j;        
              }    
     }    
     //将第一个值和后面几个数中最小的那个交换位置    
     int temp=a[i];    
     a[i]=a[minIndex];    
     a[minIndex]=temp;
}

优化后的选择排序将后面数据中最小的元素索引记录下来,只需要交换一次就可以将最小的放到最前面。


4.插入排序

int temp;
for (int i = 0; i < a.length - 1; i++)
{    
    temp = a[i + 1];    
    int Index = i;    
    for (;Index >= 0 && temp < a[Index];Index--)    
    {        
        a[Index + 1] = a[Index];    
    }    
    a[Index + 1] = temp;
}

解释:假设第一个元素为已经排过序的元素,我们提取一个没有排过序的元素(排过序元素的后一个,现在也就是第二个),拿第二个元素和第一个元素比较,如果比第一个元素小就将第二个元素插入第一个元素之前,否则就在第一个元素之后插入该元素,现在就有俩个元素是排过序的了,再提取一个没排过序的元素(第三个),拿这个元素与已排序的元素一一比较,插入到比它大的元素的前面,然后再与前面已排序的元素比较,直至比完,重复上述动作,直至数组中的数据都是已排序的数据。


7.多维数组


Java 实际上没有多维数组, 只有一维数组。多维数组被解释为 “ 数组的数组 “。


——《Java核心基础 卷1(第十版)》

但这并不影响我们按照多维数组的概念理解它。

多维数组将使用多个下标访问数组元素,它适用于表示表格或更加复杂的排列形式。

我们主要以二维数组举例:


1. 定义

二维数组就是指数组里面的元素也是数组,

数组的数组—二维数组的每一个元素是一个一维数组

int [][]a = {{1,2,3},{1,2,3},{1,2,3}};

2.声明

//第一种声明方式
int [][] a;//建议使用这种,可以把数组类型和变量名分开
//第二种声明方式
int a[][];

这只是声明,在没有初始化之前不能使用它


3.创建/初始化

数组创建

//定义了一个整型的二维数组,这个二维数组有3个一维数组,每一个一维数组包含3个元素,并且对每个元素都进行了赋值
int [][]a = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
//简写
int [][] b  = {{1,2,3},{4,5,6},{7,8,9}};
//定义了一个整型的二维数组 ,这个二维数组有3个一维数组,每一个一维数组包含5个元素.每个元素没有赋值
int [][] c = new int[3][5];

数组被初始化之后,就可以利用两个方括号访问每个元素,例如,b[1] [2]表示二维数组b中的索引为1的一维数组中的索引为2的元素,也就是6。

image.png


4.迭代

for each 循环语句不能自动处理二维数组的每一个元素。它是按照行,也就是一维数组处理的,要想访问二维数组 a 的所有元素,需要使用两个嵌套的循环。

//for循环语句
int [][] a = new int [][]{{1,2},{3,4}};
for(int i =0;i<a.length;i++){//循环外部数组  i=0时内层循环{1,2}   i=1时到{3,4}
   for(int j =0;j<a[i].length;j++){  //循环内部数组  
         System.out.println(a[i][j]);
   }
}
/*
//for each 循环语句
for (int[] a1 : a) {
    for (int a2 : a1) {
         System.out.println(a2);
    }
}
*/

image.png


8.不规则数组


什么是不规则数组呢?

拿二维数组来说,不规则数组就是二维数组中的一维数组中存储的元素数量都不相同。

例如:

int[][] a = {{1,2,3}, {4,5}};

不规则数组怎么使用?

要想创建一个不规则的数组 , 首先需要一个规定了一维数组数量的二维数组 。

int[][] a = new int[5][];

然后再来规定一维数组的大小

for (int n = 0; n < 5; n++){   
    a[n] = new int[n+1];
}

然后我们就可以在索引不越界的前提下,来访问这些元素

for (int n = 0; n < a.length; n++) {    
    for (int k = 0; k < a[n].length; k++) {        
        a[n][k] = k+1;    
    }    
    System.out.println(Arrays.toString(a[n]));
}

image.png

有关数组的知识我就总结了这些,其中可能有不周到的地方,欢迎大家在评论区批评指点。


目录
相关文章
|
2月前
|
存储 缓存 算法
Java 数组
【10月更文挑战第19天】Java 数组是一种非常实用的数据结构,它为我们提供了一种简单而有效的方式来存储和管理数据。通过合理地使用数组,我们能够提高程序的运行效率和代码的可读性。更加深入地了解和掌握 Java 数组的特性和应用,为我们的编程之旅增添更多的精彩。
36 4
|
2月前
|
存储 缓存 算法
提高 Java 数组性能的方法
【10月更文挑战第19天】深入探讨了提高 Java 数组性能的多种方法。通过合理运用这些策略,我们可以在处理数组时获得更好的性能表现,提升程序的运行效率。
43 2
|
2月前
|
存储 Java
Java“(array) <X> Not Initialized” (数组未初始化)错误解决
在Java中,遇到“(array) &lt;X&gt; Not Initialized”(数组未初始化)错误时,表示数组变量已被声明但尚未初始化。解决方法是在使用数组之前,通过指定数组的大小和类型来初始化数组,例如:`int[] arr = new int[5];` 或 `String[] strArr = new String[10];`。
99 2
|
2月前
|
存储 Java
什么是带有示例的 Java 中的交错数组?
什么是带有示例的 Java 中的交错数组?
56 9
|
2月前
|
Java
Java数组动态扩容和动态缩减
Java数组动态扩容和动态缩减
27 3
|
2月前
|
存储 算法 Java
Java一分钟之-数组的创建与遍历
数组作为Java中存储和操作一组相同类型数据的基本结构,其创建和遍历是编程基础中的基础。通过不同的创建方式,可以根据实际需求灵活地初始化数组。而选择合适的遍历方法,则可以提高代码的可读性和效率。掌握这些基本技能,对于深入学习Java乃至其他编程语言的数据结构和算法都是至关重要的。
33 6
|
2月前
|
存储 Java 程序员
【一步一步了解Java系列】:何为数组,何为引用类型
【一步一步了解Java系列】:何为数组,何为引用类型
34 1
|
2月前
|
存储 XML Java
如何在 Java 中将常见文档转换为 PNG 图像数组
如何在 Java 中将常见文档转换为 PNG 图像数组
20 1
|
2月前
|
存储 安全 Java
Java数组(Arrays)详解
Java 中的数组是一种用于存储固定数量同类型数据的高效数据结构,支持连续内存存储和随机访问。数组可以声明并初始化,通过索引访问和修改元素,获取长度,使用循环遍历,支持多维形式,并可通过 `Arrays` 类的方法进行复制和排序。数组具有固定大小和类型安全的特点,但需注意越界等问题。灵活运用数组能显著提升编程效率。
134 9
|
3月前
|
存储 Java 数据处理
Java 数组的高级用法
在 Java 中,数组不仅可以存储同类型的数据,还支持多种高级用法,如多维数组(常用于矩阵)、动态创建数组、克隆数组、使用 `java.util.Arrays` 进行排序和搜索、与集合相互转换、增强 for 循环遍历、匿名数组传递以及利用 `Arrays.equals()` 比较数组内容。这些技巧能提升代码的灵活性和可读性,适用于更复杂的数据处理场景。
44 10