第五章 数组
5.1 数组概要
- 数组是一种引用类型,内存的示意图:

- 数组是一组数据的集合
- 数组作为引用类型
- 数组中的元素可以是"基本类型",也可以是"引用类型",但是,必须是同一种类型
- 数组的长度(元素的个数)是一个属性表示的,length表示的就是长度
- 数组的长度一旦确定后,就无法修改了
- 数组中的元素是有下标的,并且从0开始,最大的下标值是length-1
5.2 一维数组的创建和使用
5.2.1 创建一维数组
5.2.1.1 第一种(推荐):int[] arr = new int[2];
5.2.1.2 第二种:int arr[] = new int[2];
5.2.1.3 动态创建数组和静态创建数组
5.2.1.3.1 动态创建数组
- 动态创建数组:默认在堆中开辟了3个位置并且,默认元素的值就是该类型的默认值


- 可以在实际开发中按照下标添加对应的数据元素

- 可以通过循环的方式获取元素
- 案例1:
public class A {
public static void main(String[] args) {
//动态创建数组
String[] arr = new String[3];
//按照下标
arr[0] = "a";
arr[1] = "b";
arr[2] = "c";
//循环获取元素值
for (int index = 0; index < arr.length; index++) {
System.out.println(arr[index]);
}
}
}
- [null]
- 案例2:不关心元素的下标
public class A {
public static void main(String[] args) {
//动态创建数组
String[] arr = new String[3];
//按照下标
arr[0] = "a";
arr[1] = "b";
arr[2] = "c";
//循环获取元素值
for (String element : arr) {
System.out.println(element);
}
}
}
- [null]
- 案例3:lambda函数的方式
public class A {
public static void main(String[] args) {
//动态创建数组
String[] arr = new String[3];
//按照下标
arr[0] = "a";
arr[1] = "b";
arr[2] = "c";
//循环获取元素值
Arrays.stream(arr).forEach(System.out::println);
}
}
- 必须注意元素的下标,因为,会出现一个运行期的异常:下标越界

5.2.1.3.2 静态创建数组
- 就是初始化的时候就是把数组中的元素有默认值添加为指定的数值了
public class A {
public static void main(String[] args) {
//静态创建数组
int[] array = {1,2,3,4,5};
//输出
for (int index = 0; index < array.length; index++) {
System.out.println(array[index]);
}
}
}
import java.util.Arrays;
public class A {
public static void main(String[] args) {
//静态创建数组
String[] array = {"女","足","牛"};
//输出
Arrays.stream(array).forEach(System.out::println);
}
}
5.3 二维数组的创建和使用
- 二维数组就是两个一维数组
5.3.1 声明方式:
- 在类型的后面添加中括号
public class A {
public static void main(String[] args) {
int[][] array = new int[2][3];
}
}
- 在参数的后面添加中括号
public class A {
public static void main(String[] args) {
int array[][] = new int[2][3];
}
}
- 扩展
public class A {
public static void main(String[] args) {
int[] array[] = new int[2][3];
}
}
5.3.2 动态创建二维数组


5.3.3 循环获取元素
public class A {
public static void main(String[] args) {
//动态创建二维数组:2行3列
int[] array[] = new int[2][3];
//添加元素
array[0][0] = 1;
array[0][1] = 2;
array[0][2] = 3;
array[1][0] = 4;
array[1][1] = 5;
array[1][2] = 6;
//通过嵌套循环获取元素
for (int rows = 0; rows < array.length; rows++) {
for (int cols=0;cols<array[rows].length;cols++){
System.out.println("array["+rows+"]["+cols+"]="+array[rows][cols]);
}
}
}
}
5.3.4 高维创建二维数组
5.3.4.1 静态方式创建
public class A {
public static void main(String[] args) {
int[][] array = {{1}, {2,3}, {4,5,6}};
//遍历
for (int rows = 0; rows < array.length; rows++){
for (int cols = 0;cols < array[rows].length; cols++){
System.out.println("array["+rows+"]["+cols+"]="+array[rows][cols]);
}
}
}
}
5.3.4.2 动态方式创建
public class A {
public static void main(String[] args) {
//高位创建,可以不确定列数
int[][] array = new int[3][];
//在使用元素时,必须创建出来了
array[0] = new int[2];
array[0][0] = 1;
array[0][1] = 2;
array[1] = new int[3];
array[1][0] = 3;
array[1][1] = 4;
array[1][2] = 5;
array[2] = new int[1];
array[2][0] = 6;
//遍历
for (int rows = 0; rows < array.length; rows++){
for (int cols = 0;cols < array[rows].length; cols++){
System.out.println("array["+rows+"]["+cols+"]="+array[rows][cols]);
}
}
}
}

5.4 数组的排序
5.4.1 冒泡排序
- 案例:对3,1,6,2,5进行排序
- 左边和右边两个相邻的数据进行比较
- 如果右边的小于左边的数据那么进行一次交换
- 如果右边的大于左边的数据那么不进行一次交换
- 公式:
- 可以看到比较了n-1次,那么第二遍n-2,以此类推
- (n-1)+(n-2)+...=((n-1)*n)/2
- 所以对上面的数据进行排序的次数(比较次数):((5-1)*5)/2=10
- 比较的次数称为时间复杂度(10),临时使用的变量称为空间复杂度(1)
第一遍比较的示意图

- 冒泡排序编码案例
public class A {
public static void main(String[] args) {
//创建数组
int[] array = {3,1,6,2,5};
//循环比较
for (int i = array.length - 1; i > 0; i--) {
for (int j=0;j<i;j++){
//判断
if (array[j]>array[j+1]){
//必须使用一个临时变量保存一个j位置的元素
int temp = array[j];
//交换位置
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
//输出排序后的元素
for (int index = 0; index < array.length; index++) {
System.out.println(array[index]);
}
}
}
5.4.2 选择排序
- 选择排序对冒泡排序进行改进:使交换次数减少了,但是,比较的次数没有减少
- 原理:找到一个元素后依次与后面的元素比较,找到最小的元素放到前面

- 案例代码
public class A {
public static void main(String[] args) {
//创建数组
int[] array = {3,10,6,2,5,1};
//循环比较:选择排序的方式
for (int i = 0; i < array.length; i++) {
//设置一个最小的下标值,获取该元素
int min = i;
//循环获取最小的元素
for (int j=i+1;j< array.length;j++){
//判断比较的结果
if (array[i]<array[min]) {
//更换最小的元素对应的下标
min = j;
}
}
//找到最小的元素后交换位置
if (min!=i){
int temp = array[i];
array[i] = array[min];
array[min] = temp;
}
}
//输出排序后的元素
for (int index = 0; index < array.length; index++) {
System.out.println(array[index]);
}
}
}
5.5 数组的搜索方式
5.5.1 二分法(折半法)
- 在使用二分法时,数组必须已经排序了

- 就是把最小下标+最大下标求和后除2,就可以判断需要的数据是在前一半还是后一半
- 案例代码:
public class A {
public static void main(String[] args) {
//创建数组
int[] array = {11,12,13,14,15,16,17,18,19,20};
//使用折半方法
int index = binarySearch(array, 19);
System.out.println(index);
}
//需要编写一个折半查找数据的方法:获取下标的值
public static int binarySearch(int[] array,int value){
//开始的下标
int begin = 0;
//结束的下标
int end = array.length-1;
//循环
while (begin <= end) {
//折半
int mid = (begin+end)/2;
//判断
if (value==array[mid]) {
return mid;
}else if (value>array[mid]){
//开始的下标是有变化的
begin = mid+1;
}else if (value<array[mid]){
end = mid-1;
}
}
return -1;
}
}
5.5.2 笔试题
- 10万瓶水,其中有一瓶有毒,现在给你10只小强(蟑螂),如果小强喝了有毒的水后3秒死亡,问如何找到这瓶水?
- 答:使用折半+推算
5.6 Arrays工具类
5.6.1 通过工具类对数组进行排序
import java.util.Arrays;
public class A {
public static void main(String[] args) {
//创建数组
int[] array = {3,1,6,2,5};
//工具类对数组排序
Arrays.sort(array);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
5.6.2 使用工具类对数组进行二分法
import java.util.Arrays;
public class A {
public static void main(String[] args) {
//创建数组
int[] array = {11,12,13,14,15,16,17,18,19,20};
//查找元素对应的下标
int index = Arrays.binarySearch(array, 20);
System.out.println(index);
}
}