首先思考一个问题,我们这么多人是如何整理在一起上课的?
分了班级?对不对。所以我们一大帮子人进行集中、整理、放置在一起,就形成了一个“班级”。那么当出现了很多的数据呢?
数据,也可以像我们每一个人一样,集中合并放置在一起,进行批量存储和操作。数组就是集合当中最原始最简单的一种。
在 java 中,数组的特点在于:
- 只能存放同一数据类型的数据
- 所有元素数据存放在连续内存空间
- 数组空间大小一旦确定,不可更改
这三个特点也是 java 中数组的缺点,但由于数组的不可被修改性,后面我们还会学习其他的数据结构。
声明方式
声明方式存在两种
- 明确数据情况
- 未知具体数据情况,仅知道元素个数
明确数据情况
这种声明方式适合于明确数组中数据的值。
语法:元素类型 [] 数组名称 = {数据1, 数据2, ... 数据n};
```java // 表示内存中开辟了一块空间用于存储 5 个整数 int [] numbers = {1, 2, 3, 4, 5};
// 表示内存中开辟了一块空间用于存储 3 个浮点数,56 也会被存储为 56.0 double [] rainFall = {12.3, 78.4, 56};
// 表示内存中开辟了一块空间用于存储 4 个字符串 String[] users = {“zhangsan”, “lisi”, “wangwu”, “zhaoliu”};
对于数组(变量)名 numbers、rainFall、users 都是一个引用,指向了内存中的地址,以便我们对数组进行操作。
<a name="YoeEg"></a>
### 未知数据情况
这种方式适用于不确定数组中值,只明确存放的个数。<br />语法:`数据类型 [] 数组名称 = new 数据类型[数组长度];`
```java
// 声明了一个名为 numbers 长度为 8 的数组,用于未来存放整数
int [] numbers = new int[8];
// 声明了一个名为 rainFall 长度为 10 的数组,用于未来存放小数
double[] rainFall = new double[10];
存放方式
当书写完数组的声明后,它在内存中的存放方式实际上是一个引用,通过变量名字 “numbers”、“rainFall”、“users” 指向了一块内存地址。
像之前我们书写的 int a = 5;
,char c = 'c';
5 和字符 c 都是属于基本数据类型,对吧?基本数据类型的变量空间中存放的是值本身,引用类型的变量空间中存放的是引用,该引用指向真正的数据。
总结下来就是:
- 基本数据类型的变量空间中存放的是值本身
- 引用类型的变量空间中存放的是引用,该引用指向真正的数据
默认初始化值
在对于第二种只明确个数的声明方式int[] numbers = new int[8]
每个元素会默认初始化为 0。
- 若元素是基本数据类型,赋值初始化为 0
- int 类型,各元素初始化为 0
- double/float 类型,各元素初始化为 0.0
- char 类型,各元素初始化为 ASCII 码为 0 的字符(一个空字符)
- boolean 类型,各元素初始化为 false
- 若元素为引用数据类型,赋值初始值为 null
int [] numbers = new int[10]; // 访问 numbers[0] 得到 0
double [] rainFall = new double[5]; // 访问 rainFall[0] 得到 0.0
String[] names = new String[5];// 访问 names[0] 得到 null
操作数组中的元素
数组中的元素通过数组名[下标]
进行操作。下标相当于元素在数组中的编号,下标从 0 开始,最大下标为数组长度减1。
若下标不在范围,会报异常:ArrayIndexOutOfBoundsException
即(数组下标越界异常)。数组有一个length
属性用来代表数组的长度,可以避免数据访问时越界。 ```java int numbers[] = {1, 2, 3, 4, 5}; System.out.println(numbers[886]); // ArrayIndexOutOfBoundsException: Index 886 out of bounds for length 5
System.out.println(numbers.length); // 5
<a name="ILXad"></a>
## 遍历数组
遍历数组就是指依次拿到数组中的每一个元素,进行相应的操作。我们已知数组下标从 0 开始,所以可以使用循环取得数组中每一项。
```java
for(int i = 0; i < arr.length; i++){
// 相应操作
}
数组的拷贝
我们已经得知数组是属于引用类型的,数组变量名只是一个引用:
int arr1[] = {1, 2, 3};
int arr2[] = arr1; // arr1 和 arr2 指向了同一块内存空间
arr1[0] = 886; // 其中一个被改变
System.out.println(arr2[0]); // 另一个也同时被改变
为了使两块内存空间独立开来,就需要对“数据”进行拷贝。尝试对 int arr[] = {1, 2, 3};
进行拷贝。
排序
对集合中元素进行排序也是非常常用基本操作。排序的方式有很多,冒泡、选择、自然等等,语言自带了排序方法,对于手写排序,主要掌握冒泡或者选择排序。
/*
选择排序
数组中一个数和后面所有数字一一比较
*/
int arr[] = {3, 15, 6, 2, 8, 19};
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
/*
冒泡排序
数组中的数字两两比较
*/
for (int count = 1; count < arr.length; count++) {
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}