0


【JavaSE】数组超详讲解【一次性 弄懂 数组问题】

希望通过博客和大家相互交流,相互学习,如有错误,请评论区指正

数组是一组相同类型数据元素的集合,这些数据在内存中连续存放(含义和C语言相同,这里就不再啰嗦)

一、定义数组

1. 静态初始化

数据类型[] 数组名称 = { 初始化数据 };
int[] arr = {1, 2, 3, 4, 5};
int[][] array = {{1,2,3},{4,5,6}};

定义一个数组,里面5个元素,每个元素类型都是int

2. 动态初始化

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

eg1.

int[] arr2 = new int[]{1, 2, 3, 4, 5};
int[][] array2 = new int[][]{{1,2,3},{4,5,6}};

eg2.

int[] arr3 = new int[5];
int[][] array3 = new int[2][3];

动态初始化中通过 new 来实例化一个数组对象,里面一共有5个元素,每个元素类型都是int

前面的arr, arr2, arr3都是数组的名字,也就是变量名,等号右边的是数组对象

eg2中创建数组的时候并没有赋初值,那么它里面就是0(注意和C语言区分)

3. 二维数组的不规则定义

int[][] array3 = new int[2][];

这里要和C语言区分,C语言中可以将数组的行省略,但是列不能省略

Java当中,数组行必须要有,列可以不写,但是列不能自动推导出来

这种定义就是说该数组有两行,有几列是不确定的,并且Java中的每行的列数是可以不同的,如下代码:

int[][] array3 = new int[2][];
array3[0] = new int[2];
array3[1] = new int[3];

Java中的数组是在内存的什么地方呢?

这个问题我们应该严谨的来回答,数组对象在 堆 上,但是数组变量arr,arr2,arr3在栈上,这看起来很别扭,但事实就是这样

8大基本类型,里面直接存放的就是我们要存的数据,在栈上,但arr属于引用类型,里面存放的是它所指向的对象的地址

我们通过以下图来说明

eg. int[] arr = new int[]{1, 2, 3, 4, 5};

我们可以来验证一下

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

运行结果:

注意

这并不是堆中真正的地址,而是经过Java处理的

二、数组的长度与打印数组

Java是一门面向对象的语言,我们关注对象本身,在Java中数组的一个属性就是length,我们可以直接拿来用,如下代码:

public static void main(String[] args) {
    int[] arr = new int[]{1, 2, 3, 4, 5};
    int len = arr.length;
    System.out.println(len);
}

打印数组

方式1:

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

运行结果:

打印二维数组:

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

二维数组的内存布局和C语言还是有很大区别的,如下图所示:

方式2:

for (int e : arr) {
    System.out.print(e + " ");
}

方式2中for循环中有一个 : 后面是要打印的数组,前面是将要打印的数组的元素类型

二维数组:

public static void main(String[] args) {
    int[][] array = new int[][]{{1,2,3},{4,5,6}};
    for (int[] cur : array) {
        for (int val : cur) {
            System.out.print(val + " ");
        }
        System.out.println();
    }
}

方式3:

也可以将数组转化为字符串然后打印输出

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

二维数组:

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

三、数组作为方法的参数

传参

当我们用数组来传参的时候应该,应该要拿什么来接收呢?

数组变量其实就是个引用,我们传过去,直接拿数组变量来接收即可(避免了传整个数组过去,开销过大)

如下代码:

public static void print(int[] array) {
    for (int i : array) {
        System.out.print(i + " ");
    }
}
public static void main(String[] args) {
    int[] arr = new int[]{1, 2, 3, 4, 5};
    print(arr);
}

图示:

两个引用指向同一块内存

什么是引用 ?

引用其实就相当于C语言当中的指针,用来指向一块内存,我们通过引用可以找到这块内存或这个对象,并通过引用来对这个对象进行一些列操作

表情包:对象 的图像结果

如下图:

Java 将数组设定成引用类型, 这样的话后续进行数组参数传参, 其实只是将数组的地址传入到函数形参中,这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大)

null

C语言当中的指针当我们创建之后不想让它指向任何变量时,就会让它指向NULL,代表0x00000000地址处

那么在Java当中也有这种情况,我们让引用指向 null,但是这里的null并不是0x00000000地址处,而是空对象,让这个引用指向一个空对象

表情包:空对象 的图像结果

int[] arr = null;

相当于一个无效的引用

当我们对这个引用进行操作的时候就会出空指针异常(NullPointerException)

public static void main(String[] args) {
    int[] arr = null;
    System.out.println(arr[0]);
}

四、操作数组的工具类(java.util.Arrays)

Java提供的操作数组的方法很多,在写代码时很方便

表情包:功能强大 的图像结果

用的时候要导入java.util.Arrays这个包

1. Arrays.toString();

将数组当中的数据转换为字符串

在 IDEA 中可以看到Java对toString方法做了重载,可以使得它可以针对不同类型的数组进行操作

函数原型

static String toString(int[] a)

Returns a string representation of the contents of the specified array

代码示例

import java.util.Arrays;
public class Demo2 {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        String str = Arrays.toString(arr);
        System.out.println(str);
    }
}

在这段代码中通过Arrays.toString();将arr数组中的数据转换成了字符串(非常方便)

运行结果:

** 模拟实现**:

public static String toString(int[] arr) {
    String str = "[";
    for (int i = 0; i < arr.length - 1; i++) {
        str = str + arr[i] + ",";
    }
    if (arr.length != 0) {
        str = str + arr[arr.length - 1];   // 对最后一个元素做特殊处理
    }
    str = str + "]";
    return str;
}

其他类型的数组做重载处理就行

2. Arrays.copyOf();

也可以用System.arraycopy();

拷贝数组

这个方法并不是简单的进行了 arr = arr2这样的操作,而是创建一个新的对象,将原对象中的值拷贝到新对象中,这样的话修改原数组自然是不会影响新数组的值

**函数原型 **

static int[] copyOf(int[] original, int newLength)

Copies the specified array, truncating or padding with zeros (if necessary) so the copy has the specified length.

代码示例:

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

通过调用Arrays.copyOf();完成数组的深度拷贝

这个方法的第二个参数也可以比原数组长度大或小

若传入的newLength > arr.length则剩余部分全部用0来填充

若newLength < arr.length,则从头拷贝到指定长度

eg.

public static void main(String[] args) {
    int[] arr = {1,2,3,4,5};
    int[] arr2 = Arrays.copyOf(arr, 8);
    System.out.println(Arrays.toString(arr2));
    int[] arr3 = Arrays.copyOf(arr, 3);
    System.out.println(Arrays.toString(arr3));
}

** 模拟实现**

public static int[] copyOf(int[] arr, int newLength) {
    int[] array = new int[newLength];
    int minLength = arr.length < newLength ? arr.length : newLength;
    for (int i = 0; i < minLength; i++) {
        array[i] = arr[i];
    }
    return array;
}

注意:数组下标不能越界,将3种情况要全部考虑进去

3. Arrays.copyOfRange();

拷贝数组的某个范围

函数原型

static int[] copyOfRange(int[] original, int from, int to)

Copies the specified range of the specified array into a new array

代码示例

public static void main(String[] args) {
    int[] arr = {1,2,3,4,5};
    int[] arr2 = Arrays.copyOfRange(arr, 0, 5);
    System.out.println(Arrays.toString(arr2));
    int[] arr3 = Arrays.copyOfRange(arr, 2, 8);
    System.out.println(Arrays.toString(arr3));
    int[] arr4 = Arrays.copyOfRange(arr, 0, 0);
    System.out.println(Arrays.toString(arr4));
}

运行结果:

注意:Java中的范围基本上都是左闭右开区间

模拟实现

public static int[] copyOfRange(int[] arr, int fromIndex, int toIndex) {
    int[] newArray = new int[toIndex - fromIndex];
    int toIndexMin = arr.length < toIndex ? arr.length : toIndex;
    for (int i = fromIndex; i < toIndexMin; i++) {
        newArray[i - fromIndex] = arr[i];
    }
    return newArray;
}

4. Arrays.clone();

产生了这个对象的一个副本(Object 的克隆方法)

这是一个浅拷贝

欢迎大家关注!!!

一起学习交流 !!!

让我们将编程进行到底!!!

--------------整理不易,请三连支持------------------


本文转载自: https://blog.csdn.net/weixin_46531416/article/details/122261697
版权归原作者 来自爪哇的bean 所有, 如有侵权,请联系我们删除。

“【JavaSE】数组超详讲解【一次性 弄懂 数组问题】”的评论:

还没有评论