前言
数组是一个很重要的引用数据类型(Java中除了八大基本数据类型,其他的皆为引用数据类型)。数组是一组数据(元素)的集合,且每个元素都必须是相同类型的。
数组长度不变,由length属性表示;length属性被final修饰,只能访问不可修改;下标范围是[0,length - 1],若越界则报错:ArrayIndexOutOfBoundsException (数组下标越界异常)。
数组分为一维数组、多维数组。
数组定义时不能指定其长度,例如:int b [100] [100];
数组初始化一般和定义一起完成,也可先定义再初始化;
数组的初始化分为静态初始化和动态初始化。
一维数组:
-
静态初始化 :
int [ ] array = {1,2,3,4};
-
动态初始化:
int [ ] array = new int [10];
二维数组:
-
静态初始化:
String [][] alphabet = {{"a","b","c","d"},{"e","f"},{"g"},{"h","i","j","k","l"}};
//二维数组的第二维长度可以不一致
-
动态初始化:
<类型> [][] <数组名> = new <类型>[<第一维大小>,<第二维大小>];
//注意第一维和第二维,一般与实际问题中对应。行优先则行为第一维,列为第二维;列优先则列为第一维,行为第二维
正文
一、数组的使用
1 输出数组元素,以For-Each循环(增强For)为例
For-Each一般用于输出数组中的所有元素;
int [] array = {6,7,8,9,10};
for (int i : array) {
System.out.print(i+ "\t");
}
// 6 7 8 9 10
更为常见的是普通的For循环(见下方法二)
2 数组作为返回值、数组作为方法参数入参:以反转数组元素案例为例
class Scratch {
public static void main(String[] args) {
int [] array = {6,7,8,9,10};
int [] reversed = reverseArray(array);
printArray(reversed);
}
// 使用普通For循环打印输出任意一个数组
public static void printArray(int [] array){
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
// 数组作为参数入参 数组成为返回值
public static int[] reverseArray(int [] array){
int length = array.length;
int [] result = new int[length];
for (int i = 0; i < length; i++) {
result[i] = array[length-1-i];
}
return result;
}
}
二、多维数组的理解
多维数组可以看成是数组的数组,比如二维数组可理解为一维数组里又嵌套了个一维数组;
int a[][] = new int[2][5];
以上二维数组a可以看成一个两行五列的数组(或者两列五行,如果以列优先)
一般的实际情况多维最多用到二维数组;
-
二维数组的遍历:
-
使用增强For
-
使用普通For循环
类似于一维数组,for循环中嵌套for(不再赘述)
-
class Scratch{
static int [][] dyadicArray1 = new int [3][];
static int [][] dyadicArray2 = {{},{1},{2,3},{4,5,6}};
static int [][] dyadicArray3 = new int [3][4];
static int [][] dyadicArray4 = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
// static int length = dyadicArray.length;
public static void main(String[] args) {
/*// 报空指针错误NullPointerException
for (int[] ints : dyadicArray1) {
for (int anInt : ints) {
System.out.print(anInt + " ");
}
}*/
// 1 2 3 4 5 6
System.out.println();
for (int[] ints : dyadicArray2) {
for (int anInt : ints) {
System.out.print(anInt + " ");
}
}
/* System.out.println();
// 打印输出12个0
for (int[] ints : dyadicArray3) {
for (int anInt : ints) {
System.out.print(anInt + " ");
}
}
System.out.println();
// 输出1到16
for (int[] ints : dyadicArray4) {
for (int anInt : ints) {
System.out.print(anInt + " ");
}
}
*/
}
}
三、工具类Arrays的应用
Arrays.toString(): 打印出数组中每个元素
Arrays.sort(): 按升序排序,并返回排序完的数组
Arrays.fill(a,): 将指定的元素a填充进数组
四、利用数组和循环进行冒泡排序
import java.util.Arrays;
class Scratch {
static int[] testArray ={9,6,5,10,12};
static int[] testArray1 ={1,2,3,4,5};
static int[] testArray2 = {32,43,34,55,3,222};
public static void main(String[] args) {
int[] sorted = BubbleSort(testArray2);
System.out.println(Arrays.toString(sorted));
}
public static int[] BubbleSort(int [] array){
// 临时变量
int temp;
// 外层循环:判断要走多少次
for (int i = 0; i < array.length; i++) {
// 通过flag标识位减少没有意义的比较
boolean flag = false;
// 内层循环,比较判断两个数,若第一个数比第二个数大,则交换位置
for(int j = 0;j < array.length-1; j++) {
if (array[j] > array[j+1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
flag = true;
}
}
if(flag == false){
break;
}
}
return array;
}
}
冒泡排序时间复杂度为O(n2) ,是一种稳定的排序;
五、稀疏数组
一种很重要的数据结构;
适用情况:当一个数组中大部分元素为0时,或者为同一值的数组时,可以使用系数数组来保存该数组
引入案例:编写五子棋游戏,有存盘退出和续上盘的功能。考虑使用二维数组记录棋盘;
分析:因为二维数组的很多值都是默认值0,因此记录了很多没有意义的数据。
解决:采用稀疏数组,解决重复的问题,将原来一个庞大冗余的数组转换成了精简占空间小的数组
处理方式:
-
记录数组一共有几行几列,有多少个不同值
-
把具有不同值的元素和行列及值记录在一个小规模数组里,从而缩小程序的规模
本质:记录每一个有效的坐标的值并将它们放置进一个新的数组
创建稀疏数组和将稀疏数组还原
/**
* @author Echohol
* @created 2021/07/2021/7/15 - 9:21
*
*/
public class DemoSparseArray {
//创建打印数组的函数
public static void printArray(int [][] array){
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + "\t");
}
System.out.println();
}
}
public static void main(String[] args) {
//创建要转化的数组
int [][] rawArray = new int [5][8];
rawArray[3][4] = 4;
rawArray[1][2] = 2;
rawArray[4][5] = 5;
rawArray[0][1] = 1;
rawArray[2][3] = 3;
printArray(rawArray);
System.out.println("=================================================================");
//获取其中的所有特殊值个数
//sum用于计算有多少个特殊值
int sum = 0;
for (int[] ints : rawArray) {
for (int anInt : ints) {
if(anInt!=0){
sum++;
}
}
}
//根据上述属性定义初始化稀疏数组
//获取原数组的行列数
int row = rawArray.length;
int col = rawArray[0].length;
//稀疏数组的行数
int sparseRow = sum + 1;
//稀疏数组的列数固定为3
int[][] sparseArray = new int[sparseRow][3];
//定义稀疏数组第一列:原数组的行列值和特殊值个数
sparseArray[0][0] = row;
sparseArray[0][1] = col;
sparseArray[0][2] = sum;
//遍历原数组并将特殊值的行列值和本身值储存进稀疏数组
//count为计数器,用于计算获取到了几个特殊值,获取到一个加一
int count = 0;
for (int i = 0; i < rawArray.length; i++) {
for (int j = 0; j < rawArray[i].length; j++) {
if(rawArray[i][j]!=0){
count++;
//获取到的第n个原数组元素就在稀疏数组的第(n+1)行;
// 而稀疏数组(n+1)行的下标就是n,故count直接作为稀疏数组的行下标
//稀疏数组列规定只有三列,每行的列从左至右表示原数组的特殊值的 行下标、列下标和本身的值
sparseArray[count][0] = i;
sparseArray[count][1] = j;
sparseArray[count][2] = rawArray[i][j];
}
}
}
//打印稀疏数组
printArray(sparseArray);
System.out.println("=================================================================");
//将稀疏数组还原成原数组
//先获取稀疏数组的第一行前两个元素,并分别赋给新定义的还原数组完成初始化
int reverseRow = sparseArray[0][0];
int reverseCol = sparseArray[0][1];
int[][] reversedArray = new int [reverseRow][reverseCol];
//初始化后的数组全为0,特殊值还需要经过遍历稀疏数组中剩下的行中的数据去将它们一个个地赋值给还原数组
//这里i = 1 是因为稀疏数组第一行无需遍历,第一行保存的是原数组的参数
for (int i = 1; i < sparseArray.length; i++) {
for (int j = 0; j < sparseArray[i].length; j++) {
//此处sparseArray[i][0]对应原数组的行下标
// sparseArray[i][1]对应列下标
// sparseArray[i][2]对应本身元素的值
reversedArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i[2];
}
}
//打印输出
printArray(reversedArray);
}
}