Java数组

数组概述

数组定义

  • 数组是相同类型数据的有序集合。
  • 数组描述的是相同类型的若干个数据按照一定的先后次序離列组合而成
  • 其中每一个数据称作ー个数组元素,每个数组元素可以通过一个下标来访向它们。

数组申明创建

首先必须声明数组变量,オ能在程序中使用数组。下面是声明数组变量的语法:

1
2
3
4
5
6
7
8
9
10
11
package com.everweekup.Array;

public class ArrayDemo1 {
public static void main(String[] args) {
// 变量类型 变量的名字 = 变量的值
// 数组类型
int[] sums; // 1.整型数组定义 首选方法
int sum[]; // 早些时候为了方便c或c++程序员迁移到java而保留的
}
}

ava语言使用new操作符来创建数组,语法如下:

1
2
3
4
5
6
7
8
9
10
package com.everweekup.Array;

public class ArrayDemo1 {
public static void main(String[] args) {
// 变量类型 变量的名字 = 变量的值
// 数组类型
int[] nums; // 1.整型数组定义
nums = new int[10]; // 定义了一个大小为10的数组,可以存放10个int类型的数据
}
}

数组的元素是通过索引访问的,数组索引从0开始。

获取数组长度:arrays.length

数组赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.everweekup.Array;

public class ArrayDemo1 {
public static void main(String[] args) {
// 变量类型 变量的名字 = 变量的值
// 数组类型
int sum = 0;
int[] nums; // 1.整型数组定义
nums = new int[10]; // 定义了一个大小为10的数组,可以存放10个int类型的数据

// 给数组元素赋值
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
nums[3] = 4;
nums[4] = 4;
nums[5] = 5;
nums[6] = 6;
nums[7] = 7;
nums[8] = 8;
nums[9] = 9;

// 计算所有元素的和
for(int x : nums){
sum += x;
}
System.out.println(sum);


}
}

数组特点

  • 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
  • 其元素必须是相同类型不允许出现混合类型。
  • 数组中的元素可以是任何数据类型,包括基本类型和引副用类型。
  • 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
  • 数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。

三种初始化及内存分析

内存分析

JVM内存分析图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.everweekup.Array;

public class ArrayDemo1 {
public static void main(String[] args) {
// 变量类型 变量的名字 = 变量的值
// 数组类型
int sum = 0;
int[] nums; // 1.整型数组定义
nums = new int[10]; // 定义了一个大小为10的数组,可以存放10个int类型的数据

// 给数组元素赋值
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
nums[3] = 4;
nums[4] = 4;
nums[5] = 5;
nums[6] = 6;
nums[7] = 7;
nums[8] = 8;
nums[9] = 9;


// 计算所有元素的和
for(int x : nums){
sum += x;
}
System.out.println(sum);


}
}

对以上代码片段在内存中的执行作图如下:

如果访问数组超过数组的界限会报错:java.lang.ArrayIndexOutOfBoundsException:

三种初始化

1
2
3
4
5
// 静态初始化 创建+赋值
int[] a = {1, 2, 3, 4, 5, 6};

// 动态初始化 :包含默认初始化
int[] b = new int[10];
  • 数组的默认初始化
    • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化(比如说创建整型数组,如果数组没被赋值,那它的每个元素默认值为0)

数组特点

  • 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
  • 其元素必须是相同类型不允许出现混合类型。
  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
  • 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量
  • 数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的

数组边界

数组下标的合法区间:[0, length-1],如果越界就会报错;

小结

  • 数组是相同数据类型(数据类型可以为任意类型)的有序集合
  • 数组也是对象。数组元素相当于对象的成员变量
  • 数组长度的确定的,不可变的。如果越界,则报: ArrayindexoutofBounds

数组使用

1
2
3
4
5
6
public class Demo03 {
public static void main(String[] args) {
int[] arrays = {1, 2, 3, 4, 5, 6};

int[] reverse = reverseArray(arrays);
}

普通For循环&数组作为方法入参

1
2
3
4
5
6
// 数组作为方法入参
public static void printArray(int[] array){
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}
}

For-Each循环

1
2
3
4
5
6
// 数组作为方法入参
public static void printArray(int[] array){
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}
}

数组作返回值

1
2
3
4
5
6
7
8
// 反转数组 数组作为返回值
public static int[] reverseArray(int[] array){
int[] result = new int[array.length];

for(int i = 0, j=(array.length-1); i < array.length; i++, j--){
result[i] = array[i];
}
return result;

多维数组

多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。

二维数组

1
2
3
4
5
6
7
8
package com.everweekup.Array;

public class MultiplicationArray {
public static void main(String[] args) {
int[][] a = new int[2][3]; // 两行四列的数组
System.out.println(a[0]); //[I@1b6d3586 是一个数组对象的内存地址
}
}

画图理解如下:

二维数组图解

以此类推,多维数组得逻辑也可以这么理解和实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.everweekup.Array;

public class MultiplicationArray {
public static void main(String[] args) {
// int[][] a = new int[2][4];
int[][] a = {{1,2},{3,4},{5,6}};
// 增强型for循环遍历元素
for (int[] ints : a) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
// 普通for循环
for(int i = 0; i<a.length; i++){
for(int j = 0; j<a[i].length; j++){
System.out.print(a[i][j]+"\t");
}
System.out.println();
}
}
}

Arrays类

java.util.Arrays是数组的工具类,由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类 Arrays供我们使用,从而可以对数据对象进行一些基本的操作。

Arrays类中的方法都是 static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而”不用”使用对象来调用(注意:是”不用”而不是”不能”)

该工具类常用功能有:

  • 给数组赋值:通过fill方法。
  • 对数组排序:通过sort方法按升序。
  • 比较数组:通过 equals方法比较数组中元素值是否相等。
  • 查找数组元素:通过 binarySearch方法能对排序好的数组进行二分查找法操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.everweekup.Array;

import java.util.Arrays;

public class ArraysDemo {
public static void main(String[] args) {
int[] a = {1, 5, 77, 8909, 4456, 2, 34, 78, 345, 6};
System.out.println(a); //[I@1b6d3586
// 用arrays类方法打印数组
System.out.println(Arrays.toString(a)); //[1, 5, 77, 8909, 4456, 2, 34, 78, 345, 6]
// 自己写一个类似toString的方法
// printArray(a); //[1, 5, 77, 8909, 4456, 2, 34, 78, 345, 6]
// 对数组排序
Arrays.sort(a);
System.out.println(Arrays.toString(a)); //[1, 2, 5, 6, 34, 77, 78, 345, 4456, 8909]

// 数组填充
Arrays.fill(a, 2,4,0);// 数组中下标2到4间的元素填充为0 | [1, 2, 0, 0, 34, 77, 78, 345, 4456, 8909]
System.out.println(Arrays.toString(a));

Arrays.fill(a, 0);// 全部填充为0
System.out.println(Arrays.toString(a)); //[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]




}
public static void printArray(int[] array){
for(int i = 0; i<array.length; i++){
if(i == 0){
System.out.print("["+array[i]+", ");
}else if(i == (array.length - 1)){
System.out.print(array[i]+"]");
}else{
System.out.print(array[i]+", ");
}
}
}
}

冒泡排序

冒泡排序是八大排序算法中最为经典的一个,其代码逻辑相当简单,两层循环,外层冒泡轮数,里层依次比较,时间复杂度是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.everweekup.Array;

import java.util.Arrays;

public class BubbleSort {
public static void main(String[] args) {
int[] a = {1, 4, 5, 56, 78, 33, 78, 89, 30};
// 冒泡排序 嵌套循环:时间复杂度O(n)
sortBuble(a);
System.out.println(Arrays.toString(a));
}

/*
冒泡排序
1.比较数组中相邻的两个元素,如果第一个元素比第二个大,我们就交换两个元素的位置;
2.每次比较都会产生一个最大的数,这样每一轮比较都会比上一轮少一次比较,因为上一轮已经选出了最大的数,这一轮就没必要和最大的数比较;
3.依次循环,直到结束;
*/
public static void sortBuble(int[] array){
// 临时变量
int temp = 0;

// 外层循环,判断要走多少次
// n个数比大小,我们只需要比较n-1次
for (int i = 0; i < (array.length-1); i++) {
// 内层循环
// 优化--无需对有序数组进行排序
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;
}
}
}
}

稀疏数组

介绍

当一个数组中大部分元素为0,或者为同一值的数组时(即大量无用的数据占据了过多的空间),可以使用稀疏数组来保存该数组。

稀硫数组的处理方式是:

  • 记录数组一共有几行几列,有多少个不同值
  • 把具有不同值的元素和行列及值记录在一个小规模的数组中,第一行用于记录原数组的维度和有效元素个数。借此缩小程序的规模。

如下图:左边是原始数组,右边是稀疏数组

稀疏数组在日常中的运用较为常见,比如说编写五子棋游戏,存盘和续上盘的功能。

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package com.everweekup.Array;

public class SparseArray {
public static void main(String[] args) {
// 1.创建二维数组,0代表没有棋子,1代表黑棋,2代白哦白棋
int[][] array = new int[11][11];
array[1][2] = 1;
array[2][3] = 2;
// 输出原始数组
System.out.println("输出原始数组:");

for (int[] ints : array) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}

System.out.println("===========================");
// 转换为稀疏数组保存
// 获取有效值个数
int sum = 0;
for (int[] ints : array) {
for (int anInt : ints) {
if(anInt != 0){
sum++;
}
}
}
System.out.println("有效值个数: "+sum);
// 有效值个数+1代表稀疏数组的行数,3列固定是行,列,值
int sparseArray[][] = new int[sum+1][3];
sparseArray[0][0] = array.length;
sparseArray[0][1] = array[0].length;
sparseArray[0][2] = sum;

// 遍历二维数组,将非零的值存放在稀疏数组
int count = 0;
for (int i = 0; i<array.length; i++){
for (int j = 0; j<array[i].length; j++){
if (array[i][j] != 0){
count++;
// 存放有值的行
sparseArray[count][0] = i;
// 存放值得列
sparseArray[count][1] = j;
// 存放值
sparseArray[count][2] = array[i][j];
}
}
}
// 输出稀疏数组
System.out.println("输出稀疏数组: ");
for (int[] ints : sparseArray) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}

System.out.println("读取稀疏数组还原: ");

int[][] array3 = new int[sparseArray[0][0]][sparseArray[0][1]];

for (int i = 1; i<sparseArray.length; i++){
array3[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}

for (int[] ints : array3) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}


}
}