分享数组的学习心得

206 阅读15分钟

[toc]

数组(掌握)

一、数组的定义

在Java中,可以使用以下格式来定义一个数组,如下:

数据类型 [] 数组名 = new 数据类型 [元素个数或数组长度];

int [] x = new int [100];

上述语句就相当于在内存中定义了100个int类型的变量,第一个变量的名称为 x[0] ,第二个变量的名称为x[1] ,以此类推,第100个变量的名称为 x[99] ,这些变量的初始值都是 0 。为了更好地理解数组的这种定义方式,可以将上面的一句代码分成两句来写,具体如下:

//声明一个int[]类型的变量
int [] x;
//创建一个长度为100的数组
x = new int[100];

数组中的每个元素都有一个索引(也可称为角标),要想访问数组中的元素可以通过“x[0]、x[1]、……x[98]、x[99]”的形式。需要注意的是,数组中==最小的索引是0==,==最大的索引是“数组的长度-1”==。在Java中,为了方便我们获得数组的长度,提供了一个length 属性,在程序中可以通过==“数组名.length”==的方式来获得数组的长度,即元素的个数。

接下来,通过一个案例来演示如何定义数组以及访问数组中的元素,如下所示。ArrayDemo01.java

//声明变量
int[] arr;
//创建数组对象
arr = new int[3];
System.out.println("arr[0] = " + arr[0]);//访问数组中的第一个元素
System.out.println("arr[1] = " + arr[1]);//访问数组中的第二个元素
System.out.println("arr[2] = " + arr[2]);//访问数组中的第三个元素
System.out.println("数组的长度是" + arr.length);//打印数组的长度

运行结果如下所示:

arr[0] = 0 arr[1] = 0 arr[2] = 0 数组的长度是3

在上述代码中声明了一个int[]类型变量arr,并将数组在内存中的地址赋值给它。在5~7行代码中通过角 标来访问数组中的元素,在第8行代码中通过length属性访问数组中元素的个数。从打印结果可以看出,数组中的三个元素初始值都为0,这是因为当数组被成功创建后,数组中元素会被自动赋予一个默认值,根据元素类型的不同,默认初始化的值也是不一样的。具体如下表所示。

元素的默认值

数据类型 默认初始值
byte、short、int、long 0
float、double 0.0
char 一个空字符(空格),即'\u0000'
boolean false
引用数据类型 null,表示变量不引用任何对象

如果在使用数组时,不想使用这些默认初始值,也可以显式地为这些元素赋值。接下来通过一个程序来学习如何为数组的元素赋值,如下所示。ArrayDemo02.java

int [] arr = new int[4];
arr[0] = 1;//为第一个元素赋值1
arr[1] = 2;//为第二个元素赋值2
//打印每个元素的值
System.out.println("arr[0] = " + arr[0]);
System.out.println("arr[1] = " + arr[1]);
System.out.println("arr[2] = " + arr[2]);
System.out.println("arr[3] = " + arr[3]);

运行结果如下所示:

arr[0] = 1 arr[1] = 2 arr[2] = 0 arr[3] = 0

在上述代码中,第1行代码定义了一个数组,此时数组中每个元素都为默认初始值0。第2、3行代码通过赋值语句将数组中的元素arr[0]和arr[1]分别赋值为1和2,而元素arr[2]和arr[3]没有赋值,其值仍为0,因此打印结果中四个元素的值依次为1、2、0、0。

在定义数组时只指定数组的长度,由系统自动为元素赋初值的方式==称作动态初始化。==

在初始化数组时还有一种方式叫做==静态初始化==,就是在定义数组的同时就为数组的每个元素赋值。数组的静态初始化有两种方式,具体格式如下:

1、类型 [] 数组名 = new 类型 [] {元素,元素,.........};

2、类型 [] 数组名 = {元素,元素,元素,......};

上面的两种方式都可以实现数组的静态初始化,但是为了简便,建议采用第二种方式。接下来通过一 段代码来演示数组静态初始化的效果,如下所示。ArrayDemo03.java

//数组的静态初始化
int [] arr = {1,2,3,4};
//打印每个元素的值
System.out.println("arr[0] = " + arr[0]);
System.out.println("arr[1] = " + arr[1]);
System.out.println("arr[2] = " + arr[2]);
System.out.println("arr[3] = " + arr[3]);

==注意:==

上述代码中采用静态初始化的方式为数组每个元素赋予初值,分别是1、2、3、4。需要注意的是第2行代码千万不可写成int[] arr = new int[4]{1,2,3,4};,这样写编译器会报错。原因在于编译器会认为数组限定的元素个数[4]与实际存储的元素{1,2,3,4}个数有可能不一致,存在一定的安全隐患。

二、数组的遍历

在操作数组时,经常需要依次访问数组中的每个元素,这种操作称作数组的遍历。接下来通过一个案 例来学习如何使用for循环来遍历数组,如下所示。ArrayDemo04.java

//数组的静态初始化
int [] arr = {1,2,3,4};
//用for循环遍历数组的元素
for (int i = 0; i <arr.length ; i++) {
    System.out.println("arr["+i+"] = " + arr[i]);
}

运行结果如下所示:

arr[0] = 1 arr[1] = 2 arr[2] = 3 arr[3] = 4

上述代码中,定义一个长度为5的数组arr,数组的角标为 0~4 。由于for循环中定义的变量 i 的值在 循环过程中为 0~4 ,因此可以作为索引,依次去访问数组中的元素,并将元素的值打印出来。

三、高级for循环遍历数组

我们也可以通过高级for循环(for each循环)来访问数组中的每个元素,接下来我们通过一个案例来学习如何使用高级for循环来遍历数组。如下所示。ArrayDemo05.java

高级for循环(for each)的语法格式:

for(每一个元素的数据类型 临时变量名 : 要循环的容器的变量名){

​ 语句体;

}

//数组的静态初始化
int[] arr = {1, 2, 3, 4};
//用高级for循环遍历数组的元素
for (int i : arr) {
    System.out.println(i);
}

注意:for each循环当中的i的值指的是数组arr中的每个元素的值。

四、数组中常见的问题

4.1、数组的最值

在操作数组时,经常需要获取数组中元素的最值。接下来通过一个案例来演示如何获取数组中元素的 最大值,如下所示。ArrayDemo06.java

//数组的静态初始化
int[] arr = {1, 2, 3, 4, 5, 423, 32, 31231, 3432, 32, 435, 76};
//假设最大值的索引为0
int max = 0;
for (int i = 1; i < arr.length; i++) {
    //如果下一个索引的值比设置的max的值大,就将该值重新赋值给max
    if (arr[i] > max) {
        max = arr[i];
    }
}
System.out.println(max);

上述代码中,定义了一个临时变量max,用于记住数组的最大值。通过for 循环获取数组中的最大值,赋值给max变量。

步骤:

首先假设数组中第一个元素arr[0]为最大值,然后使用for循环对数组进行遍历,在遍历的过程中只要遇到比max值还大的元素,就将该元素赋值给max。这样一来,变量max就能够在循环结束时记住数组中的最大值。需要注意的是,在for循环中的变量i是从1开始的,这样写的原因是程序已经假设第一个元素为最大值,for循环中只需要从第二个元素开始比较,从而提高程序的运行效率。

4.2、在数组中增加一个数

图解:

在数组中增加一个数.png

/**
 * 从数组中增加一个数,生成新的一个数组
 *
 * @param arr   传入一个数组
 * @param index 索引
 * @param num   数值
 * @return
 */
public static int[] addArrays(int[] arr, int index, int num) {
    int[] temp = new int[arr.length + 1];

    for (int i = 0; i < index; i++) {
        temp[i] = arr[i];
    }

    for (int i = index; i < arr.length; i++) {
        if (i == index) {
            temp[i] = num;
        }
        temp[i + 1] = arr[i];
    }

    return temp;
}

4.3、在数组中去掉一个数

图解:

在数组中去掉一个数.png

/**
 * 从数组中删除一个数,生成一个新的数组
 *
 * @param arr   传入一个数组
 * @param index 索引
 * @return
 */
public static int[] delArrays(int[] arr, int index) {
    int[] temp = new int[arr.length - 1];

    for (int i = 0; i < index; i++) {
        temp[i] = arr[i];
    }

    for (int i = index; i < arr.length; i++) {

        if (i < temp.length) {

            temp[i] = arr[i + 1];

        }
    }
    return temp;


}

4.4、在数组中替换一个数

/**
 * 从数组中改变一个数,并返回新的一个改变的数组
 *
 * @param arr   传入一个数组
 * @param index 索引
 * @param num   数值
 * @return
 */
public static int[] replace(int[] arr, int index, int num) {
    int[] newArray = new int[arr.length];

    for (int i = 0; i < arr.length; i++) {

        newArray[i] = arr[i];
        if (i == index) {
            newArray[i] = num;
        }

    }

    return newArray;
}

4.5、数组的求和

/**
  * 数组中的元素相加和
  *
  * @param arr 传入数组
  * @return
  */
public static int sumAdd(int[] arr) {
    int sum = 0;
    for (int i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    return sum;
}

五、数组的异常问题

5.1、数组越界异常

每个数组的索引都有一个范围,即0~length-1。在访问数组的元素时,索引不能超出这个范围,否则程 序会报错,如下所示。ArrayDemo07.java

//定义一个长度为4的数组
int[] arr = new int[4];
//通过角标4访问数组元素
System.out.println("arr[4] = " + arr[4]);

运行结果如下所示:

Exception in thread "main" ==java.lang.ArrayIndexOutOfBoundsException==: Index 4 out of bounds for length 4 at com.bjsxt.demo.ArrayDemo01.main(ArrayDemo01.java:8)

上图运行结果中所提示的错误信息是数组越界异常ArrayIndexOutOfBoundsException,出现这个异常的 原因是数组的长度为4,其索引范围为0~3,而上述代码中的第4行代码使用索引4来访问元素时超出了数组的索引范围。所谓异常指程序中出现的错误,它会报告出错的异常类型、出错的行号以及出错的原因,关于异常在后面的章节会有详细地讲解。

5.2、空指针异常

在使用变量引用一个数组时,变量必须指向一个有效的数组对象,如果该变量的值为null,则意味着没有指向任何数组,此时通过该变量访问数组的元素会出现空指针异常,接下来通过一个案例来演示这种异常,如下所示。ArrayDemo08.java

int[] arr = new int[3]; // 定义一个长度为3的数组
arr[0]=5;//为数组的第一个元素赋值
System.out.println("arr[0] = " + arr[0]);//访问数组的元素
arr = null;//将数组arr置为null
System.out.println("arr[0] = " + arr[0]);//访问数组的元素

运行结果如下所示:

arr[0] = 5 Exception in thread "main" ==java.lang.NullPointerException== at com.bjsxt.demo.ArrayDemo01.main(ArrayDemo01.java:9)

通过上图所示的运行结果可以看出,上述代码中第2、3行代码都能通过变量arr正常地操作数组。第6 行代码将变量置为null,当第7行代码再次访问数组时就出现了空指针异常NullPointerException。

六、Arrays工具类

package com.bjsxt.demo;

import java.util.Arrays;

/**
 * @author Rainbow
 */
public class ArraysDemo {
    public static void main(String[] args) {
        int[] arr = {2, 5, 2, 2, 1, 23, 1213, 43, 322, 1312, 4343, 32255, 34};
        int[] arr2 = {2, 5, 2, 2, 1, 23, 1213, 43, 322, 1312, 4343, 32255, 34};
//      sort排序从小大
        Arrays.sort(arr);

//      将数组中的数据返回字符串
        System.out.println(Arrays.toString(arr));

//      采用二分法搜索算法查找值50,如果查找成功,则返回相应的下标值,否则返回一个负数值
        int index = Arrays.binarySearch(arr, 50);
        System.out.println(index);

//      采用二分法搜索算法查找值5,如果查找成功,则返回相应的下标值,否则返回一个负数值
//      左闭右开[fromIndex,toIndex)
        int index2 = Arrays.binarySearch(arr, 2, 4, 2);
        System.out.println(index2);

//      替换全部
        Arrays.fill(arr, 50);
        System.out.println(Arrays.toString(arr));

//      替换区间(左闭右开)
        Arrays.fill(arr, 2, 4, 100);
        System.out.println(Arrays.toString(arr));

//      拷贝数组指定拷贝的索引从0开始到newLength结束
        int[] newArr = Arrays.copyOf(arr, 5);
        System.out.println(Arrays.toString(newArr));

//      拷贝数组指定拷贝的索引从2开始到索引5结束(左闭右开)
        newArr = Arrays.copyOfRange(arr, 2, 5);
        System.out.println(Arrays.toString(newArr));

//      只有两个数组大小相同,并且下标相同的元素都对应相等,返回true,否则返回false
        boolean bool = Arrays.equals(arr, arr2);
        System.out.println(bool);

//      采用二分法搜索算法查找值50,如果查找成功,则返回相应的下标值,否则返回一个负数值
        int index3 = Arrays.binarySearch(arr, 50);
        System.out.println(index3);
    }
}

运行结果如下:

[1, 2, 2, 2, 5, 23, 34, 43, 322, 1213, 1312, 4343, 32255] -9 2 [50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50] [50, 50, 100, 100, 50, 50, 50, 50, 50, 50, 50, 50, 50] [50, 50, 100, 100, 50] [100, 100, 50] false 6

二维数组(了解)

一、二维数组的定义格式

二维数组的定义有很多方式,接下来针对几种常见的方式进行详细地讲解,具体如下:

第一种方式:

int[][] [] [] arr = new int [3] [4];

上面的代码相当于定义了一个3*4的二维数组,即二维数组的长度为3,二维数组中的每个元素又是一 个长度为4的数组,接下来用一个图来表示这种情况,如下图所示:

图解:

二维数组的第一种格式.png

第二种方式:

int[][] [] [] arr = new int [3] [];

第二种方式和第一种类似,只是数组中每个元素的长度不确定,接下来用一个图来表示这种情况,如下图所示:

图解:

二维数组的第二种格式.png

第三种方式:

int[][] [] [] arr = {{1,2},{3,4,5,6},{7,8,9}};

上面的二维数组中定义了三个元素,这三个元素都是数组,分别为{1,2}、{3,4,5,6}、{7,8,9},接下来通 过一个图来表示这种情况,如下图所示。

图解:

二维数组的第三种格式.png

对二维数组中元素的访问也是通过角标的方式,如需访问二维数组中第一个元素数组的第二个元素, 具体代码如下:

arr[0][1];

二、二维数组元素的访问

操作二维数组时,经常需要获取数组中元素的值。接下来通过一个案例来演示如何获取数组中元素 值,如下所示。ArrayDemo08.java

//定义一个二位数组
int[][] arr = new int[3][4];
//打印二维数组的长度
System.out.println("二维数组的长度" + arr.length);
//打印二位数组的元素
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
//打印第一个一维数组的元素
System.out.println(arr[0][0]);
System.out.println(arr[0][1]);
System.out.println(arr[0][2]);
System.out.println(arr[0][3]);
//打印第二个一维数组的元素
System.out.println(arr[1][0]);
System.out.println(arr[1][1]);
System.out.println(arr[1][2]);
System.out.println(arr[1][3]);
//打印第三个一维数组的元素
System.out.println(arr[2][0]);
System.out.println(arr[2][1]);
System.out.println(arr[2][2]);
System.out.println(arr[2][3]);

运行结果如下所示:

二维数组的长度3 [I@312b1dae [I@7530d0a [I@27bc2616 0 0 0 0 0 0 0 0 0 0 0 0

三、二维数组元素遍历与数组元素累加和

学习完了数组元素的访问,我们来学习下数组的遍历及数组的元素累加和操作。

/**
 * 遍历二维数组元素并求和
 *
 * @param arr 二维数组
 * @return
 */
public static int sumAdd(int[][] arr) {

    int sum = 0;
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr[i].length; j++) {
            sum += arr[i][j];
        }
    }
    return sum;
}

四、二维数组习题练习

接下来通过一个案例来熟悉二维数组的使用。 例如:要统计一个公司三个销售小组中每个小组的总销售额以及整个公司的销售额。如下所示

  • 第一小组销售额为{11, 12}万元
  • 第二小组销售额为{21, 22, 23}万元
  • 第三小组销售额为{31, 32, 33, 34}万元。
public class ArrayDemo3 {
    public static void main(String[] args) {
        int[][] arr = new int[3][];
        //每一组的销售金额
        arr[0] = new int[]{11, 12};
        arr[1] = new int[]{21, 22, 23};
        arr[2] = new int[]{31, 32, 33, 34};

        //记录所有组的销售总额
        int sum = 0;
        //记录每一组的销售总额
        int groupSum = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                groupSum += arr[i][j];
            }
            sum += groupSum;
            System.out.println("第" + (i + 1) + "组的销售总额=" + groupSum + "万元");
        }

        System.out.println("总销售额为" + sum + "万元");
    }
}

运行结果如下所示:

第1组的销售总额=23万元 第2组的销售总额=89万元 第3组的销售总额=219万元 总销售额为331万元

在上述代码中,第3行代码定义了一个长度为3的二维数组,并在5~7行代码中为数组的每个元素赋值。 过程中还定义了两个变量sum和groupSum,其中sum用来记录公司的总销售额,groupSum用来记录每个销售小组的销售额。当通过嵌套for循环统计销售额时,外层循环对三个销售小组进行遍历,内层循环对每个小组员工的销售额进行遍历,内层循环每循环一次就相当于将一个小组员工的销售总额统计完毕,赋值给groupSum,然后把groupSum的值与sum的值相加赋值给sum。当外层循环结束时,三个销售小组的销售总额groupSum都累加到sum中,即统计出了整个公司的销售总额。

寄语:

当你的才华还撑不起你的野心的时候,你就应该静下心来学习;当你的能力还驾驭不了你的目标时,就应该沉下心来,历练;梦想,不是浮躁,而是沉淀和积累, 只有拼出来的美丽,没有等出来的辉煌,机会永远是留给最渴望的那个人,学会与内心深处的你对话,问问自己,想要怎样的人生,静心学习,耐心沉淀,送给自己,共勉。

如果,此文章对你有所帮助,请帮忙点个赞呗!爱你,么么哒!!!