零基础 “入坑” Java--- 七、数组(二)

发布于:2025-07-06 ⋅ 阅读:(20) ⋅ 点赞:(0)


在上一章节中,我们已经对数组的知识进行了初步的学习;在本章节中,我们将通过对数组的练习进一步学习有关数组更多的知识。

一、数组转字符串

我们可以使用for循环来遍历数组:

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }

Java给我们提供了一个更快速的解决办法,借助工具类就可以完成:

import java.util.Arrays;

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        System.out.println(Arrays.toString(array)); //[1, 2, 3, 4, 5]
    }

当我们输入"Arrays"时,编译器会自动帮我们在首行导入"import java.util.Arrays;"语句,即导入所需的包。我们可以使用"Arrays.toString()"将数组内容转换为字符串进行输出(输出结果为字符串)。

接下来,我们尝试自己编写一个toString方法,使输出的结果 与Java提供的方法 输出的结果相同:

    public static String myToString(int[] array) {
        String ret = "[";
        for (int i = 0; i < array.length; i++) {
            ret += array[i];
            //最后一位数字结尾不需要逗号
            if(i != array.length - 1) {
                ret += ", ";
            }
        }
        ret += "]";
        return ret;
    }
    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        System.out.println(myToString(array)); //[1, 2, 3, 4, 5]
    }

二、数组的拷贝

当我们想将一个数组中的内容,拷贝到另一个数组中时,可以使用for循环对数组中的元素逐个操作:

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        int[] copy = new int[array.length]; //空数组
        System.out.println(Arrays.toString(copy)); //[0, 0, 0, 0, 0]
        for (int i = 0; i < array.length; i++) {
            copy[i] = array[i];
        }
        System.out.println(Arrays.toString(copy)); //[1, 2, 3, 4, 5]
    }

对于拷贝的结果,应该存在两组一样的值,我们再来分析一段代码,判断它是不是拷贝:

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        int[] array2 = array;
        System.out.println(Arrays.toString(array2)); //[1, 2, 3, 4, 5]
    }

虽然打印结果与 array 相同,但这并不是拷贝,只不过是让 array2 也指向了 array 的地址,访问的是同一个对象,在内存上是同一块空间。

对于数组的拷贝,Java也贴心的提供了更便捷的解决办法:

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        int[] copy = Arrays.copyOf(array, array.length);
        System.out.println(Arrays.toString(copy)); //[1, 2, 3, 4, 5]
    }

copyOf有两个参数,第一个参数是 想拷贝哪个数组,第二个参数是拷贝的长度。

基于上面的代码,我们对其进行扩容操作:

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        int[] copy = Arrays.copyOf(array, array.length * 2);
        System.out.println(Arrays.toString(copy)); //[1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
    }

我们对 copyOf 的第二个参数进行修改,即可完成扩容的操作。


当我们想获取数组中的部分元素时,Java也给我们提供了一种解决办法:

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5,0,0,0,0,0};
        System.out.println(Arrays.toString(array)); //[1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
        int[] copy = Arrays.copyOfRange(array, 1, 5);
        System.out.println(Arrays.toString(copy)); //[2, 3, 4, 5]
    }

copyOfRange 有三个参数,第一个参数为想拷贝哪个数组,第二个参数为拷贝的起始位置,第三个参数为拷贝的结束位置。对于拷贝的范围,采取的是左闭右开区间,即可以获取到起始位置的值,但获取不到结束位置的值。

copyOfRange 的第三个参数超过了数组的最后一个元素也没关系,会根据当前数组的默认值数据类型自动填充:

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5,0,0,0,0,0};
        System.out.println(Arrays.toString(array)); //[1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
        int[] copy = Arrays.copyOfRange(array, 0, 15);
        System.out.println(Arrays.toString(copy)); //[1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    }

拷贝数组还有一种方式:

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        int[] copy = new int[array.length];
        System.arraycopy(array, 1, copy, 2, 2);
        System.out.println(Arrays.toString(copy)); //[0, 0, 2, 3, 0]
    }

System.arraycopy 有五个参数,第一个参数是想拷贝哪个数组(假设数组名为array),第二个参数为从 array 哪个位置开始拷贝,第三个参数为目的数组,第四个参数为目的数组的哪个位置,第五个参数为拷贝的长度。

在使用时,需确保拷贝的长度范围可以在 array 中获取到,否则程序会抛出异常:

    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        int[] copy = new int[array.length];
        //错误示范:从 array 的1位置开始,获取不到 array.length(5)个元素!!!
        System.arraycopy(array, 1, copy, 2, array.length);
        System.out.println(Arrays.toString(copy));
    }

运行结果为:
在这里插入图片描述

三、求数组中元素的平均值

    public static double average(int[] array) {
        int sum = 0;
        for (int x:array) {
            sum += x;
        }
        return (double) sum / (double) array.length;
    }
    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        System.out.println(average(array)); //3.0
    }

四、查找数组中指定元素(顺序查找)

要求:有一个已知数组,给出一个元素,查找该元素在数组中的位置:

    public static int find(int[] array, int x) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == x) {
                return i;
            }
        }
        return -1; //没找到
    }
    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        System.out.println(find(array, 3)); //2
    }

五、数组排序(冒泡排序)

要求:已知一个数组,让数组变得有序(升序或降序):

我们以升序为例:思路为:将数组中相邻元素从前到后进行两两比较,如果前一个元素比后一个元素大,则交换,一趟完成后,最大的元素就在数组的末尾;重复该过程,直至数组完全有序。
举个例子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

    public static void bubbleSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            boolean flg = true;
            //优化1:一趟走完,最后一个元素一定有序。(- i)
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    int tmp = array[j + 1];
                    array[j + 1] = array[j];
                    array[j] = tmp;
                    flg = false;
                }
            }
            //优化2:某趟走完已经有序了
            if(flg == true) {
                break;
            }
        }
    }
    public static void main(String[] args) {
        int[] array = new int[]{8,6,9,5,4};
        bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }

Java为我们提供了便捷的解决办法:

    public static void main(String[] args) {
        int[] array = new int[]{1,8,2,3,6,4,7,5};
        Arrays.sort(array);
        System.out.println(Arrays.toString(array)); //[1, 2, 3, 4, 5, 6, 7, 8]
    }

六、查找数组中指定元素(二分查找)

针对有序数组,可以使用更高效的二分查找来解决这个问题。

我们先来学习二分查找的思想:

我们以升序数组为例,二分查找即先获取中间位置的元素n,再使用待查找元素与n进行比较
1.如果相等,即找到了,返回该元素在数组中的下标;
2.如果小于,则丢弃n右侧元素,以二分查找思想在n左侧重复操作。
3.如果大于,则丢弃n左侧元素,以二分查找思想在n右侧重复操作。

我们以图画形式举例:
在这里插入图片描述
由此,我们根据图中思想编写代码:

    public static int binarySearch(int[] array, int x) {
        int left = 0;
        int right = array.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (x < array[mid]) {
                //左侧寻找
                right = mid - 1;
            } else if (x > array[mid]) {
                //右侧寻找
                left = mid + 1;
            }else {
                //找到了
                return mid;
            }
        }
        return -1; //没找到
    }
    public static void main(String[] args) {
        int[] array = new int[]{9,1,8,2,10,3,6,4,7,5};
        Arrays.sort(array); //变有序
        System.out.println(Arrays.toString(array));
        System.out.println(binarySearch(array, 9)); //8
    }

当然,Java也给我们提供了二分查找的解决办法:

    public static void main(String[] args) {
        int[] array = new int[]{9,1,8,2,10,3,6,4,7,5};
        Arrays.sort(array);
        System.out.println(Arrays.binarySearch(array, 9)); //8
    }

七、判断两个数组中的元素是否相等

    public static void main(String[] args) {
        int[] array1 = new int[]{1,2,3,4,5,6};
        int[] array2 = new int[]{1,2,3,4,5,6};
        
        boolean ret = Arrays.equals(array1,array2);
        System.out.println(ret); //true
    }

八、填充数据

    public static void main(String[] args) {
        //数组中元素均为0
        int[] array = new int[10];
        //将数组中元素均填充为6
        Arrays.fill(array, 6);
        System.out.println(Arrays.toString(array));
    }

当然,我们也可以指定填充的范围:

    public static void main(String[] args) {
        //数组中元素均为0
        int[] array = new int[10];
        //将数组中元素下标为0~4填充为6
        Arrays.fill(array, 0, 5, 6);
        System.out.println(Arrays.toString(array));
    }

在这里需要注意,对于填充的范围为左闭右开区间。

九、数组逆序

要求:给定一个数组,将里面的元素逆序排列。

解题思路为:设定两个下标,分别指向第一个元素和最后一个元素,将两个值交换;让指向第一个元素的下标自增,指向最后一个元素的下标自减,循环即可。

    public static void nix(int[] array) {
        int left = 0;
        int right = array.length - 1;
        while (left < right) {
            int tmp = array[left];
            array[left] = array[right];
            array[right] = tmp;
            left++;
            right--;
        }
    }
    public static void main(String[] args) {
        int[] array = new int[]{1,2,3,4,5};
        nix(array);
        System.out.println(Arrays.toString(array));
    }

十、二维数组

二维数组的每一个元素都是一个一维数组。

语法格式:

数据类型[][] 数组名称 = new 数据类型[行数][列数]{初始化数据};

体现到代码上有三种写法:

int[][] array1 = new int[][]{{1,2,3},{4,5,6}};
int[][] array2 = {{1,2,3},{4,5,6}};
int[][] array3 = new int[2][3]; //数组中元素为0

在这里插入图片描述
当我们想要逐个访问数组中的元素时,可以使用双层for循环来完成:

    public static void main(String[] args) {
        int[][] array1 = new int[][]{{1,2,3},{4,5,6}};
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(array1[i][j] + " ");
            }
            System.out.println();
        }
    }

二维数组是一个特殊的一维数组
在这里插入图片描述
二维数组元素中存放的为一维数组的地址,当访问二维数组中的元素时,会根据元素中存放的地址找到一维数组。

当数据较多时,我们依旧可以使用length来获取数组长度;但需要注意在第二层循环时,数组的长度应为 二维数组元素中 存放的地址 指向的 当前一维数组的长度

    public static void main(String[] args) {
        int[][] array1 = new int[][]{{1,2,3},{4,5,6}};
        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                System.out.print(array1[i][j] + " ");
            }
            System.out.println();
        }
    }

对于二维数组,Java也提供了更便捷的方法可以达到同上的效果:

    public static void main(String[] args) {
        int[][] array1 = new int[][]{{1,2,3},{4,5,6}};
        System.out.println(Arrays.deepToString(array1));
        //[[1, 2, 3], [4, 5, 6]]
    }

在Java中的二维数组可以是不规则的:

//可以省略列数不写
int[][] array1 = new int[2][];
array1[0] = new int[]{1,2,3};
array1[1] = new int[]{4,5,6,7,8,9};

当省略列数,且没有赋值的时候,二维数组中的元素存储的默认值为null,在操作时要注意可能会出现空指针异常的情况,如:

    public static void main(String[] args) {
        int[][] array1 = new int[2][];
        System.out.println(array1[0].length);
    }

运行结果为:
在这里插入图片描述


Ending。