希望通过博客和大家相互交流,相互学习,如有错误,请评论区指正
数组是一组相同类型数据元素的集合,这些数据在内存中连续存放(含义和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 的克隆方法)
这是一个浅拷贝
欢迎大家关注!!!
一起学习交流 !!!
让我们将编程进行到底!!!
--------------整理不易,请三连支持------------------