⭐前言⭐
本文将介绍一种常见的数据结构–数组
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
🔑GithubJava仓库,欢迎点击访问🔑
📝博主的笔记链接📝
🌲数组基础
数组是什么
数组本质上就是一组相同数据类型的数据结构。
创建数组
Java数组创建和C语言有所不同。
下面以整型数组为例
int[] nums1 = new int[]{1,2,3};//1>>>动态初始化
int[] nums2 = new int[3];//2>>>长度为3,默认初始化为0
int[] arr1 = {1,2,3};//3>>>静态初始化
int[] arr2 = new int[n];//可以要求n不是常量
int[][] nums3 = new int[][]{{1,2,3},{1,2,3}};
int[][] nums4 = new int[2][3];
int[][] arr3 = {{1,2,3},{1,2,3}};
需要注意的是:
- 定义数组的时候不能写具体的数字,如
int[3] num={1,2,3};
- 动态初始化的第二个[]也不能写具体数字,如
int [] num=new int[3]{1,2,3};
直接报错。
数组使用
一般是获取数组长度以及根据下标访问数组
int[] arr={1,2,3,4,5};
int len= arr.length;
for(int i=0;i<len;++i){
System.out.println(arr[i]);
}
需要注意的是
- 在Java中使用.length得到数组的长度
- 下标访问不可越界,范围是[0,arr.length)
有关二维数组长度
int[][] nums={{1,2,3},{2,4,5}};
int m=nums.length;//行
int n=nums[0].length;//列
遍历数组
常见有三种实现方式
- 通过for-i循环实现
- 通过for-each循环实现
- 通过Arrays类中自带的功能实现
显现附上代码
public static void main(String[] args) {
int[] array={1,2,3,4,5,6};
//for-i循环
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");
}
System.out.println();
//for-each循环
for (int x:array) {
System.out.print(x+" ");
}
System.out.println();
//Arrays功能,可以自行查看
System.out.println(Arrays.toString(array));
}
对于二维数组
public static void main(String[] args) {
int[][] nums={{1,2,3},{4,5,6}};
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums[0].length; j++) {
System.out.print(nums[i][j]+" ");
}
System.out.println();
}
System.out.println("--------------------------------");
for (int[] ret: nums) {
for(int x: ret)
System.out.print(x+" ");
System.out.println();
}
System.out.println("--------------------------------");
System.out.println(Arrays.deepToString(nums));
}
区别:for循环可以拿到下标,而后者不能拿到下标,更多用到访问集合中的元素
二维数组的不规则性
🌲数组和方法
数组作为方法的参数
最长的就是写一个函数打印内容
附上一个实现的代码
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6};
printfArr(arr);
}
public static void printfArr(int[] nums){
for (int x: nums) {
System.out.print(x+" ");
}
}
Java中的应用类型
在C语言中有传值掉用还有传值调用
public static void main(String[] args) {
int num=10;
changeNum(num);
System.out.println(num);
}
public static void changeNum(int x){
x=0;
}
在执行完后num的值仍然为10,而不会改变称为0。
public static void main(String[] args) {
int[] arr={0,0,0,0,0,0};
changeArr(arr);
for (int x:
arr) {
System.out.print(x+" ");
}
}
public static void changeArr(int[] arr){
arr[0]=1;
arr[1]=2;
}
通过数组引用却又改变了数值,对应了C语言中的传址调用。
数组作为方法的返回值
public static void main(String[] args) {
String s=getStr();
System.out.println(s);
}
public static String getStr() {
String s="abcdefg";
return s;
}
abcdefg
如果是整型数组,返回类型由String
改变为int[]
如果是浮点型数组,改变为double[]
🌲初识JVM
什么是引用?
引用相当于一个 “别名”, 也可以理解成一个指针。
创建一个引用只是相当于创建了一个很小的变量, 这个变量保存了一个整数, 这个整数表示内存中的一个地址。
JVM被分为5个区
- 程序计数器 (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 开始, 运行时常量池在堆上)。
下面将通过堆栈来简要说明引用
public static void main(String[] args) {
int[] nums1={1,2,3,4};
int[] nums2=nums1;
System.out.println(nums1==nums2);
nums2=new int[]{1,2,3,4};
System.out.println(nums1==nums2);
}
true
false
分析和说明:
最开始nums1指向对象是绿色的数组,nums2指向nums1的对象,也是绿色的数组
它们指向相同的对象所以第一个的true
然后nums2指向另一个对象,虽然他们的内容是相同的,但是地址不同,所以输出false
public static void main(String[] args) {
int[] arr={0,0,0,0,};
System.out.println(Arrays.toString(arr));
changeNums(arr);
System.out.println(Arrays.toString(arr));
changeNums2(arr);
System.out.println(Arrays.toString(arr));
}
public static void changeNums(int[] arr){
arr=new int[]{1,1,1,1,1};
}
public static void changeNums2(int[] arr){
arr[0]=1;
arr=new int[]{1,2,3,4};
}
我们可以看见第一个函数的int[] {1,1,1,1}
对于原来的实参没有任何影响,这是因为它指向了其他的对象,并没有改变arr的指向。
第二个的arr[0]=1
造成影响是因为这时候arr还指向主函数中数组的内容。
按照C语言的指针理解那就是,new一个对象时指针指向了其他内容,当指针还指向内容时就可以改变内容。
🌲Arrays方法
- fill函数(填充函数)
public static void main(String[] args) {
int[] arr1=new int[10];
int[] arr2=new int[10];
Arrays.fill(arr1,1);//将所有元素填充为1
Arrays.fill(arr2,1,3,9);//将下标[1,3)填充为9
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toString(arr2));
}
- sort排序函数
public static void main(String[] args) {
int[] arr={1,2,1,4,3,90,3452,21,23,2,34,6,5,78};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
- copyOf()拷贝函数和clone()克隆
public static void main(String[] args) {
int[] arr1={1,2,3,4,5,6,7};
int[] arr2=Arrays.copyOf(arr1,arr1.length);//拷贝所有
int[] arr3=Arrays.copyOfRange(arr1,1,3);//拷贝下标[1,3)之间的元素
int[] arr4=arr1.clone();//拷贝所有
System.out.println(Arrays.toString(arr2));
System.out.println(Arrays.toString(arr3));
System.out.println(Arrays.toString(arr4));
}
🍕尾语🍕
如有不足之处,欢迎指正。