1. 数组的基本概念
定义:数组是一块连续的存储空间,存储的是相同类型的元素。
T[] 数组名 = new T[N];
切记:数组不能越界。
1.1 求数组长度
不需要像c中的sizeof()函数,Java中求数组长度直接用:数组名.length
1.2 数组的三种初始化方法
int[] arr1={1,2,3,4};//直接赋值 静态初始化
int[] arr2=new int[]{1,2,3,4};//动态初始化
int[] arr3=new int[10];//只是分配了内存 但是没有进行赋值 只有默认值 且其中的10个都是0
如果只是分配了内存,则其默认存储值如下:
1.3 数组的使用
Java中引用了专门用于数组的打印形式:
找到其中的for each,点击会出现以下形式:
:左边填数组当中数据类型定义的变量,:右边填数组名。
这两种循环本质上没有任何区别。
另外,打印数组的另外一种方法:Arrays
public static void main(String[] args) {
int[] arr = {1, 2, 3};
String ret = Arrays.toString(arr);
System.out.println(ret);
}
2.1. 初始JVM的内存分布
程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址
虚拟机栈(JVM Stack): 与方法调用相关的一些信息,每个方法在执行时,都会先创建一个栈帧,栈帧中包含有:局部变量表、操作数栈、动态链接、返回地址以及其他的一些信息,保存的都是与方法执行时相关的一些信息。比如:局部变量。当方法运行结束后,栈帧就被销毁了,即栈帧中保存的数据也被销毁了。
本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的
堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} ),堆是随着程序开始运行时而创建,随着程序的退出而销毁,堆中的数据只要还有在使用,就不会被销毁。
方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域
现在我们只简单关心堆 和 虚拟机栈这两块空间,后序JVM中还会更详细介绍。
2.2 基本类型变量与引用类型变量的区别
从上图可以看到,引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量便可以去操作对象。有点类似C语言中的指针,但是Java中引用要比指针的操作更简单。
2.3 再谈引用变量
这段代码中的int[ ] arr2=arr1实际上等于把arr1的地址赋给了arr2所以使得一个地址同时指向两个数组,故更改arr2的值也会影响arr1的值,类似于c语言中的数组。
另外,Java中的数组是存放在堆上的,而变量赋值和方法创建都是在栈上进行的。
Java中的数组属于引用类型,主要是因为数组都是存放在堆上的,而栈中只是存放了数组的地址,属于引用了堆上的数组,所以叫引用类型。
另外,数组是引用类型无法用整形类型赋值,要想赋值需要用NULL进行赋值,代表这个引用不指向任何内容。
fuc1相当于新建了一个数组并且修改了形参自己的指向,而fuc2相当于修改了指向的数组中存放的内容。
注意:
整体初始化只有一次机会,就是在定义的同时初始化。
结构体、数组都是聚合类型,凡是聚合类型都是整体初始化机会只有一次。
2.4 数组的拷贝
方法一:
直接使用Arrays.copyOf进行拷贝
另外,扩容拷贝数组只需要在长度上乘个二。
方法二:
利用System.arraycopy可以指定完成目标到目标的拷贝
按住ctrl+鼠标左键点开System.arraycopy方法,即可查看一下变量
根据目录填入数据,即可完成拷贝。
另外,它也支持局部拷贝。
方法三:
利用Arrays.copyOfRange拷贝数组中的局部内容。
注意:Java中的范围都是[3,5)左闭右开的。
方法四:
直接使用clone()方法进行克隆。
alt+7打开代码索引。
3 例题
1. 模拟实现Arrays.toString()函数
注意:1.要考虑null的情况。
2.注意‘ [ ’ , ' ] ' , ' , '
public static String My_toString(int[] tmp) {
if (tmp == null) {
return "null";
}
String ret = "[";
for (int i = 0; i < tmp.length; i++) {
ret += tmp[i];
if (i != tmp.length - 1) {
ret += ",";
}
}
ret += "]";
return ret;
}
public static void main(String[] args) {
Arrays.toString()
int[] arr = {1, 2, 3, 4};
System.out.println(My_toString(arr));
}
2. 求数组中元素的平均值
public static double avg(int[] arr){
int sum=0;
for (int x:
arr) {
sum+=x;
}
return sum*1.0/arr.length;
}
public static void main(String[] args) {
int[] arr={1,2,3,2,3,5,8,3};
System.out.println(avg(arr));
}
3. 查找数组中指定元素(顺序查找)
方法一:直接查找
public static int fuc(int[] arr,int num){
for (int i = 0; i < arr.length; i++) {
if(arr[i]==num){
return i;
}
}
return -1;
}
public static void main(String[] args) {
int[] arr={1,2,8,55,66,45,25};
Scanner scanner=new Scanner(System.in);
int num=scanner.nextInt();
System.out.println(fuc(arr, num));
}
方法二:二分查找
知识点补充:数组从小到大快速排序方法:Arrays.sort()。
注意:不是冒泡排序,底层是快排。
所以二分查找就完成了:
public static int sort(int arr[],int num){
int left=0;
int right=arr.length-1;
for (int i = 0; i < arr.length; i++) {
int mid=(left+right)/2;
if(arr[mid]num){
right=mid-1;
}
else{
return mid;
}
}
return -1;
}
public static void main(String[] args){
int[] arr={2,5,6,4,33,64,85,25};
Scanner scanner=new Scanner(System.in);
int num=scanner.nextInt();
System.out.println(sort(arr, num));
}
方法三:二分查找(系统板)方便
public static void main(String[] args) {
int[] arr={2,5,6,4,33,64,85,25};
System.out.println(Arrays.binarySearch(arr, 33));
}
4. 额外补充:
1. 倒叙排序数组
public static void sort(int[] arr){
int left=0;
int right=arr.length-1;
while(left
2. 数组比较使用Arrays.equals()方法
3. 快速初始化数组:利用Arrays.fill()方法
部分初始化数组:利用Arrays.fill()方法
5. 二维数组
5.1 二维数组的初始化
二维数组的三种初始化方式:
public static void main(String[] args) {
int[][] arr1=new int[3][5];
int[][] arr2=new int[][]{{1,2,3},{3,6,5}};
int[][] arr3={{2,5,6},{8,5,6}};
}
5.2 二维数组的打印
方法一:如果把二位数组当成其列数个一维数组,则i的范围将是i
而j的范围将是j
public static void main(String[] args) {
int[][] arr = {{4, 5, 6}, {1, 2, 3}};
paint(arr);
}
public static void paint(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
方法二:因为二维数组的每个元素都是一维数组,所以可以这样打印。
public static void main(String[] args) {
int[][] arr=new int[2][3];
System.out.println(arr[0]);
System.out.println(Arrays.toString(arr[0]));
System.out.println(arr[1]);
System.out.println(Arrays.toString(arr[1]));
}
方法三:利用Arrays.deepToString进行打印
注意:这种打印方法无法换行。
5.3 不规则数组
不规则数组就是只规定行,不规定列的数组。
其输出结果为null
不规则数组的优点是:可以自定义二维数组中一维数组的大小。
其原理是如下图: