数组

数组

1 数组的定义和读写

1.1 什么是数组

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

​ 什么是数组呢? java 的数组是由相同数据类型的一组数据组成的连续存储的结构。

image-20220630184929777

上图是几个数组的示例

1.2定义数组

数组的定义有以下三种

  1. 定义空间的方式:数组类型[] 变量名称 = new 数据类型[长度];
  2. 初始化方式:数据类型[] 变量名称 = {值0,值1,值2,······,值N};
  3. 完整写法:数据类型[] 变量名称 = 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;
    
}

image-20220630190656405

1.4 内存存储

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

image-20220630191049399

我们发现,数组对象也是存储在内存堆中的,而 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));
    }
}

image-20220630205720708

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);
    }
}

image-20220630210550620

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);
    }

image-20220630211554575

练习:现在有一组数据{16,25,9,90,23},请编程对其进行排序。

分析:我们准备采用冒泡法进行排序,冒泡法中有一个趟的概念,从前到后走一遍被称为一趟,假如对 N 个数字进行从小到大的 升序排列的话:

  1. 第 0 趟会得到 0 到 N-1 之间的最大值排到 N-1 的位置。
  2. 第 1 趟会得到 0 到 N-2 之间的最大值排到 N-2 的位置。
  3. ……
  4. 第 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");
    }
}

image-20220701080703617

冒泡排序的口诀(升序): 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);
    }
}

image-20220701145733676

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

image-20220701145817805

在 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");
    }
}

image-20220701153544566

练习:使用 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);
    }
}

image-20220701154442834

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));
    }
}

image-20220701155604172

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+" ");
    }
}

image-20220701160505366

posted @ 2022-07-01 16:08  茶煮清凉  阅读(113)  评论(0)    收藏  举报