🎨1.Java 数组的基本用法
🎳1.1 数组的定义方式
🍁方式 1:
数据类型[] 变量名 = 元素1,元素2,元素3,...,元素n;
int[] arr = 1,2,3,4,5,6,7,8,9,0;
🍁方式 2:
数据类型[] 变量名 = new int[]元素1,元素2,元素3,...,元素n;
int[] arr = new int[]1,2,3,4,5,6,7,8,9,0;
❗️new
后面那个中括号里面不能指定元素个数,必须是空的!
🍁方式 3:
数据类型[] 变量名 = new int[元素个数]; (数组全部元素会初始化为0)
🎳1.2 数组的创建与使用
🍁数组的创建:
int[] data1 = {1,2,3,4,5,6,7,8,9,0};
int[] data2 = new int[]{1,2,3,4,5,6,7,8,9,0};
int[] data3 = new int[10];
复制代码
🍁数组的使用:
import java.util.Arrays;
public class TestBlog {
public static void main(String[] args) {
//创建数组
int[] arr = new int[]{1,2,3,4,5,6,7,8,9,0};
//访问数组长度
System.out.println(arr.length);
//访问数组元素
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
//遍历数组 1.for循环 2.foreach循环 3.toString函数
//方式1:for循环
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
//方式2:foreach循环
for (int a: arr) {
System.out.print(a + " ");
}
System.out.println();
//方式3:toString函数
System.out.println(Arrays.toString(arr));
}
}
复制代码
对于数组遍历方式 2:
for (接受变量: 数组) {
//语句块;
//此方法不能获取下标
}
复制代码
对于遍历方式 3:toString
是 JavaArrays
类中的一个方法,能够将数组转换成字符串,有,
隔开元素,中括号[]
包裹数组所有元素!
🎨2.Java 类型之引用
🎳2.1 引用类型
在 Java 当中数组其实是一个对象,我们知道在数组定义时有两种方式都用到了关键字new
,这个关键字就是实现类的实例化,实例出一个对象,使用一个能接收“实例化对象的值”的类型就是引用类型。这个“实例化对象的值”其实是一个地址,该地址指向该数组(对象),比如下面定义的x
变量定义一个数组,这个x
就是引用变量。这个与 C 语言中的指针有一点相似,但是它并不是指针,引用变量是一个值,在这里,该值是这个数组的地址。我们知道我们所定义的x
变量是局部变量所以它在栈上生成,而这个数组(对象)是在堆上开辟内存的。null
表示空引用,与 C 语言中的NULL
很相似,表示一个无效的内存位置,既然这个内存是无效的,那肯定就不能对这个内存指向的空间进行读写。注意: Java 中并没有约定 null
和 0
号地址的内存有任何关联.
数据类型[] 变量名 = new int[元素个数]; (数组全部元素会初始化为0)
int[] x = new int[3];
x[0] = 10;
x[1] = 20;
x[2] = 30;
复制代码
所谓的 "引用" 本质上只是存了一个地址. Java 将数组设定成引用类型, 这样的话后续进行数组参数传参, 其实只是将数组的地址传入到函数形参中. 这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大)下面用一个数组传参的例子来进一步理解引用。
🎳2.2 数组传参
public class TestBolg {
public static void arrFunc(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
arr[i] = 10 * (i+1);
}
}
public static void main(String[] args) {
int[] x = new int[3];
arrFunc(x);
System.out.println(Arrays.toString(x));
}
}
复制代码
对于数组的传参就是将一引用变量的值传递给方法的形参,由于引用变量存的是对象的地址,所以方法会根据传入的参数对数组(实例化的对象)进行修改或读写操作,从而使数组内元素的值发生改变,这就是引用传递。
🎳2.3 认识 JVM 区域划分
🎨3.Java 数组应用
🎳3.1 利用数组求平均值与交换两个数
public class AvgSwap {
public static void swap(int[] data) {
int tmp = data[0];
data[0] = data[1];
data[1] = tmp;
}
public static double avg(int[] data) {
int sum = 0;
for (int i = 0; i < data.length; i++) {
sum += data[i];
}
return 1.0 * sum / data.length;
}
public static void main(String[] args) {
int[] swap = {22, 33};
int[] avg = {1,2,3,4,5,6,7,8,9,0};
System.out.println("数据交换前:a = " + swap[0] + ", b = " + swap[1]);
swap(swap);
System.out.println("数据交换后:a = " + swap[0] + ", b = " + swap[1]);
System.out.println("数组平均值为:" + avg(avg));
}
}
复制代码
🎳3.2 拷贝数组
import java.util.Arrays;
public class Copy {
public static int[] copy(int[] arr) {
if (arr == null) {
return null;
}
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[] arr1 = {1,2,3,4,5,6,7,8,9};
System.out.println("数组1:");
System.out.println(Arrays.toString(arr1));
int[] arr2 = copy(arr1);
System.out.println("数组2:");
System.out.println(Arrays.toString(arr2));
}
}
复制代码
当然 Java 中的Arrays
类有内置的拷贝方法:<font color = orange>
static 数据类型[] copyOf(数据类型[] original, int newLength)
</font>复制指定的数组,用零截取或填充(如有必要),以便复制具有指定的长度。
<font color = orange>
static 数据类型[] copyOfRange(数据类型[] original, int from, int to)
</font>将指定数组的指定范围[from, to)
复制到新数组中。<font color = orange>
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
</font>Object src
表示源数组,srcPos
表示从源数组开始拷贝的下标位置,Object dest
表示目标数组,destPos
表示表示从目标数组开始拷贝的下标位置,length
表示拷贝数组元素个数。如果细心去查看该方法源代码,会发现该方法被native
修饰,这个表示这个方法是使用C/C++
实现的。将指定源数组中的数组从指定位置复制到目标数组的指定位置。<font color = orange>
</font>
最后一种就是利用数组名.clone
创建并返回此对象的副本。 “复制”的精确含义可能取决于对象的类。因为数组实例化后就是一个对象,该方法会返回值为对应类型的数组,所以使用该方法进行拷贝。
import java.util.Arrays;
public class Copy {
public static void main(String[] args) {
int[] arr1 = {1,2,3,4,5,6,7,8,9};
System.out.println("arr1:" + Arrays.toString(arr1));
int[] arr2 = Arrays.copyOf(arr1, arr1.length);
System.out.println("arr2:" + Arrays.toString(arr2));
int[] arr3 = Arrays.copyOf(arr1, arr1.length * 2);
System.out.println("arr3:" + Arrays.toString(arr3));
int[] arr4 = Arrays.copyOfRange(arr1, 1, 5);
System.out.println("arr4:" + Arrays.toString(arr4));
int[] arr5 = new int[arr1.length];
System.arraycopy(arr1, 0, arr5, 0, arr1.length);
System.out.println("arr5:" + Arrays.toString(arr5));
int[] arr6 = arr1.clone();
System.out.println("arr6:" + Arrays.toString(arr6));
}
}
复制代码
另外,一般来说数组的拷贝是浅拷贝,因为 Java 中万物皆对象,对对象的拷贝就是浅拷贝,而数组也是一种对象,除非人为因素使实现深拷贝,如果数组中的为简单的数据类型一般都是深拷贝,如果数组中为引用类型一般都是浅拷贝。
🎳3.3 数组转换字符串
再上述代码展示中我相信大家已经看到了Arrays.toString
方法的使用,它能将一个数组转换成带中括号字符串!现在我们来模拟一下这个方法:
public class StringArray {
public static String myToString(int[] arr) {
if (arr == null) {
return "[]";//空引用返回[]
}
String str = "[";//初始化字符串为[
for (int i = 0; i < arr.length - 1; i++) {
str += arr[i] + ",";//注意最后一个数组元素后无逗号
}
str += arr[arr.length - 1] + "]";//查漏补缺,补上最后一个元素和]
return str;
}
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
System.out.println(myToString(arr));
}
}
复制代码
🎳3.4 数组查找
⛳️3.4.1 顺序查找
顺序查找是最简单的查找方法,直接遍历一遍数组就可以了。
public class Search {
public static void main(String[] args) {
//顺序查找元素,找到其下标,未找到则输出未找到
int[] arr = {1,2,3,4,5,6,7,8,9};
int k = 7;
int flag = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == k) {
System.out.println("找到了!下标为:" + i);
flag = 1;
break;
}
}
if (flag == 0) {
System.out.println("未找到!");
}
}
}
复制代码
⛳️3.4.2 二分查找
然后就是我们已经非常熟悉的二分查找:
public class BinSearch {
public static int binSearch(int[] arr, int k) {
if (arr == null) {
return -1;
}
int left = 0;
int right = arr.length - 1;
int mid = left + (right - left) / 2;
while (left <= right) {
mid = left + (right - left) / 2;
if (k > arr[mid]) {
left = mid + 1;
}
else if (k < arr[mid]) {
right = mid - 1;
}
else {
return mid;
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
int k = 7;
System.out.println(binSearch(arr, k));
}
}
复制代码
🎳3.5 数组的排列
⛳️3.5.1 判断数组是否有序
使用两个计数棋进行计数(从 1 开始计数),遍历数组分别对数组前一项不小于后一项,数组后一项不小于前一项独立计数,如果计数结果有刚好等于数组长度的结果则数组有序。
public class ArraryOrder {
public static boolean arrOrder(int[] arr) {
if (arr == null) {
return false;
}
int cnt1 = 1;
int cnt2 = 1;
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] <= arr[i+1]) {
cnt1++;
}
if (arr[i] >= arr[i+1]) {
cnt2++;
}
}
if (cnt1 == arr.length || cnt2 == arr.length) {
return true;
}
else {
return false;
}
}
public static void main(String[] args) {
int[] arr1 = {1,2,3,4,5,6,7,8,9};
int[] arr2 = {9,8,7,6,5,4,3,2,1};
int[] arr3 = {2,1,4,7,5,9,8,3,6};
System.out.println(arrOrder(arr1));
System.out.println(arrOrder(arr2));
System.out.println(arrOrder(arr3));
}
}
复制代码
⛳️3.5.2 数组逆序
双指针,依次将左边元素与右边元素互换。
import java.util.Arrays;
public class ReverseArr {
public static void rever(int[] arr) {
if (arr == null) {
return;
}
int l = 0;
int r = arr.length - 1;
while (l < r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
l++;
r--;
}
}
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
System.out.println("逆序前:");
System.out.println(Arrays.toString(arr));
System.out.println("逆序后:");
rever(arr);
System.out.println(Arrays.toString(arr));
}
}
复制代码
⛳️3.5.3 冒泡排序(升序)
从数组首位元素开始将数组的相邻两个元素进行比较,如果前面的元素比后面大,则进行交换否则不交换,每进行一趟排序就能将一个最大的数放在最后,如果需要把所有元素都排好序,需要进行数组元素个数减一趟排序。因为每一趟排序都会排出一个最大的数放在后面,也就是说每排序一趟就有一个数排序完成,所以每完成一趟排序,排序比较次数就减一,假设数组元素个数为size
,则一共要进行size-1
趟排序,第 1 趟排序比较次数为size-1
,随着趟数比较次数逐次递减,如果此时为第i
趟排序,则需要比较的次数为size - 1 - i
。比如 10 个元素进行冒泡排序,一共要进行 9 趟排序,第一趟需排序比较 9 次,第二趟 8 次,第三趟 7 次,以此类推。
import java.util.Arrays;
public class BubbleSort {
public static void bubbleSort(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
int flag = 0;
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j+1]) {
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
flag = 1;
}
}
if (flag == 0) {
break;
}
}
}
public static void main(String[] args) {
int[] arr = {2,1,8,5,9,4,6,7,3};
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
bubbleSort(arr);
System.out.println("排序后:");
System.out.println(Arrays.toString(arr));
}
}
复制代码
🎨4.二维数组
二维数组本质上也就是一维数组, 只不过每个元素又是一个一维数组.
前面我们知道了,我们是使用引用来指向一个数组的,那么二维数组其实一个类型为引用的数组,数组中的每个元素都是一个引用变量,引用变量中指向另一个一维数组。
二维数组定义:
数据类型[][] 数组名称 = new 数据类型 [行数][列数] 初始化数据
数组名称.length;//表示行数
数组名称[行数].length;//表示某一行的列数
复制代码
public class TestBolg {
public static void main(String[] args) {
int[][] arr = new int[3][3];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
arr[i][j] = 8 + i +j;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.println(Arrays.toString(arr[i]));
}
}
}
复制代码
同理, 还存在 "三维数组", "四维数组" 等更复杂的数组。
评论