本篇博客适合有C语言基础的同学们观看
数组的定义
int[] arr={1,2,3,4,5};
int[] arr2=new int[]{1,2,3,4,5};
以上两种定义方法是没有区别的,只是写法不同而已
但是请注意
以上是第三种定义数组的方式,但是如上图这种定义数组的方式与前两种不一样的是:没有初始化,然而当我们给他赋值的时候只能一个一个赋值.
与C语言不同的是:没有给数组初始化时,数组里面元素的值默认为0,boolean类型的值默认为false,如果数组中存放的是引用类型,则默认为:NULL
但是请注意:在所有的定义我的数组当中,[]中都不能出现数字.
int[] arr
类型 名字
所以不要在里面加入其他的东西,这一点与C语言不同
好的,我们接下来分析一下数组越界时会发生什么
会报错!!!(狗头:当然会报错啦)
此时你要注意了,与C语言不同的是,Java非常严谨,倘若数组越界,则会直接报错.
数组中元素的访问
在Java当中,数组中元素的访问方式和C语言一样都是要通过下标来访问的,存储方式也是连续存储的因此也会支持随机访问
下面我们利用这种性质来打印一个数组
在Java中可以通过:数组名.length来直接求得数组的长度
Foreach
如果你认为这样写还是太麻烦了,可以我们直接用foreach(增强for循环)
这个for循环的意思是:将数组中的每一个元素依次拿出来放到x中.
这里的foreach连长度都不需要知道
运行流程图如下
那么for循环和foreach的区别在哪里?
注意:for循环可以通过循环变量来拿到数组的下标,而foreach则拿不到下标.
那么有没有第三种打印的方法呢?
有的!
Arrays.toString
恐怖如斯
Arrays.toString是一个Java已经帮你写好的一个方法
其实就相当于我们C语言中的库函数,是Java或者别人已经帮你写好的,你拿去用就可以了,当然了,使用的时候需要包含java.util.Arrays的头文件.
但是请注意,Aeeays.toString是将数组中的数据以字符串的形式输出的
运行结果
这也就很好的解释了,为什么用此方法打印出来的值带有[]和,.
好的,那我们思考几个很重要的问题
这个数组的内存在哪里?在Java中内存是怎么划分的?划分了那些内存?.
在Java中内存主要划分为:方法区、虚拟机栈、本地方法栈、堆、程序计数器
那么有没有发现一个问题:为什么会有两个栈呢?
JVM其实是拿C/C++写的软件,在本地方法栈中执行的是C/C++的底层代码.
引用类型
我们不妨猜一下下面这段代码会出现什么样的结果
但是请注意,这里的“指针”仅仅是一个名字,在Java中是不存在指针的.
那么既然它不指向任何的对象,那么他也就不是一个数组,那么既然他不是一个数组就必然不会访问到它的“下标”.
NULL
现在有一个问题
这里的ret1和ret2输出的内容一样吗?
一样的,解释如下
我们在这里类比
int a = 10;
int b = a;
上面这两行代码的意思是将a这个变量里面存放的值给b这个变量,那么
int[] array2 = array;
它的意思就是将array这个变量里面的值给array2这个变量,那么此时array2与array所指向的空间就是同一个了(array2这个引用指向了array这个引用所指向的对象)
那么我们现在将array2[0]=99;
这个操作之后打印出来的结果是什么?
两个都是99,因为你这两个引用类型指向的是同一个对象
那么下面这种情况该怎么解释
当我的array指向array2所指向的对象时,我原来的array所指向的对象怎么办?
将来会自动回收掉!!!
数组的应用场景
保存数据
现在我们来写一个打印数组的函数print
和C语言中学习的函数栈帧是一样的,实参的array和形参的array是不一样的两块空间,但是和C语言不同的是,在Java中值传递和址传递是没有太大的区分的,因为对于Java而言数组是一个引用类型,引用类型中放入的是一个指向对象的一个地址所以当给函数传的是值的时候就是值传递,当给函数传地址的时候就是址传递.
这行代码输出的结果是什么?
为什么?
但是,请注意:和C语言一样,一但退出这个函数,那么这个函数所开辟栈帧就会被回收掉.
而且数组是可以作为函数的返回值的
那么以后你若是想要返回多个值的话可以通过数组来返回,例如:
我的天哪!!!
在Java中数组的[]中不一定是一个常量的,所以上面的那种定义方法也是可以的,和我们C语言中所说的变长数组是一样的.
数组练习
数组转字符串
public class Test {
public static String mytoString(int[] arr) {
if(arr == null) {
return "null";
}
String srr = "[";
for (int i = 0; i < arr.length; i++) {
srr += arr[i];
if (i == (arr.length) - 1) {
srr += "]";
} else {
srr += ",";
}
}
return srr;
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
String ret = mytoString(arr);
System.out.println(ret);
}
注意:题目要求是将整形数组里的内容转化为字符串输出,并没有要求让这个字符串存到一个字符串数组中去,那么利用Java特有的字符串的拼接方法,我们就可以实现这个功能,最后返回这个字符串的名字就可以找到这个字符串了(和C语言一样).
在数组中查找元素,并且返回该元素的下标
import java.util.Arrays;
import java.util.Scanner;
/**
* Created with IntelliJ IDEA
* Description:
* User: lenovo
* Date: 2023 -03 -12
* Time: 10:43
*/
public class B_find {
public static void main(String[] args) {
int[] arr = {1, 2, 6, 4, 5, 6, 19, 8, 9, 10};
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
Arrays.sort(arr);//对该数组进行排序(面向对象)
//Bfind(arr,x);
int ret = Arrays.binarySearch(arr, x);//对该数组进行二分查找(面向对象)
System.out.println("排序后的数组" + Arrays.toString(arr));
System.out.println(ret);
}
//以下是面向过程所需要的二分查找的算法,不涉及排序
public static int Bfind(int[] arr, int x) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (x == arr[mid]) {
return mid;
} else if (x > arr[mid]) {
left = mid + 1;
} else if (x < arr[mid]) {
right = mid - 1;
} else {
return mid;
}
}
return -1;
}
}
可以看到,对于面向对象的Java而言,Java本身自带这些东西,你直接拿来用就行,但是对于面向过程的C语言而言你若是要用,那么你得自己写.
Java实现冒泡排序
import java.util.Arrays;
/**
* Created with IntelliJ IDEA
* Description:
* User: lenovo
* Date: 2023 -03 -12
* Time: 11:59
*/
public class bubble_sort {
public static int[] bubble_sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
boolean a = false;
//这里用a来判断这一趟排序结束后是否已经排好顺序
//i表示趟数
for (int j = 0; j < arr.length - 1 - i; j++) {
//j的循环要跟着i在变化,也就是用来控制每趟比上一趟少1
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
a = true;//如果排序了就让a=true
}
}
if (a == false) {//在每一趟排序后都要判断这一趟有没有排过序,若是没有则证明该数组已然排好序,直接跳出就可以了
break;
}
}
return arr;
}
public static void main(String[] args) {
int[] arr = {1, 15, 2, 98, 45, 65, 102, 203, 150};
bubble_sort(arr);
System.out.println("排序后的数组" + Arrays.toString(arr));
}
}
数组拷贝
import java.util.Arrays;
/**
* Created with IntelliJ IDEA
* Description:
* User: lenovo
* Date: 2023 -03 -12
* Time: 12:40
*/
public class Test {
public static int[] copy(int[] arr) {
int[] copy=new int[arr.length];
for (int i = 0; i < arr.length; i++) {
copy[i]=arr[i];
}
return copy;
}
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6,7,8,9,10};
int[] ret=copy(arr);
System.out.println(Arrays.toString(ret));
}
}
那么在Java中有没有字符串拷贝的库方法呢?
有的
那么它是怎么工作的呢?
上图是Arrays.copy0f的源码,我们可以看到,要使用这个方法需要给这个方法传两个变量
拷贝的数组
新的长度
import java.util.Arrays;
/**
* Created with IntelliJ IDEA
* Description:
* User: lenovo
* Date: 2023 -03 -12
* Time: 12:40
*/
public class Test {
public static int[] copy(int[] arr) {
int[] copy = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
copy[i] = arr[i];
}
return copy;
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] ret = Arrays.copyOf(arr, arr.length);
//int[] ret=copy(arr);
System.out.println(Arrays.toString(ret));
}
}
好的,但是有没有发现,这个Arrays.copy0f要输入一个新的长度,那么就意味着
这个方法还可以拿来扩容!
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] ret = Arrays.copyOf(arr, arr.length * 2);
//int[] ret = Arrays.copyOf(arr, arr.length);
//int[] ret=copy(arr);
System.out.println(Arrays.toString(ret));
}
}
运行结果如上所示
那有没有更灵活的拷贝的方法呢?
有的
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] ret=Arrays.copyOfRange(arr,1,3);//[1,3)在Java中一般都是左闭右开区间
System.out.println(Arrays.toString(ret));
//int[] ret = Arrays.copyOf(arr, arr.length * 2);
//int[] ret = Arrays.copyOf(arr, arr.length);
//int[] ret=copy(arr);
//System.out.println(Arrays.toString(ret));
}
按照范围来拷贝,但是请注意
在Java中遇到区间一般都是[)左闭右开区间.
那么中间这个又是什么呢?
好的家人们,第三种拷贝数组的方法
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] copy=new int[arr.length];
System.arraycopy(arr,0,copy,0,arr.length);
System.out.println(Arrays.toString(copy));
//int[] ret=Arrays.copyOfRange(arr,1,3);//[1,3)在Java中一般都是左闭右开区间
//System.out.println(Arrays.toString(ret));
//int[] ret = Arrays.copyOf(arr, arr.length * 2);
//int[] ret = Arrays.copyOf(arr, arr.length);
//int[] ret=copy(arr);
//System.out.println(Arrays.toString(ret));
}
}
注意:拷贝一定是开了一个全新的空间的,不是前面写函数的时候将引用类型所指向的地址传过去!.
数组逆序
import java.util.Arrays;
/**
* Created with IntelliJ IDEA
* Description:
* User: lenovo
* Date: 2023 -03 -12
* Time: 13:35
*/
public class Test {
public static int[] revers(int[] arr) {
int i = 0;
int j = arr.length - 1;
for (i = 0, j = arr.length - 1; i < j; i++, j--) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
return arr;
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] rev = revers(arr);
System.out.println(Arrays.toString(rev));
}
}
运行结果如下
二维数组
先来一个和C语言一样的
public class Test {
public static void main(String[] args) {
//一共有三种定义方式
int[][] arr1 = {{1, 2, 3}, {4, 5, 6}};//第一种
int[][] arr3 = new int[][]{{1, 2, 3}, {4, 5, 6}};//第二种
int[][] arr2 = new int[2][3];//第三种
//和C一样去打印数组
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(arr1[i][j] + " ");
}
System.out.println();
}
}
}
不知是否大家还记得这句话
二维数组就是特殊的一维数组
public static void main(String[] args) {
int[][] arr1 = {{1, 2, 3}, {4, 5, 6}};
//int[][] arr3 = new int[][]{{1, 2, 3}, {4, 5, 6}};
//int[][] arr2 = new int[2][3];
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();
}
所以对于几行几列的问题我们可以写出如上的代码
接下来我们看另外一种打印的方法
public class Test {
public static void main(String[] args) {
int[][] arr={{1,2,3},{4,5,6}};
for (int[] tmp: arr) {
for (int x: tmp) {
System.out.print(x+" ");
}
System.out.println();
}
}
但是,foreach是操作不了下标的
OKOK,那么接下来让我们看一下Arrays的操作
public static void main(String[] args) {
int[][] arr = {{1, 2, 3}, {4, 5, 6}};
String ret = Arrays.deepToString(arr);
System.out.println(ret);
}
与C语言的区别!!!!!!
现在array1数组就是这样的一种情况
不规则的二维数组
public class Test {
public static void main(String[] args) {
int[][] arr=new int[2][];
arr[0]=new int[3];
arr[1]=new int[5];
System.out.println(arr[0].length);
System.out.println(arr[1].length);
}
public static void main(String[] args) {
int[][] arr=new int[2][];
arr[0]=new int[3];
arr[1]=new int[5];
System.out.println(arr[0].length);
System.out.println(arr[1].length);
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();
}
}
Arrays.fill
ublic class Test {
public static void main(String[] args) {
int[] arr=new int[100];
Arrays.fill(arr,9);
System.out.println(Arrays.toString(arr));
}
}
这个方法可以将你的数组中所有的元素都填充为9
还可以进行范围填充,如下
public class Test {
public static void main(String[] args) {
int[] arr=new int[100];
Arrays.fill(arr,0,8,7);//[0,8)
//Arrays.fill(arr,9);
System.out.println(Arrays.toString(arr));
}
OKOK,本篇博客到这里就结束了,谢谢所有能看到这里的同学们!!!