Java学习苦旅——不一样的数组

Posted rampant boy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习苦旅——不一样的数组相关的知识,希望对你有一定的参考价值。

本篇博客将讲解Java中的数组。

数组的基本用法

什么是数组

数组是一块连续的内存,所存放的是一组相同数据类型的集合。

创建数组

基本语法

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

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

代码示例

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

int[] array2 = new int[10];

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

数组的使用

计算数组长度

直接使用数组名.length即可。例如:

public static void main(String[] args) {
    int[] array = {1,2,3,4,5,6,7};
    System.out.println("数组长度为" + array.length);
}

结果为:

打印数组

for循环打印数组

例如:

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

结果为:

使用for each打印数组

for each也称为增强for循环。使用方法为 for(表达式1 : 表达式2) 。表达式1表示数组的元素类型,表达式2是数组名。

public static void main(String[] args) {
    int[] array = {1,2,3,4,5,6,7};
    for(int x : array) {
        System.out.println(x);
    }
}

结果为:

使用Arrays打印数组

Arrays是帮助我们操作数组的工具类。Arrays.toString是将当前数组转化为字符串的形式进行输出 例如:

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

结果为:

数组在内存中的存储

初始JVM内存区域划分

  • 程序计数器 (PC Register):只是一个很小的空间,保存下一条执行的指令的地址。

  • 虚拟机栈(JVM Stack):重点是存储局部变量表(当然也有其他信息)。我们刚才创建的 int[] arr 这样的存储地址的引用就是在这里保存。

  • 本地方法栈(Native Method Stack):本地方法栈与虚拟机栈的作用类似,只不过保存的内容是Native方法的局部变量。在有些版本的 JVM 实现中(例如HotSpot),本地方法栈和虚拟机栈是一起的。

  • 堆(Heap):JVM所管理的最大内存区域。使用new创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} )

  • 方法区(Method Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法编译出的的字节码就是保存在这个区域。

  • 运行时常量池(Runtime Constant Pool):是方法区的一部分,存放字面量(字符串常量)与符号引用。(注意从JDK1.7开始,运行时常量池在堆上)

局部变量和引用保存在栈上,new出的对象保存在堆上。

堆的空间非常大,栈的空间比较小。

堆是整个 JVM 共享一个,而栈每个线程具有一份(一个 Java 程序中可能存在多个栈)。

理解内存

内存就是指我们熟悉的 “内存”。内存可以直观的理解成一个宿舍楼。有一个长长的大走廊,上面有很多房间。每个房间的大小是1Byte (如果计算机有 8G 内存, 则相当于有 80亿 个这样的房间)。每个房间上面又有一个门牌号,这个门牌号就称为 地址

理解引用

对于数组的存储,我们暂时只考虑两块区域——栈区和堆区

例如:

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

array1和array2就是引用,也称为引用变量。这个变量里面储存的是一个地址(假设这两个数组的地址为0x123和0x456)。

null

int[] array = null;

这行代码代表array这个引用不指向任何一个对象。

数组作为方法的参数

基本用法

例如打印数组:

public static void main(String[] args) {
    int[] array = {1,2,3,4,5,6,7};
    print(array);
}

public static void print(int[] array) {
    for (int i = 0; i < array.length; i++) {
        System.out.println(array[i]);
    }
}

结果为:

传参示意图

数组传参传递的是当前引用的值——地址。

数组作为方法的返回值

例如:

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

//将原数组各个元素都乘以二,然后赋值给一个新数组
public static int[] func(int[] array) {
    int[] ret = new int[array.length];
    for (int i = 0; i < array.length; i++) {
        ret[i] = array[i] * 2;
    }
    return ret;
}

结果为:

因此,数组作为方法的返回值的时候,返回的仍然是地址。

拷贝数组

for循环拷贝数组

例如:

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

结果为:

Arrays.copyOf拷贝数组

Arrays.copyOf传两个参数,第一个是数组名称,第二个是拷贝的长度。 例如:

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

结果为:

Arrays.copyOfRange拷贝数组

Arrays.copyOfRange可以选择拷贝区间,第一个参数是数组名称,第二参数是起始位置,第三个参数是终止位置。范围遵循左闭右开的规则。 例如:

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

System.arraycopy拷贝数组

System.arraycopy使用方法如下:

从src的srcPos开始拷贝,拷贝到dest的destPos位置。拷贝长度是length。

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

结果为:

clone拷贝数组

例如:

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

结果为:

二维数组

基本语法

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

例如:

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

Java中二维数组不可省略行。

代码示例

例如打印数组:

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

结果为:

二维数组的存储

例如:

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

array这个数组,本身长度为2,每个元素又是一个一维数组。

我们可以验证一下:

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

结果为:

二维数组的打印

for循环打印二维数组

例如:

public static void main(String[] args) {
    int[][] array = {{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();
    }
}

结果为:

for each打印二维数组

例如:

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

结果为:

Arrays.deepToString打印二维数组

例如:

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

结果为:

本篇博客到此结束。

上一篇博客:Java学习苦旅(五)——方法?方法!!!

下一篇博客:Java学习苦旅(七)——我有对象啦!!!

以上是关于Java学习苦旅——不一样的数组的主要内容,如果未能解决你的问题,请参考以下文章

java SpringRetry学习的代码片段

[java学习]java容器源码初探

从键盘输入两个长度不一样的数组,然后怎么把他们合并在一个里面,按从小到大的输出?java的,求代码

片段(Java) | 机试题+算法思路+考点+代码解析 2023

为啥此代码片段返回意外结果?

java中求数组最值方法的定义和前面为啥不一样,好心人帮忙看看