目录
数组的初始化
- 数组初始化的长度可以是变量,也就是数组的长度可以由自己输入。
int n = 10;
int[] arr = new int[n];//OK
- 如果不知道给数组初始化多大和初始化为什么值,就初始化为null。
因为数组是引用数据类型,用来存 数组对象的地址,如果数组初始化时没有指向具体的数组对象,那就指向 null 空引用。
int[] array;
System.out.println(array);//error,使用数组的时候,数组必须已经初始化。
int[] array = null;
System.out.println(array);//OK
遍历数组
这里总结两种基本的遍历数组的方法:
public static void main(String[] args) {
int[] array = {
1, 2, 3, 4};
//第一种遍历方式: 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 + " ");
}
}
前两种方法的区别就是for i循环有下标,for-each循环没有下标。
求数组的长度
格式: 数组名 . length
int[] array = {
1,2,3,4};
int len = array.length;
System.out.println(len);//4
对 数组是引用数据类型 的理解
要了解数组是引用数据类型,得先了解JVM虚拟机的内存划分:
内存划分便于管理不同类型的数据。
理解数组,主要关注 虚拟机栈 以及 堆:
- 局部变量存储在虚拟机栈中
- 实例化的对象存储在堆中
举个例子:
public static void func() {
int a = 10;
int b = 20;
int[] arr = new int[]{
1, 2, 3};
}
这个代码是在func方法中创建并初始化了 3 个局部变量,这 3 个局部变量分别是 a , b 和 arr ,
变量 a 和 b 是 int 类型,也就是基本数据类型,基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值。所以变量 a 存放的是10,变量 b 存放的是 20;
但数组 arr 的类型是引用数据类型,而引用数据类型创建的变量,一般称为对象的引用 (引用变量),其空间中存储的是对象所在的堆内存中 的地址。所以 arr 指向数组对象的起始位置 1 。通过这个引用变量,我们可以访问和操作整型数组 arr 中的元素。
再举一个例子:
public static void func2() {
int[] array1 = new int[3];
array1[0] = 10;
array1[1] = 20;
array1[2] = 30;
int[] array2 = new int[]{
1, 2, 3, 4, 5};
array2[0] = 100;
array2[1] = 200;
array1 = array2;
array1[2] = 300;
array1[3] = 400;
array2[4] = 500;
}
–
null 空引用
null ,是一个不指向对象的引用,表示一个无效的内存位置,因此不能对这个内存进行任何读写操作,一旦尝试读写, 就会抛出 NullPointerException 空指针异常。
int[] arr = null;
System.out.println(arr[0]);//error
System.out.println(arr.length);//error
数组的应用场景
用两段代码增强对 数组作为函数参数的理解:
第一段代码,这段代码可以通过形参改变main方法中数组对象的值:
public static void func1(int[] arr) {
arr[0] = 99;
}
public static void main(String[] args) {
int[] array = {
1, 2, 3, 4};
func1(array);
}
第二段代码,这段代码不能通过形参改变main方法中数组对象的值:
public static void func2(int[] arr) {
arr = new int[]{
11,22,33,44,55};
}
public static void main(String[] args) {
int[] array = {
1, 2, 3, 4};
func2(array);
}
Java当中,可以返回整个数组
public class Test {
public static int[] func3() {
int[] arr = new int[2];
arr[0] = 10;
arr[1] = 20;
return arr;
}
public static void main(String[] args) {
int[] ret = func3();
for (int i = 0; i < ret.length; i++) {
System.out.print(ret[i] + " ");//10 20
}
}
}
数组转字符串
使用该方法前需要导入 java.util.Arrays 包。Arrays 是操作数组的工具类,Arrays 类中包含 了一些操作数组的常用方法包。方法包可以想象成方便面的调料包,想用的时候倒调料包即可,无需关注调料包是怎么做的。
格式:Arrays.toString(需要转成字符串的数组)
import java.util.Arrays;//导入java.util.Arrays 包, 其中包含了一些操作数组的常用方法包
public class Test {
public static void main(String[] args) {
int[] arr = {
1, 2, 3, 4, 5};
String ret = Arrays.toString(arr);//数组转字符串
System.out.println(ret);//[1, 2, 3, 4, 5]
}
}
自己实现数组转字符串方法
import java.util.Arrays;
public class Test {
public static String myToString(int[] array) {
if(array == null) {
return "null";
} else if (array.length == 0) {
return "[]";
} else {
String ret = "[";
for (int i = 0; i < array.length; i++) {
ret += array[i];
if(i < array.length-1) {
ret += ", ";
}
}
ret += "]";
return ret;
}
}
public static void main(String[] args) {
int[] arr = {
1, 2, 3, 4, 5};
System.out.println(myToString(arr));//[1, 2, 3, 4, 5]
}
}
数组排序
使用该方法前需要导入 java.util.Arrays 包。
整个数组升序排序格式:Arrays.sort(要被排序的数组)
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {
100,345,2,564,4,10};
Arrays.sort(arr);//整个数组升序排序
System.out.println(Arrays.toString(arr));//[2, 4, 10, 100, 345, 564]
}
}
数组区间升序排序格式:Arrays.sort(要被排序的数组, 下标1, 下标2)
下标1表示排序起始下标,下标2 表示排序终止下标 +1。比如在 下标1 到 下标3 的范围排序,那么格式是:Arrays.sort(数组名, 1, 4)
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {
100,345,2,564,4,10};
Arrays.sort(arr,1,4);//数组区间升序排序
System.out.println(Arrays.toString(arr));//[100, 2, 345, 564, 4, 10]
}
}
冒泡排序的实现
import java.util.Arrays;
public class Test {
public static void bubbleSort(int[] array) {
//防止空指针异常
if(array == null) {
return ;
}
//循环趟数,两个数要比较 1趟,3个数比较 2趟,n个数比较 n-1趟
for (int i = 0; i < array.length - 1; i++) {
//假设该趟已经都排序好了
boolean flg = true;
//每一趟的目的是该趟的所有数中,把最大的数移到最后
//每一趟需要两两比较 array.length - 1 -i 对。
//array.length - 1 -i中的 i 表示,该趟已经有 i 个数排序好了,不用再和最后 i 个数比较了。
for (int j = 0; j < array.length - 1 -i; j++) {
if(array[j] > array[j + 1]) {
//该趟还没有都排序好
flg = false;
//交换
int tmp = array[j];
array[j] = array[j + 1];
array[j + 1] = tmp;
}
}
//如果该趟确实已经都排序好了,结束循环
if(flg) {
break;
}
}
}
public static void main(String[] args) {
int[] arr = {
10, 6, 5, 2, 7};
bubbleSort(arr);
System.out.println(Arrays.toString(arr));//[4, 5, 6, 10, 11]
}
}
数组逆序
Arrays 类中没有包含能逆序数组的方法,得自己实现
思路
设定两个下标, 分别指向第一个元素和最后一个元素. 交换两个位置的元素,
然后让前一个下标自增, 后一个下标自减, 循环继续即可。
import java.util.Arrays;
public class Test {
public static void reverse(int[] array) {
if(array == null){
return ;
}
int left = 0;
int right= array.length -1;
while(left < right) {
int tmp = array[left];
array[left] = array[right];
array[right] = tmp;
left++;
right--;
}
}
public static void main(String[] args) {
int[] arr = {
10, 6, 5, 2, 7};
reverse(arr);
System.out.println(Arrays.toString(arr));//[7, 2, 5, 6, 10]
}
}
查找数组中指定元素(二分查找)
Arrays 类中包含查找数组中指定元素的方法包,
使用该方法前需要导入 java.util.Arrays 包。
格式:Arrays.binarySearch(要被查找的数组, 要查找的元素)
如果没有找到该元素,会返回一个负数。
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {
2, 5, 6, 7, 10};
System.out.println(Arrays.binarySearch(arr,5));//1
}
}
自己实现
写一个二分查找的方法,给定一个有序(有序是指升序或降序) 的整型数组,用键盘输入一个数,在数组中查找这个数,如果查到了就返回该数在数组中的下标,找不到就返回 -1。
以升序数组为例, 二分查找的思路是先取中间位置的元素, 然后使用待查找元素与数组中间元素进行比较:
- 如果相等,即找到了返回该元素在数组中的下标
- 如果小于,以类似方式到数组左半侧查找
- 如果大于,以类似方式到数组右半侧查找
import java.util.Scanner;
public class Test {
public static int binarySearch(int[] arr, int num) {
int left = 0;
int right = arr.length - 1;
while(left <= right) {
int middle = left + ((right-left) / 2);//这么算中间数是防止left + right时超出int的范围
if(num == arr[middle]) {
return middle;
} else if (num > arr[middle]) {
left = middle + 1;
} else {
right = middle - 1;
}
}
return -1;//如果查找不到,返回-1
}
public static void main(String[] args) {
int[] arr = {
1, 3, 6, 7, 9, 10, 11, 13};//被查找的下标必须是升序的
//输入要查找的数
System.out.println("请输入要查找的数:");
Scanner sc = new Scanner(System.in);
int input = sc.nextInt();
int ret = binarySearch(arr,input);
if(ret == -1) {
System.out.println("找不到");
} else {
System.out.println(input + "所在的下标是" + ret);
}
sc.close();
}
}
判断两个数组的内容是否一样
Arrays 类中包含 判断两个数组的内容是否一样 的方法包,
使用该方法前需要导入 java.util.Arrays 包。
格式:Arrays.equals(数组1, 数组2)
该方法的返回类型是布尔类型
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr1 = {
2, 6, 5, 7, 10};
int[] arr2 = {
5, 6, 7, 2, 10};
System.out.println(Arrays.equals(arr1,arr2));//false
int[] arr3 = {
2, 6, 5, 7, 10};
System.out.println(Arrays.equals(arr1,arr3));//true
}
}
数组填充
Arrays 类中包含 数组填充 的方法包,
数组填充分为全部填充和部分填充
使用该方法前需要导入 java.util.Arrays 包。
全部填充格式:Arrays.fill(要填充的数组,需要填充的数)
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr1 = new int[10];
Arrays.fill(arr1,9);
System.out.println(Arrays.toString(arr1));//[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
int[] arr2 = {
3, 4, 5, 6, 7};
Arrays.fill(arr2,8);
System.out.println(Arrays.toString(arr2));//[8, 8, 8, 8, 8]
}
}
部分填充格式:Arrays.fill(要填充的数组,起始下标,终止下标 + 1,需要填充的数)
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr2 = {
3, 4, 5, 6, 7};
Arrays.fill(arr2,0,3,8);
System.out.println(Arrays.toString(arr2));//[8, 8, 8, 6, 7]
}
}
数组拷贝
Arrays 类中包含 数组拷贝 的方法包,
格式;Arrays.copyOf(要拷贝的数组,拷贝长度)
返回值是一个数组,需要用数组变量接收。
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {
2, 3, 4, 6};
int[] copy = Arrays.copyOf(arr,arr.length);
System.out.println(Arrays.toString(copy));//[2, 3, 4, 6]
}
}
除了用来拷贝,还有扩容的作用。
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {
2, 3, 4, 6};
int[] copy = Arrays.copyOf(arr,arr.length*2);//两倍的拷贝长度
System.out.println(Arrays.toString(copy));//[2, 3, 4, 6, 0, 0, 0, 0]
}
}
还有一种拷贝方法,参数不是长度,而是两个坐标
格式:Arrays.copyOfRange(要拷贝的数组,起始坐标,终止坐标 + 1)
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {
2, 3, 4, 6};
int[] copy = Arrays.copyOfRange(arr,1,4);
System.out.println(Arrays.toString(copy));//[3, 4, 6]
}
}
以下代码不是拷贝
int[] arr = {
1,2,3,4,5,6};
int[] newArr = arr;
newArr[0] = 10;
二维数组
二维数组的定义格式:
//第一种格式
int[][] array1 = {
{
1, 2, 3},{
4, 5, 6}};
//第二种格式
int[][] array2 = new int[][]{
{
1, 2, 3},{
4, 5, 6}};
//第三种格式
int[][] array3 = new int[2][3];
//定义不规则的二维数组,行不能省略,列可以省略
int[][] array4 = new int[2][];
二维数组的使用:
使用二维数组前,算出二维数组的列数和行数是很重要的。
二维数组是特殊的一维数组,他的每一个元素都是一维数组。
int[][] array = {
{
1, 2, 3},{
4, 5, 6}};
System.out.println(array[0]);//地址:[I@1b6d3586
System.out.println(array[1]);//地址:[I@4554617c
System.out.println(array.length);//2,相当于行数
System.out.println(array[0].length);//3 相当于列数
System.out.println(array[1].length);//3 相当于列数
能得到二维数组的长度和宽度,就能更方便的使用二维数组了,比如遍历打印二维数组 :
int[][] array = {
{
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();
}
//输出结果:
//1 2 3
//4 5 6
当然,用 for-each 循环就不需要求二维数组的列数和行数。
int[][] array = {
{
1, 2, 3},{
4, 5, 6}};
//二维数组的每个元素是一维数组
for (int[] tmp : array) {
//一维数组的每个元素才是整型
for (int x: tmp) {
System.out.print(x + " ");
}
System.out.println();
}
//输出结果:
//1 2 3
//4 5 6
二维数组转字符串
Arrays工具类中包含的 Arrays.deepToString() 方法可以将二维数组转字符串
格式:Arrays.deepToString(数组名)
int[][] array = {
{
1, 2, 3},{
4, 5, 6}};
System.out.println(Arrays.deepToString(array));// [[1, 2, 3], [4, 5, 6]]
不规则二维数组的使用
不规则二维数组没有初始化的时候每个元素都是 null ,不指向任何一个一维数组,当对 null 进行读写操作时就会出现空指针异常(NullPointerException)
int[][] array = new int[2][];
System.out.println(array[0]);//null
System.out.println(array[1]);//null
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();
}
对二维数组的每个元素创建一个数组之后是可以使用的。
public static void main(String[] args) {
int[][] array = new int[2][];
array[0] = new int[]{
1,2};
array[1] = new int[]{
1,2,3,4};
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();
}
//输出结果:
//1 2
//1 2 3 4