数组
数组
1 数组的定义和读写
1.1 什么是数组
 我们之前学习的变量只能保存一个数据,而数组可以存储一组数据,如果我们把变量当成一个数据点,那么数组就是一个数据线(这个线是有多个连续的数据点构成的),二维数组可以构成数据平面,我们在开学初其实还学习了数据立方体——数据库,可以存储各种类型的数据多维度互相关联。
 为了方便学习,咱们约定现在讨论的数组如果不特别指明,指的就是一维数组,二维数组大家作
为选学即可。 什么是数组呢? java 的数组是由相同数据类型的一组数据组成的连续存储的结构。

上图是几个数组的示例
1.2定义数组
数组的定义有以下三种
- 定义空间的方式:数组类型[] 变量名称 = new 数据类型[长度];
 - 初始化方式:数据类型[] 变量名称 = {值0,值1,值2,······,值N};
 - 完整写法:数据类型[] 变量名称 = new 数据类型[]{值0,值1,值2,······,值N};
 
示例:
int[] arr = new int[5];
String[] strs = {"张三","李四","王五"};
double[] scores = new double[] { 90, 88, 78, 90, 86, 95, 98, 72 };
    首先在内存中找一块连续的内存空间(大小 20 个字节),能够放得下 5 个整数,并为每个元素赋值,默认值 0(int 类型数组,默认值 0)。
    其次,数组名 arr 里面保存了这块空间的首地址,以后我们就通过使用 arr 来进行读写操作。(正因为 arr 指向这个连续空间首地址,因而数组是引用类型)。
1.3 读写数组
对于数组使用,主要就是 “读”和“写”操作。虽然数组在定义后会有默认值,但是通常情况下,我们最好在定义完后,先进行赋值,再进行使用。
示例:
写: arr[0] = 10; strs[0]="Jim";
读: int i = arr[1];
在读写数组时,需要注意数组的长度,同样是这个数组 int[] arr = new int[5];当我们写arr[5]=3;时,一旦运行,程序就会出错;很多初学者,特别是国内用户可能会非常疑惑,这主要是因为在 java 中数组的下标是从 0 0 开始的,因而对于长度为 5 的数组 arr,最大下标就是 4,我们最多就只能访问到 arr[4]了,这点我们在 js 中也了解过。
public static void main(String[] args) {
    int[] arr = new int[5];
    arr[5] = 3;
    
}

1.4 内存存储
🤨代码 int[] arr = {16,25,9,90,23}; 在内存中是如何存储的呢?

我们发现,数组对象也是存储在内存堆中的,而 arr 中存储的是数组对象的地址。因而下边的代
码也是正确的:
int[] arr;
arr= new int[]{1,2,3};//必须用new,表示是新的地址,不用new表示地址相同则必须长
度一致
arr= new int[]{1,2,3,4,5};
2 使用一维数组
正因为数组可以一次性保存多个数据,因而其应用场景非常多。在介绍应用之前,需要首先给大家介绍一个重要的属性: length(数组中可以存储的元素的个数,我们在声明一个数组时,一般已经指明了长度)。
练习:录入班级人数并根据班级人数录入学生的成绩到一个数组中,求出平均分数。
import java.util.Scanner;
public class Demo02 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //录入班级人数并根据班级人数录入学生成绩到一个数组中
        System.out.println("请输入班级人数");
        int num = scanner.nextInt();//根据人数确定有多少个成绩
        double[] scores = new double[num];//声明一个数组,用来保存成绩
        int i = 0;
        while (i<num){
            System.out.println("请输入第"+(i+1)+"个学员的成绩");
            scores[i] = scanner.nextInt();
            i++;
        }
        //求出平均数
        double sum = 0;
        for (int j=0;j<scores.length;j++){
            sum+=scores[j];
        }
        System.out.println("平均成绩是"+(sum/ scores.length));
    }
}

2.1遍历
对于数组而言,非常普遍的一种业务是 对数组中所有元素访问一遍(我们将之称为遍历),来获取一个业务值或查找符合条件的业务值,我们学习过多种循环结构可以完成此类遍历,今天正式给大家介绍个新写法(注释中为老写法)。
public class Demo03 {
    public static void main(String[] args) {
        double[] score = {90,88,78,90,86,95,98,72};
        double sum = 0;
//        for (int j=0;j<score.length;j++){
//            sum+=score[j];
//        }
        for (double item : score){
            sum+=item;
        }
        System.out.println("平均成绩是"+sum/ score.length);
    }
}

2.2 排序
排序,是我们都不陌生的话题,当我们在网上购物时,总是会按照销量或人气进行排序,可以是升序也可以是降序。比如我们找出最好的一个
练习:学生的成绩已经存储到 scores 数组中,求出最高分。
 public static void main(String[] args) {
        double[] score = {90,88,78,90,86,95,98,72};
        //求出最大值(使用打擂台算法)
        double  max = score[0];//生命一个擂台,先让第一个元素上台
        for (int k = 1; k < score.length; k++) {
            if (score[k]>max){//比试武功
                max = score[k];//强者留在台上
            }
        }
        System.out.println("最大值为"+max);
    }

练习:现在有一组数据{16,25,9,90,23},请编程对其进行排序。
分析:我们准备采用冒泡法进行排序,冒泡法中有一个趟的概念,从前到后走一遍被称为一趟,假如对 N 个数字进行从小到大的 升序排列的话:
- 第 0 趟会得到 0 到 N-1 之间的最大值排到 N-1 的位置。
 - 第 1 趟会得到 0 到 N-2 之间的最大值排到 N-2 的位置。
 - ……
 - 第 N-2 趟会得到 0 到 1 之间的最大值排到 1 的位置。
 
这时整个数组就已经有序了。在每一趟中,如何得到一个最大值呢?答案是在一个循环中让相邻的两个进行比较,如果前者大于后者就进行交换(保证大的数字在后边),当循环结束后,本趟中的最大值就会被交换到最后了,就像一个水泡从水底向上冒一样,所以叫做冒泡排序。
public static void main(String[] args) {
    int[] arr = {90,88,78,90,86,95,98,72};
    for (int i = 0; i < arr.length; i++) {//控制趟
        for (int j = 0; j < arr.length-1-i; j++) {//每趟还要比较几次
            //比较j和它后面一位位置上的元素,前者大就交换位置,确保大的放后面
            if (arr[j]>arr[j+1]){
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    //排完序输出
    for (int i : arr){
        System.out.print(i+"\t");
    }
}

冒泡排序的口诀(升序): N 个数字来排序, 两两相比小靠前, 外层循环 N-1, 内层循环 N-1-i。
2.3 对象数组和排序
数组可以存储任何数据类型,不光可以存储上述例子中用到的基本类型的数据,也可以存储对象型数据。
练习:以下图代码中出现的矩形类为基础,创建一个存储矩形对象的数组(比如 5 个矩形对象),然后按照 面积对矩形进行冒泡排序。
距形类的代码参考如下:
public class Rect {
    double len;
    double width;
    public Rect(){}
    public Rect(double len,double width){
        this.len = len;
        this.width = width;
    }
    public double getArea(){
        return len*width;
    }
    @Override
    public String toString() {
        return String.format("矩形[长=%.2f,宽=%.2f,面积=%.2f]",
                this.len,this.width,this.getArea());
    }
}
排序的实现代码如下:
public static void main(String[] args) {
    Rect[] arr = {new Rect(10,6),new Rect(7,9),
            new Rect(3,12),new Rect(6,6),new Rect(8,7)};
    for (int i = 0; i < arr.length-1; i++) {
        for (int j = 0; j < arr.length-1-i; j++) {
            if (arr[j].getArea()>arr[j+1].getArea()){
                Rect temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    for (Rect rect : arr){
        System.out.println(rect);
    }
}

说明:上边代码中对象数组的存储内存图为:

在 java 中,数组一般都存储在 堆中,但是值类型的数组中,直接存储数据,而对象数组中,存储的是对象的地址
3 ArrayList动态数组
何谓动态数组呢?
前边学习的数组中,存储元素的个数都是固定的,还记得我们之前在 js 课程中学过的 Array 吗?灵活的不得了,有各种供我们使用的方法,那在 java 中,有没有对应的工具类呢?答案当然是有的——ArrayList,ArrayList 可以存储各种类型的数据,整数、字符串还有自定义的对象等,ArrayList的真正叫法是集合,这一点我们会在后面的课程中介绍到。
在使用 ArrayList 时,需要 import java.util.ArrayList;
下表列出了 ArrayList 中定义的一些常用方法:
| 方法名 | 说 明 | 
|---|---|
| boolean add(Object o) | 在集合的末尾添加元素,起始索引从 0 开始 | 
| void add(int index,Object o) | 在指定的索引位置添加元素,插队 | 
| 在指定的索引位置添加元素,插队 | 获得集合中的元素个数 | 
| Object get(int index) | 获得指定索引位置处的元素 | 
| void set(int index,Object obj) | 将对象 obj 放到 index 下标位置,替换 | 
| boolean contains(Object o) | 判断集合中是否已存在指定元素 | 
| boolean remove(Object o) | 从列表中删除制定元素 | 
| Object remove(int index) | 从列表中删除指定位置的元素 | 
练习:创建一个 Arraylist 集合并往里边填写数据,再循环显示,并判断里边是否包括某个数据。
public static void main(String[] args) {
    ArrayList list = new ArrayList();
    list.add(10);
    list.add(30);
    list.add(0,20);
    list.add(5);
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i)+"\t");
    }
    if (list.contains(5)){
        System.out.println("\n包含5");
    }else {
        System.out.println("\n不包含5");
    }
}

练习:使用 ArrayList 作为存储对象的集合,实现矩形面积中的冒泡排序。
public static void main(String[] args) {
    ArrayList<Rect> arr = new ArrayList<Rect>();
    arr.add(new Rect(10,6));
    arr.add(new Rect(7,9));
    arr.add(new Rect(3,12));
    arr.add(new Rect(8,7));
    for (int i = 0; i < arr.size()-1; i++) {
        for (int j = 0; j < arr.size()-1-i; j++) {
            Rect rj = arr.get(j);
            Rect rj1 = arr.get(j+1);
            if (rj.getArea()>rj1.getArea()){
                Rect temp = rj;
                arr.set(j,rj1);
                arr.set(j+1,temp);
            }
        }
    }
    for (Rect rect : arr){
        System.out.println(rect);
    }
}

4 二维数组和sort排序
4.1二维数组
练习:某次考试后,需要把 3 个学习小组所有成员的成绩都记录下来(每个小组 2~4 人不等),把每一组的人员成绩,和平均成绩都输出出来。
public static void main(String[] args) {
    double[][] score = {{80,90},{100,75,80,90},{80,85,90}};
    for (int i = 0; i < score.length; i++) {
        double sum = 0;
        System.out.println("第"+(i+1)+"组的成绩是:");
        for (int j = 0; j < score[i].length; j++) {
            System.out.print(score[i][j]+" ");
            sum+=score[i][j];
        }
        System.out.println("平均分是:"+(sum/score[i].length));
    }
}

4.2 Arrays.sort
学习冒泡排序,让我们掌握了一种排序的方法,如果只是对 基本类型数组 的数据进行排序,Arrays 类提供的 sort 方法会更直接。
public static void main(String[] args) {
    int[] intArray = new int[]{4,8,6,0,1,9,5,2,3,7};
    Arrays.sort(intArray);
    System.out.println("整数型数组排序的结果:");
    for (int n : intArray) {
        System.out.print(n+" ");
    }
}

                    
                
                
            
        
浙公网安备 33010602011771号