【Java】数组详解

目录

前言:为什么需要数组

一、一维数组

1、一维数组的初始化

(1)动态初始化1

 (2)动态初始化2

(3)静态初始化

2、一维数组的使用

3、案例演示

二、二维数组

1、二维数组的初始化

(1)动态初始化1

 (2)动态初始化2

(3)动态初始化3-列数不确定

(4)静态初始化

2、案例演示

3、使用细节及注意事项

三、数组赋值机制

1、基本数据类型与引用数据类型

(1)基本分类

(2)两者区别

2、数组赋值机制

四、数组的一些操作

1、数组拷贝

2、数组反转

3、数组扩容

4、数组排序

(1)排序的基本介绍

(2)冒泡排序

5、数组查找


前言:为什么需要数组

我们在编写程序处理的对象有时数量会非常多,例如统计一个班的数学成绩,或是统计一个班学生的身高,如果再和之前的方法一样一条语句定义一个变量,那代码就会显得非常冗长,可读性差,因此,为了解决大量的变量带来的麻烦,数组就诞生了。它能够存放规定的数据元素的个数,但是需要注意的是这些数据元素必须是类型一致。


一、一维数组

数组可以存放多个同一类型的数据,数组也是一种数据类型,不过,它是引用类型。

1、一维数组的初始化

对于数组的初始化其共有三种形式,包括两种动态初始化及一种静态初始化

(1)动态初始化1

数据类型  数组名[] = new 数据类型[大小]

数据类型[]  数组名 = new 数据类型[大小]

int  a[] = new int[5]  —> 创建了一个数组,可存放5个int类型,名字为a

int[]  a = new int[5]

内存说明如下图:

 (2)动态初始化2

动态初始化方式二只是把动态初始化方式一进行了拆分

先声明后创建

int a[];

a = new a[5];

对于动态初始化来说,其与C语言有些区别,其需要进行new int[5]操作,该操作开辟一个存放5个int类型大小的数组。

(3)静态初始化

数据类型 数组名[] = {元素值,元素值...}

int a[ ] = {2,5,6,6,87,2,1}

如果知道数组有多少元素,那么就可以使用静态初始化。

上面的用法等同于:

int a[ ] = new int[7];

a[0] = 2; a[1] = 5; a[2] = 6; a[3] = 6;

a[4] = 87; a[5] = 2; a[6] = 1;

2、一维数组的使用

我们将元素存入数组中,那么我们该如何取出元素呢?— 使用数组下标。

比如你要取出上述a数组的第三个元素:a[2]。数组的下标是从0开始的,即第一个元素的下标为0。Java为我们提供了直接获得数组元素个数的方法:数组名.length,那么数组中最后一个元素的下标为:a[a.length-1]。

一些使用细节总结:

  • 数组是多个相同类型数据的组合, 实现对这些数据的统一管理
  • 数组中的元素可以是任何数据类型, 包括基本类型和引用类型, 但是不能混用。
  • 数组创建后, 如果没有赋值, 有默认值
    int: 0,short: 0,byte: 0,long: 0,float: 0.0,double: 0.0,char: \u0000,boolean: false,String: null
  • 使用数组的步骤 1. 声明数组并开辟空间 2. 给数组各个元素赋值 3. 使用数组
  • 数组的下标是从 0 开始的
  • 数组下标必须在指定范围内使用, 否则报: 下标越界异常
  • 数组属引用类型, 数组型数据是对象(object)

3、案例演示

【案例一】创建一个 char 类型的 26 个元素的数组, 分别 放置'A'-'Z'。 使用 for 循环访问所有元素并打印出来

public class ArrayExercise {
    public static void main(String[] args) {
        char[] chars = new char[26];
        for( int i = 0; i < chars.length; i++) {//循环 26 次
            chars[i] = (char)('A' + i); //'A' + i 是 int , 需要强制转换
        }
        //循环输出
        System.out.println("===chars 数组===");
        for( int i = 0; i < chars.length; i++) {//循环 26 次
            System.out.print(chars[i] + " ");
        }
    }
}

思路分析:定义一个数组放入26个字母。因为可以通过‘A’+i来推出其他字母,那么可以通过for循环来对其进行赋值。并通过for循环进行打印。

【案例二】求出一个数组 int[]的最大值 {4,-1,9, 10,23}, 并得到对应的下标

public class ArrayExercise {
    public static void String [] args) {
        int[] arr = {4,-1,9,10,23};
        int max = arr[0];//假定第一个元素就是最大值
        int maxIndex = 0; //假设最大值下标为0
        
        for(int i = 1; i < arr.length; i++) {//从下标 1 开始遍历 arr
            if(max < arr[i]) {//如果 max < 当前元素
                max = arr[i]; //把 max 设置成 当前元素
                maxIndex = i;
            }
        }
        System.out.println("max=" + max + " maxIndex=" + maxIndex);
    }
}

思路分析:定义并初始化该数组,假定 max = arr[0] 是最大值,那么最大值下标为0。从下标1开始遍历 arr, 如果 max < 当前元素,则更新最大值以及最大值下标(max = 当前元素; maxIndex = 当前元素下标),直到遍历完整个数组。


二、二维数组

二维数组的应用也非常广泛,比如开发一个五子棋游戏,棋盘就需要二维数组来表示。

1、二维数组的初始化

(1)动态初始化1

类型[][] 数组名 = new 类型[大小][大小]
int[][] a = new int[2][3]

内存说明如下图:

 (2)动态初始化2

先声明: 类型 数组名[][]; 
再定义(开辟空间) 数组名 = new 类型[大小][大小]
赋值(有默认值,比如 int 类型的就是 0)

int arr[][];

arr = new int[3][2];

(3)动态初始化3-列数不确定

我们在进行二维数组初始化的时候可以省略列。例如:int arr[][] = new int[3][];

完成对下图二维数组的创建:

 创建一个二维数组,有3个一维数组,但是每个一维数组还没有开辟数据空间,通过上图可以发现:第i行的一维数组需要开辟i+1个空间,代码如下:

public class TwoDimensionalArray {
    public static void main(String[] args) {
        int[][] arr = new int[3][];
        for(int i = 0; i < arr.length; i++) {//遍历 arr 每个一维数组
            //给每个一维数组开空间 new
            //如果没有给一维数组 new ,那么 arr[i]就是 null
            arr[i] = new int[i + 1];
            //遍历一维数组, 并给一维数组的每个元素赋值
            for(int j = 0; j < arr[i].length; j++) {
                arr[i][j] = i + 1;//赋值
            }
        }

        //遍历 arr 输出
        for(int i = 0; i < arr.length; i++) {
            //输出 arr 的每个一维数组
            for(int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + " ");
            } 
            System.out.println();//换行
        }
    }
}

(4)静态初始化

定义 类型 数组名[][] = { {值 1,值 2..},{值 1,值 2..},{值 1,值 2..} }
使用即可 [ 固定方式访问 ]

int[][] arr = { {1,2,3}, {4,1,5}, {7,5,7} }

2、案例演示

【案例一】使用二维数组打印一个 10 行杨辉三角

public class YangHui {
    public static void main(String[] args) {
        int[][] yangHui = new int[12][];
        for(int i = 0; i < yangHui.length; i++) {//遍历 yangHui 的每个元素
            //给每个一维数组(行) 开空间
            yangHui[i] = new int[i+1];
            //给每个一维数组(行) 赋值
            for(int j = 0; j < yangHui[i].length; j++){
                //每一行的第一个元素和最后一个元素都是 1
                if(j == 0 || j == yangHui[i].length - 1) {
                    yangHui[i][j] = 1;
                } else {//中间的元素
                    yangHui[i][j] = yangHui[i-1][j] + yangHui[i-1][j-1];
                }
            }
        }
        //输出杨辉三角
        for(int i = 0; i < yangHui.length; i++) {
            for(int j = 0; j < yangHui[i].length; j++) {//遍历输出该行
                System.out.print(yangHui[i][j] + "\t");
            } 
            System.out.println();//换行.
        }
    }
}

杨辉三角规律: 

  • 第一行有1个元素,第n行有n个元素;
  • 每一行的第一个元素和最后一个元素都是1
  • 从第三行开始,对于非第一个元素arr[i][j] = arr[i-1][j] + arr[i-1][j-1]

3、使用细节及注意事项

  • 二维数组的声明方式有:int[][] y 或者 int[] y[] 或者 int y[][]
  • 二维数组实际上是由多个一维数组组成的, 它的各个一维数组的长度可以相同, 也可以不相同。 比如:arr[][] 是一个二维数组int arr[][] = {{1,2},{3,4,5}},arr[0] 是一个含有两个元素的一维数组 ,arr[1] 是一个含有三个元素的一维数组构成, 我们也称为列数不等的二维数组

三、数组赋值机制

在学习数组的赋值机制之前,我们先来分清楚什么是基本数据类型和引用数据类型

1、基本数据类型与引用数据类型

(1)基本分类

基本数据类型有以下几种:

  • 整数类型:long、int、short、byte;

  • 浮点类型:float、double:

  • 字符类型:char,因为Java在内存中总是使用Unicode表示字符,所以,一个英文字符和一个中文字符都用一个char类型表示,它们都占用两个字节;

  • 布尔类型:boolean

引用数据类型有以下几种:

  • 类、接口、数组、枚举、注解、字符串等…

(2)两者区别

对于基本数据来说:

在方法中定义的非全局基本数据类型变量的具体内容是存储在中的。

在方法中定义的非全局基本数据类型变量,调用方法时作为参数是按数值传递

默认值:0

对于引用数据来说:

只要是引用数据类型变量,其具体内容都是存放在堆中的,而栈中存放的是其具体内容所在内存的地址。

引用数据类型变量,调用方法时作为参数是按引用(地址)传递的,传递的是引用的副本

默认值:null

2、数组赋值机制

数组在默认情况下是引用传递,赋的值是地址

通过下面这段代码来讲述数组的赋值机制以及值传递与引用传递的区别

int n1 = 10;
int n2 = n1;

n2 = 80;
System.out.println("n1=" + n1);
System.out.println("n2=" + n2);

int[] arr1 = {1, 2, 3};
int[] arr2 = arr1;
arr2[0] = 10;


四、数组的一些操作

1、数组拷贝

要求:

数组拷贝:要求将一个数组的值拷贝到另外一个数组,且数据空间是独立的。

思路:

新开辟一个空间给一个新的数组,并将原数组相应位置的值赋给新数组即可

代码:

public class ArrayCopy {
    //编写一个main方法
    public static void main(String[] args) {

        int[] arr1 = {10,20,30};

        //创建一个新的数组arr2,开辟新的数据空间
        //大小 arr1.length;
        int[] arr2 = new int[arr1.length];

        //遍历 arr1 ,把每个元素拷贝到arr2对应的元素位置
        for (int i = 0; i < arr1.length; i++) {
            arr2[i] = arr1[i];
        }

        //输出
        System.out.println("====arr1的元素====");
        for(int i = 0; i < arr1.length; i++) {
            System.out.print(arr1[i] + " ");//10,20,30
        }
        System.out.println("====arr2的元素====");
        for(int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i] + " ");//
        }
    }
}

2、数组反转

要求:

将数组内容反转

思路:

方法一:使用元素交换,第一个元素与最后一个元素交换,第二个元素与倒数第二个元素交换,以此类推,共交换(arr.length / 2)次。而每次交换时对应交换的元素为:arr[i] 和 arr[arr.length-1-i]

方法二:先创建一个新的数组 arr2,大小 为arr.length,逆序遍历 arr,将每个元素拷贝到 arr2 的元素中(顺序拷贝)

代码:

//思路一
public class ArrayReverse {
    public static void main(String[] args) {
        int[] arr = {11, 22, 33, 44, 55, 66, 77};

        int tmp = 0; //中间数
        for (int i = 0; i < arr.length / 2; i++) {
            tmp = arr[arr.length - 1 - i];
            arr[arr.length - 1 - i] = arr[i];
            arr[i] = tmp;
        }

        //输出
        System.out.println("===翻转后的数组为===");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}
//方法二
public class ArrayReverse02 {
    public static void main(String[] args) {
        int[] arr = {11, 22, 33, 44, 55, 66};
        int[] arr2 = new int[arr.length];

        for (int i = arr.length - 1, j = 0; i >= 0; i--, j++) {
            arr2[j] = arr[i];
        }

        arr = arr2;
        //让 arr 指向 arr2数据空间, 此时 arr原来的数据空间就没有变量引用会被当做垃圾销毁

        System.out.println("===翻转后数组元素===");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

3、数组扩容

要求:

实现动态的给数组添加元素,实现对数组扩容

1) 原始数组使用静态分配 int[] arr = {1,2,3}
2) 增加的元素 4, 直接放在数组的最后 arr = {1,2,3,4}
3) 用户可以通过如下方法来决定是否继续添加, 添加成功, 是否继续? y/n

思路:

定义一个初始数组 int[] arr = {1,2,3},再定义一个新的数组 int[] arrNew = new int[arr.length+1];遍历 arr 数组,依次将 arr 的元素拷贝到 arrNew 数组。然后把要添加的元素(例如4)赋给arrNew的最后一个元素 arrNew[arrNew.length - 1] = 4;再让 arr 指向 arrNew ; arr = arrNew; 那么 原来 arr 数组就被销毁。                                                                                                                                      创建一个Scanner可以接受用户输入。

代码:

import java.util.Scanner;

public class ArrayAdd {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        Scanner scanner = new Scanner(System.in);

        do {
            int[] arrNew = new int[arr.length + 1];
            for (int i = 0; i < arr.length; i++) {
                arrNew[i] = arr[i];
            }
            System.out.print("请输入添加的元素:>");
            int addNum = scanner.nextInt();
            arrNew[arrNew.length-1] = addNum;
            arr = arrNew;

            System.out.println("===扩容后情况为===");
            for (int i = 0; i < arr.length; i++) {
                System.out.print(arr[i] + " ");
            }

            //是否继续添加
            System.out.print("\n是否继续添加(y/n):>");
            char key = scanner.next().charAt(0);
            if(key == 'n') {
                break;
            }
        }while (true);
        System.out.println("你退出了添加...");
    }
}

上面这段代码还存在着一点小问题:当你输入除了‘n’字符以外的其他字符,它也会继续字符的添加。

4、数组排序

(1)排序的基本介绍

排序是将多个数据, 依指定的顺序进行排列的过程。

分类:

  • 内部排序:

指将需要处理的所有数据都加载到内部存储器中进行排序。 包括:交换式排序法、选择
式排序法和插入式排序法

  • 外部排序:

数据量过大, 无法全部加载到内存中, 需要借助外部存储进行排序。 包括:合并排序法和直接合并排序法
 

(2)冒泡排序

要求:

五个无序数字:24,69,80,57,13  使用冒泡排序法将其排成一个从小到大的有序数列。

思路:

 通过上述过程我们可以总结如下规律:

  • 假设我们排序的元素个数为N
  • 一个需要进行N-1轮排序(当排序完倒数第二个数之后,最后一个数自动排好),可看成外层循环。
  • 每一轮的排序都可以确定一个数的位置,例如第一轮可以确定最大的数,第二轮可以确定第二大的数,依此类推。
  • 当我们发现前一个数比后一个数大时我们就交换(从小到大排序的情况下)
  • 每一轮的比较次数再有规律地减少:第N轮比较次数为: arr.length - N

代码:

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {24, 69, 80, 57, 13};
        int tmp = 0;

        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if(arr[j] > arr[j+1]) {
                    tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
        }

        //输出
        System.out.println("===排序完的数组为===");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

5、数组查找

在Java中,常用的查找有两种:顺序查找与二分查找。这里只介绍简单的顺序查找

要求:

有一个数列:11,22,33,44,55,猜数游戏: 从键盘中任意输入一个名称, 判断数列中是否包含此名称【顺序查找】 要求: 如果找到了, 就提示找到, 并给出下标值。

思路:

定义一个数组,并遍历数组,逐一比较,如果有则输出提示信息。

代码:

import java.util.Scanner;

public class SeqSearch {
    public static void main(String[] args) {
        int[] arr = {11,22,33,44,55};
        int index = -1;
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入查找的数:>");
        int num = scanner.nextInt();

        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == num) {
                index = i;
                System.out.println("查找成功,其下标为:" + index );
            }
        }
        if(index == -1) {
            System.out.println("查找失败...");
        }

    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值