【Java编程进阶】花费数小时,带你学透Java数组,这些常用方法你还记得吗?

简介: 数组在 Java 编程中是一个非常基础且重要的概念,简单来说,就是把具有相同数据类型的数据存储在地址连续的内存空间中,目的是在程序设计中方便这一类数据的管理。每一个内容都有编号,这个编号从 0 开始,称为数组下标。数组分为一维数组和二维数组,还有一些和数组相关的重要内容,例如数组中元素的查找,排序等,下面做详细的讲解。

在这里插入图片描述

个人主页:橙子

推荐学习专栏:Java 编程进阶之路【从入门到精通】


1. 数组

数组在 Java 编程中是一个非常基础且重要的概念,简单来说,就是把具有相同数据类型的数据存储在地址连续的内存空间中,目的是在程序设计中方便这一类数据的管理。每一个内容都有编号,这个编号从 0 开始,称为数组下标。

数组分为一维数组和二维数组,还有一些和数组相关的重要内容,例如数组中元素的查找,排序等,下面做详细的讲解。

2. 一维数组

2.1 声明

语法:

元素类型[] 变量名称 示例:int[] intArray; 
元素类型 变量名称[] 示例:int intArray[]; 

上面两种声明方法效果相同,还可以在一行声明多个数组:

int[] array1,array2,array3;

2.2 初始化

数组的初始化过程就是给数据分配内存空间的过程,一维数组有两种初始化方法,分别是静态初始化和动态初始化。

静态初始化:声明数组时,对数组初始化,此时知道数组的内容,数组的大小会根据初始值的个数确定长度。

int[] arr = { 1,2,3,4 }; //省略情况
int[] arr = new int[] { 1,2,3,4 };//可以省略new int[]

动态初始化:此时不知道数组的内容,声明时需要指定数组的长度。

int[] arr = new int[10]; //定义10个int类型的数组

同样,我们可以使用如下的方法创建数组:

int[] array1;
array1 = new int[10];
int[] array2;
array2 = new int[]{10, 20, 30};
// 注意省略格式不可以拆分, 否则编译失败
// int[] array3;
// array3 = {1, 2, 3};

2.3 使用

数组的长度属性:在 Java 中,万物皆对象,比如这里的数组,所以我们可以直接获取数组的长度的属性。

示例:

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

数组元素的访问:数组中每个数据都有自己的编号,称为数组下标,数组下标从0开始,我们可以通过数组下标访问数组元素。

示例:

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

同时,我们可以使用数组下标修改数组内容:

arr[0]=0;

数组的遍历:在 Java中有两种方式遍历数组,分别是 for 循环和增强 for 循环。

//for循环遍历数组
int[]array = new int[]{10, 20, 30, 40, 50};
for(int i = 0; i < array.length; i++){
    System.out.println(array[i]);
}
//foreach增强循环遍历数组
int[] array = {1, 2, 3};
for (int x : array) {
System.out.println(x);
}
/**
*int x :array表示的是数组中的数据类型+变量名 : 数组名
*/

3. 二维数组

二维数组本质上是以数组作为数组元素的数组,即“数组的数组”。

3.1 声明

语法格式:

类型说明符 数组名[常量表达式][常量表达式]

示例:

int tempArray[][]=new int[][3]; //错误 
int tempArray[][]=new int[3][]; //正确 
int tempArray[][]=new int[3][4]; //正确

3.2 初始化

静态初始化:

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

动态初始化:

public static void main(String[] args) 
{ 
  int[][] Arr=new int[10][10]; 
  for(int i=0;i<10;i++){ 
     for(int j=0;j<10;j++){ 
         myArr[i][j] = (i+1)*j; 
      } 
  } 
}

3.3 使用

二维数组的遍历:这里和一维数组一样,也可以使用 for 循环和 foreach 循环来遍历。

示例:

int[][] arr1 = { {1,2,3},{4,5,6} };
//for
for (int i = 0; i < arr1.length; i++) {
    for (int j = 0; j < arr1[i].length; j++) {
 
         System.out.print(arr1[i][j] + " ");
     }
     System.out.println();
}
    //foreach
    for (int[] x : arr1) {
        for (int y : x) {
            System.out.print(y + " ");
        }
        System.out.println();
    }

4. 数组在内存中的分布

在学习 Java 数组时,我们一定要弄明白其在内存中的分布情况,这对于我们理解数组和使用数组都是十分重要的。为什么我们要说二位数组其实也可以理解为一维数组?

在我们弄清楚了数组在内存中的分布以后,这个问题就不难理解了。

要弄清楚数组在内存中的分布,首先要明白 JVM 内存分布情况。为了方便管理内存,JVM对内存进行了划分,Java 作为一门面向对象语言,实际上JVM 内存是以类和对象的分布划分的。

在这里插入图片描述

上图大致的表示了Java虚拟机运行时的数据区,Java经过编译后产生的.class文件被加载到 JVM 虚拟机里面的本地方法栈里面运行,Java虚拟机栈通常存放局部变量等,堆区是 Java 中最大的一块内存,用来存放对象,且不用手动释放内存,后面我们会学到Java垃圾处理机制,他会自动释放这一部分的内存,方法区用来存放常量,静态变量等。

这里我们主要看堆区和 Java 虚拟机栈。数组作为引用数据类型,在创建时,其实是创建了一个对象的引用,这个引用用来存放数组对象的首地址,例如:

int[] array = new int[]{1, 2, 3, 4};//静态初始化

此时,Java虚拟机栈上会开辟一块内存空间,存放引用数据类型的变量 array ,并且在堆区中开辟了内存空间存放 new 出来的对象,array 指向堆区中的这个对象,即存储对象的地址。如图:

在这里插入图片描述

此时,对于二维数组来说也不难理解,在 Java 虚拟机栈上的引用类型的变量指向了堆区的对象,其实在 Java 中当栈中的变量不在指向该对象时,说明该对象已经不在需要,此时堆区的对应内存就会被释放,无需手动释放。

在这里插入图片描述

5. 数组常用的方法

Java 中的 Arrays 工具类包括了数组常用的一些方法,比如数组的查找,排序,数组的拷贝等方法,而这些方法,是数组中非常基础且重要的部分,同样在我们的程序中也经常使用到。当然在使用之前需要导入:

import java.util.Arrays;

5.1 Arrays.toString方法

作用:将一维数组转化为字符串。如果你要将二维数组转化为字符串,请使用 Arrarys.deepToString

示例:

import java.util.Arrays;

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

5.2 Arrays.copyOf方法

作用:从下标0开始复制数组中的内容到一个新的数组。

示例:

import java.util.Arrays;

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

5.3 Arrays.copyOfRange方法

作用:和上一个方法相似,这个方法的作用是指定了复制的范围,并且这个方位是左闭右开的范围。

示例:

import java.util.Arrays;

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

5.4 Arrays.sort方法

作用:对数组中的元素升序排列。

示例:

import java.util.Arrays;

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

5.5 Arrays.fill方法

作用:把数组内容全部填充为一个值。如果你想填充数组中指定位置的值,请使用重载的方法:

public static void fill(int[] a, int fromIndex, int toIndex, int val)

其中四个参数的含义分别是:要填充的数组,要填充的数组的第一个元素的索引(包括该元素),要填充数组的最后一个元素的索引(不包括该元素),要填充在数组中的值。

示例:

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] array = new int[10];
        Arrays.fill(array,10);
        Arrays.fill(array,2,8,20);
        System.out.println(Arrays.toString(array));
    }
}

5.6 Arrays.equals方法

作用:判断连个数组的内容是否相等,调用时需要传入两个需要比较的数组作为参数。

示例:

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] arr1 = new int[] { 4,3,2,1 };
        int[] arr2 = new int[] { 1,2,3,4 };
        int[] arr3 = new int[] { 1,2,3,4 };
        System.out.println(Arrays.equals(arr1, arr2));//false
        System.out.println(Arrays.equals(arr2, arr3));//true
    }
}

5.7 Arrays.binarySearch方法

作用:利用二分查找查找数组中的元素,数组中的元素需要升序排列。

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] arr1 = new int[] { 1,2,3,4};

        System.out.println(Arrays.binarySearch(arr1, 2));//下标是1
    }
}

6. 总结

理解数组的思想,熟练使用数组的常用方法和明确 Java 数组在内存中的分布情况是 Java 基础篇中十分重要的一部分。


Java编程基础教程系列

【Java编程进阶】Java数据类型详解

【Java编程进阶】流程控制结构详解

【Java编程进阶】方法初识

在这里插入图片描述

欢迎订阅学习Java编程进阶之路专栏专栏文章持续更新!

目录
相关文章
|
1月前
|
Java 程序员
Java编程中的异常处理:从基础到高级
在Java的世界中,异常处理是代码健壮性的守护神。本文将带你从异常的基本概念出发,逐步深入到高级用法,探索如何优雅地处理程序中的错误和异常情况。通过实际案例,我们将一起学习如何编写更可靠、更易于维护的Java代码。准备好了吗?让我们一起踏上这段旅程,解锁Java异常处理的秘密!
|
11天前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
Java 并发编程——volatile 关键字解析
|
15天前
|
算法 Java 调度
java并发编程中Monitor里的waitSet和EntryList都是做什么的
在Java并发编程中,Monitor内部包含两个重要队列:等待集(Wait Set)和入口列表(Entry List)。Wait Set用于线程的条件等待和协作,线程调用`wait()`后进入此集合,通过`notify()`或`notifyAll()`唤醒。Entry List则管理锁的竞争,未能获取锁的线程在此排队,等待锁释放后重新竞争。理解两者区别有助于设计高效的多线程程序。 - **Wait Set**:线程调用`wait()`后进入,等待条件满足被唤醒,需重新竞争锁。 - **Entry List**:多个线程竞争锁时,未获锁的线程在此排队,等待锁释放后获取锁继续执行。
49 12
|
11天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
93 2
|
2月前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
2月前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
28天前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
28天前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
50 3
|
1月前
|
开发框架 安全 Java
Java 反射机制:动态编程的强大利器
Java反射机制允许程序在运行时检查类、接口、字段和方法的信息,并能操作对象。它提供了一种动态编程的方式,使得代码更加灵活,能够适应未知的或变化的需求,是开发框架和库的重要工具。
47 3
|
2月前
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
69 1