狂神Java SE (六)数组
01 什么是数组
- 数组是相同类型数据的有序集合
- 描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
- 其中每个数据称作一个数组元素,每个数组元素可以通过一个下标访问
02 数组的声明和创建
- 必须先声明数组变量,才能在程序中使用数组
dataType[] arrayRefVar; dataType arrayRefVar[]; // 也可以,但不推荐
- Java语言使用
new
操作符来创建数组dataType[] arrayRefVar = new dataType[arraySize];
- 数组的元素通过索引访问,索引从0开始
- 获取数组长度
arrays.length
03 三种初始化及内存分析
- Java内存分析
- 堆
- 存放new的对象和数组
- 可以被所有线程共享,不会存放别的对象引用
- 栈
- 存放基本变量类型(包含这个基本类型的具体数值)
- 引用对象的变量(存放该引用在堆里面的具体地址)
- 方法区
- 可以被所有线程共享
- 包含所有class和static变量
- 堆
// 1. 声明数组,此时array存放在栈中
int[] array = null;
// 2. 创建数组(初始化),此时在堆中开辟了内存,存放对象
array = new int[10];
// 3. 给数组中元素赋值,此时修改对应的值
array[0] = 1;
- 数组的三种初始化
- 静态初始化 (创建 + 赋值)
int[] a = {1, 2, 3}; Man[] mans = {new Man(1,1), new Man(2,3)};
- 动态初始化 (包含默认初始化)
int[] a = new int[2]; a[0] = 1; a[1] = 2;
- 默认初始化
- 数组是引用类型,其元素相当于类的实例变量
- 数组分配空间时,其中的每个元素会按照实例变量同样的方式被隐式初始化
- 静态初始化 (创建 + 赋值)
04 下标越界及小结
-
数组的特点
- 长度确定,创建后大小不可修改
- 元素类型相同,不允许出现混合类型
- 元素可以是任何数据类型,包括基本类型和引用类型
- 数组变量属于引用类型,也可以看成是对象,数组中每个元素相当于该对象的成员变量。
- 数组本身就是对象,Java中对象是在堆中的,无论数组保存原始类型还是其他对象类型,数组对象本身是在堆中的。
-
数组边界
- 下标的合法区间:
[0, length-1]
- 数组下标越界异常:
ArrayIndexOutOfBoundsException
- 下标的合法区间:
-
小结
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度是确定的、不可变的。如果越界,会报异常。
05 数组的使用
for-each
循环for (int array : arrays){ }
- 数组作为方法入参
pbulic void printArray(int[] arrays){ }
- 数组作为返回值
public static int[] reverseArray(int[] arrays){ }
06 二维数组
- 可以视为"数组的数组"
- 二维数组
int[][] a = new int[2][5];
07 Arrays类讲解
- 数组的工具类
java.util.Arrays
- 使用
Arrays
工具类,对数组对象进行一些基本操作 - 该类中的方法都是
static
修饰的静态方法,使用时可以直接使用类名进行调用,无需使用对象调用(也可以)。 - 常用功能
- 数组赋值:
fill
方法 - 数组排序:
sort
方法,升序排列 - 比较数组:
equals
方法,比较元素值 - 查找数组元素:
binarySearch
方法,对排序好的数组进行二分查找
- 数组赋值:
package com.kuang.arrays;
import java.util.Arrays;
/**
* Arrays工具类
*
* @author maple_w
* Created on 21/07/11 011 16:32
*/
public class Demo01_Arrays {
public static void main(String[] args) {
int[] a = {1,3,4,5,22,34566,123};
System.out.println(a); // [I@1b6d3586
// 打印数组元素, Arrays.toString()
System.out.println(Arrays.toString(a)); // [1, 3, 4, 5, 22, 34566, 123]
// 升序排序, Arrays.sort()
Arrays.sort(a);
System.out.println(Arrays.toString(a)); // [1, 3, 4, 5, 22, 123, 34566]
// 填充数组, Arrays.fill()
Arrays.fill(a, 2,4, 0);
System.out.println(Arrays.toString(a)); // [1, 3, 0, 0, 22, 123, 34566]
}
}
08 冒泡排序
两层循环,外层冒泡轮数,里层依次比较;
嵌套循环,时间复杂度为 \(O(n^2)\)。
package com.kuang.arrays;
import java.util.Arrays;
/**
* 冒泡排序
* 比较数组中两个相邻元素,如果第一个比第二个大,交换位置
* 每次比较都会产生一个最大或最小的数字
* 下一轮可以少一次排序
* 依次循环,直到结束
*
* @author maple_w
* Created on 21/07/11 011 16:42
*/
public class Demo02_BubbleSort {
public static void main(String[] args) {
int[] a = {1, 5, 3, 2, 6, 7, 213, 21};
int[] sortesd = bubbleSort(a);
System.out.println(Arrays.toString(sortesd)); // [1, 2, 3, 5, 6, 7, 21, 213]
}
public static int[] bubbleSort(int[] array) {
// 临时变量
int temp = 0;
// 外层循环,判断要走多少次
for (int i = 0; i < array.length - 1; i++) {
// 优化:通过flag标识减少无意义比较
boolean flag = false;
// 内层循环,比较判断两个数,如果第一个数更大,交换位置
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j + 1] < array[j]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag = true;
}
}
if (flag == false) {
break;
}
}
return array;
}
}
09 稀疏数组
- 一个数组中大部分元素为0,或同一值时,可以用稀疏数组进行保存。
- 稀疏数组的处理方式:
- 记录数组共有几行几列,有多少个不同值
- 将不同值的元素及其行列、值记录在一个小规模数组中
package com.kuang.arrays;
import java.util.Arrays;
/**
* 稀疏数组
*
* @author maple_w
* Created on 21/07/11 011 16:52
*/
public class Demo03_SparseArray {
public static void main(String[] args) {
// 二维数组表示棋盘
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 1 0 0 0 0 0 0 0 0
// 0 0 0 2 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
System.out.println("打印棋盘");
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
// 获取有效值个数
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array1[i][j] != 0) {
sum++;
}
}
}
System.out.println("有效值的个数:" + sum); // 2
// 使用稀疏数组存储
int[][] array2 = new int[sum + 1][3];
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
int count = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0) {
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
// 输出稀疏数组
// 11 11 2
// 1 2 1
// 2 3 2
System.out.println("稀疏数组:");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i][0] + "\t" + array2[i][1] + "\t" + array2[i][2]);
}
// 还原棋盘
System.out.println("还原棋盘");
// 读取稀疏数组
int[][] array3 = new int[array2[0][0]][array2[0][1]];
// 还原值
for (int i = 1; i < array2.length; i++) {
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
// 打印棋盘
for (int[] ints : array3) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 1 0 0 0 0 0 0 0 0
// 0 0 0 2 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
// 0 0 0 0 0 0 0 0 0 0 0
}
}