22.Java 数组概念/数组常见操作/多维数组/数组存储表格数据/javabean 和数组存储表格信息/Comparable接口

数组学习目标

数组概念

数组的定义

数组是相同类型数据的有序集合。
数组描述的是想同类型的若干个数据,按照一定的先后次序排列组合而成。
每一个数据称作一个元素,每个元素可以通过一个索引(下标)来访问。

数组简述

数组变量属于引用类型,数组也是对象,数组中每个元素相当于该对象的成员变量。
Java 中对象存储在堆中,所以数组对象也在堆中存储。

数组四个基本特点

  1. 长度是确定的。数组一旦被创建,其大小是不可改变的。
  2. 其元素的类型必须是相同类型,不允许出现混合类型。
  3. 数组类型可以是任何数据类型,包括基本类型和引用类型。
  4. 数组变量属于引用类型,数组也是对象。数组的元素相当于对象的属性。

数组声明

type[] arr_name; // 方式一(推荐)
type arr_name[]; // 方式二

注意点:

声明时不会实例化任何对象,只有在实例化数组对象时,JVM 才分配空间,此时才跟长度有关。
声明一个数组时,数组不会真正被创建。
构造一个数组,必须指定长度。

数组的初始化

(1)静态初始化

定义数组的同时就为数组元素分配空间并赋值。

(2)动态初始化

数组定义与数组元素分配空间并赋值的操作分开进行。

(3)默认初始化

数组是引用类型,它的元素相当于类的实例变量,因此数组分配空间时,其每个元素也被按照实例变量同样的方式被隐式初始化。比如 int类、String类等自带的类

代码示例:测试数组的三种初始化方式

package cn.jungle.test.ShuZu;

// 测试数组的三种初始化方式
public class Test2 {
    public static void main(String[] args) {
        // 数组的静态初始化
        int[] a = {1,2,3}; // 静态初始化基本类型数组
        Man[] mans = {new Man(1,1),new Man(2,2)}; // 静态初始化引用类型数组,new Man(1,1) 代表新创建的对象
        // 数组的动态初始化
        int[] a1 = new int[2]; // 动态初始化数组,先分配空间;
        a1[0] = 1; // 给数组元素赋值
        a1[1] = 2; // 给数组元素赋值
        // 数组的默认初始化(针对 int类、String类这种自带的类)
        int a2[] = new int[2]; // 默认值:0,0
        boolean[] b = new boolean[2]; // 默认值:false,false
        String[] s = new String[2]; // 默认值:nullm,null
    }
}

代码示例:创建基本类型一维数组

package cn.jungle.test.ShuZu;

// 创建基本类型一维数组
public class Test {
    public static void main(String[] args){
        int[] s = null;  // 声明数组
        s = new int[10];  // 给数组分配空间
        for(int i = 0;i < 10;i++){
            // 给数组元素赋值,数组是对象,数组中的元素就是对象的属性
            s[i] = 2 * i + 1;
            System.out.println(s[i]); // 打印数组元素
        }
    }
}

代码示例:创建引用类型一维数组

// 测试引用类型数组
class Man {
    private int id;
    private int age;
    public Man(int id,int age){
        super();   // 可写可不写,默认会执行
        this.age = age;
        this.id = id;
    }
}
public class AppMain{
    public static void main(String[] args) {
        Man[] mans; // 声明引用类型数组
        mans = new Man[10]; // 给引用类型数组分配空间
        Man m1 = new Man(1,11);  // 创建id和age属性为1和11的新对象,将其赋值给左边的 m1 对象
        Man m2 = new Man(2,22);  // 创建id和age属性为2和22的新对象,将其赋值给左边的 m2 对象
        mans[0] = m1; // 给引用类型数组的元素赋值为 m1 对象
        mans[1] = m2; // 给引用类型数组的元素赋值为 m2 对象
    }
}

引用类型数组内存分析图

代码示例:测试 “数组也是对象的概念”

package test.jungle.array;

// 测试数组也是对象的概念
public class Dog {
    // 声明 name 属性
    String name;
    public static void main(String[] args){
        // 创建一个 Dog 对象
        Dog dog1 = new Dog();
        // 对象调用方法
        dog1.back();  // null,因为没有引用到任何对象的引用变量的值为null值
        dog1.name = "阿jun修炼手册";

        // 创建大小为 3 的 Dog 引用类型数组,并赋值给前面所声明的 Dog[] 类型变量 myDogs
        Dog[] myDogs = new Dog[3];
        // 上方代码只是对 Dog 的引用,缺少了实际的 Dog 对象,所以需要创建新的 Dog 对象并赋值给数组的元素
        myDogs[0] = new Dog();
        myDogs[1] = new Dog();
        myDogs[2] = dog1;

        // 通过数组引用存取 Dog:对象调用成员属性
        myDogs[0].name = "阿jun";
        myDogs[1].name = "阿junZzz";

        // 打印 myDogs[2] 的 name 值
        System.out.println(myDogs[2].name); // 阿jun修炼手册

        // 逐个对 Dog 执行 bark() 方法
        int x = 0;
        while(x < myDogs.length){  // myDogs.length = 3,即是数组的大小
            myDogs[x].back();
            x++;
        }
    }
    public void back(){
        System.out.println(name);
    }
}

数组常见操作

数组普通遍历

利用 for 循环对数组的元素进行提取打印

for-each 增强循环数组遍历

for-each 专门用于读取数组或集合中所有元素,即对数组进行遍历,是 JDK1.5 新增加的功能。
for-each 增强 for 循环在遍历数组过程中不能修改数组中某元素的值。
for-each 仅适用于遍历,不涉及有关索引(下标)的操作。

代码示例:数组普通遍历以及 for-each 增强循环数组遍历

package test.jungle.array;

// 测试数组的定义和初始化以及循环的使用
public class Test01 {
    public static void main(String[] args) {
        // 默认初始化
        int[] arr1 = new int[5];
        System.out.println(arr1[0]); // 0
        System.out.println(arr1[1]); // 0
        // 静态初始化
        int arr2[] = {20,30,40};
        System.out.println(arr2.toString()); // [I@1b6d3586
        // 数组的 for 一般遍历
        for (int i=0;i<arr1.length;i++){ // arr1.length 的值为 arr1 的数组长度
            // 对数组元素进行赋值
            arr1[i] = i * 2 + 1;
        }
        // 使用 for-each 增强循环遍历数组
        String[] ss = {"aa","bb","cc","dd"};
        for(String temp1:ss){
            System.out.println(temp1);
        }
    }
}

数组拷贝

System 类中包含了一个 static void arraycopy (object src,int srcpos,object dest,int destpos int length) 方法,
该方法可以将 src 数组里的元素复制给 dest 数组的元素,
其中 srcpos 指定从 src 数组的第几行开始赋值,length 参数指定将 src 数组的多少个元素赋值给 dest 数组的元素。

格式:数组拷贝

System.arraycopy(目标数组,目标数组起始位置索引,拷贝数组,拷贝数组数据起始位置,拷贝数量);

代码示例:数组拷贝

package test.jungle.array;

// 测试数组拷贝
public class TestKB {
    public static void main(String[] args) {
        String[] s = {"淘宝","京东","腾讯","网易","阿jun"};
        String[] sBak = new String[7];
        System.arraycopy(s,0,sBak,0,s.length);
        for(int i = 0;i < sBak.length;i++){
            System.out.print(sBak[i] + "\t");
        }
    }
}

java.util.Arrays 类

这个类是 java 提供给我们操作数组的工具类。
Arrays 类包含了:排序、查找、填充、打印内容等常见操作。

代码示例:使用 Arrays 类输出数组中的元素:数组排序、填充、二分法查找

package test.jungle.array;
import java.util.Arrays;

// 测试 java.util.Arrays 类
public class TestArrays {
    public static void main(String[] args) {
        int[] a = {3,99,22,11};
        // 打印数组引用的值
        System.out.println(a);  // [I@1b6d3586
        // 打印数组元素的值
        System.out.println(Arrays.toString(a)); // [3, 99, 22, 11]
        Arrays.sort(a);   // 排序数组
        System.out.println(Arrays.toString(a)); // [3, 11, 22, 99]

        // 测试二分法查找:测试二分法查找之前,必须先对数组进行排序,否则没法查
        // 返回排序后元素新的索引位置,如果未找到,则返回负数,binarySearch(数组名,要查找的元素名)
        System.out.println("要查找元素的索引是:" + Arrays.binarySearch(a,22));   // 2,查找 a 数组里面是否有 22 元素
        System.out.println("要查找元素的索引是:" + Arrays.binarySearch(a,33));   // -4 查找 a 数组里面是否有 33 元素

        // 使用 Arrays 类对数组进行填充
        System.out.println(Arrays.toString(a)); // [3, 11, 22, 99]
        // 将 2 到 4 的索引元素进行替换,包头不包尾
        Arrays.fill(a,2,4,520);
        System.out.println(Arrays.toString(a)); // [3, 11, 520, 520]
    }
}

多维数组

概念

多维数组的元素是数组。
因为数组元素的数据类型可以是任意类型。

代码示例:二维数组的声明

package test.jungle.array;
import java.util.Arrays;

// 测试二维数组的声明
public class TestArrays01 {
    public static void main(String[] args) {
        // Java 中多维数组的声明和初始化应按照从低维到高维的顺序进行
        int[][] a = new int[3][];
        a[0] = new int[2];
        a[1] = new int[4];
        a[2] = new int[3];
        // 下方是不合规的多维数组定义
        int a1[][] = new int[0][4];  // 这个是非法的定义
        System.out.println(Arrays.toString(a));  // [[I@1b6d3586, [I@4554617c, [I@74a14482],打印的是多维数组的数组元素对应内存地址
        System.out.println(Arrays.toString(a1)); // 结果为 []  能够对比发现,a1 不属于是多维数组
    }
}

代码示例:二维数组的静态初始化、动态初始化以及获取数组长度

package test.jungle.array;

// 测试二维数组的静态初始化和动态初始化
public class TestArray02 {
    public static void main(String[] args) {
        // 测试二维数组的静态初始化
        int[][] a = {{1,2,3},{3,4},{3,5,6,7}};
        System.out.println(a[2][3]); // 7

        // 测试二维数组的动态初始化
        int[][] a1 = new int[3][];
        a1[0] = new int[] {1,2};
        a1[1] = new int[] {3,4};
        a1[2] = new int[] {5,6};
        System.out.println(a[2][1]); // 5

        // 获取数组长度
        // 获取二维数组第一堆数组的长度
        System.out.println(a.length); // 3
        // 获取第二维第二个数组长度
        System.out.println(a[1].length); // 2
    }
}

二维数组的静态初始化内存图如下:

数组存储表格数据

二维数组存储表格数据

每一行都可以使用一个一维数组来存储表格数据

// 静态初始化一个一维数组
Object[] a1 = {1001,"阿jun",18,"学员","2021-12-06"};

代码示例:测试二维数组 Object[][] 存储 “整个表格” 的数据

package test.jungle.array;
import java.util.Arrays;

/**
 * 测试二维数组
 * 使用 Object[][] 存储整个表格的数据
 * */
public class TestArrays03 {
    public static void main(String[] args) {
        // 利用静态初始化定义几个一维数组
        Object[] a1 = {"阿junZzz1",18,"不是很爱学习,爱偷懒","2021-12-06"};
        Object[] a2 = {"阿junZzz2",20,"爱偷懒,不是很爱学习","2021-12-06"};
        Object[] a3 = {"阿junZzz3",22,"你一定要努力,别负青春","2021-12-06"};

        // 动态初始化多维数组
        Object[][] emps = new Object[3][];
        emps[0] = a1;
        emps[1] = a2;
        emps[2] = a3;

        // 利用 for 循环打印二维数组的内容(类似于打印表格数据)
        for (int i=0;i < emps.length;i++){
            System.out.println(Arrays.toString(emps[i]));
        }
        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        // 利用 for 循环嵌套打印二维数组的内容(类似于打印表格数据)
        for (int i=0;i < emps.length;i++){
            for (int j=0;j < emps[i].length;j++){
                System.out.print(emps[i][j] + "\t");
            }
            System.out.println();
        }
    }
}

javabean 和数组存储表格信息(掌握)

使用 javabean 和数组存储表格信息

代码示例:使用 javabean 和数组存储表格数据、使用多种方式去调用数组值

package test.jungle.array;

// 使用 javabean 和数组存储表格数据
public class TestArrays04 {
    public static void main(String[] args) {
        // 定义对象来存储表格数据
        Emp emp0 = new Emp(1001,"阿jun",18,"未来的逆向工程师","2021-12-07");
        Emp emp1 = new Emp(1001,"阿junZzz",20,"未来的逆向工程师","2021-12-07");
        Emp emp2 = new Emp(1001,"阿jun修炼手册",22,"未来的逆向工程师","2021-12-07");

        // 静态初始化创建一维数组
        // Emp[] emps = {emp0,emp1,emp2};
        // 动态初始化创建一维数组
        Emp[] emps = new Emp[3];
        emps[0] = emp0;
        emps[1] = emp1;
        emps[2] = emp2;
        // 循环遍历调用对应的属性值
        for (int i=0;i < emps.length;i++){
            // emps[i] 定位到具体的引用后,使用 get 方法去获取值
            System.out.println(emps[i].getId() + "\t" + emps[i].getName() + "\t" + emps[i].getAge() + "\t" + emps[i].getJob() + "\t" + emps[i].getHiredate());
        }

        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        // 通过在 Emp 类中重写 toString() 方法,获取数组值
        for (int i=0;i < emps.length;i++){
            System.out.println(emps[i]);
        }

    }
}
// 创建一个类用来表示表结构,再创建一个对象来表示这些数据
class Emp{
    private int id;
    private String name;
    private int age;
    private String job;
    private String hiredate;
    // 定义一个空构造器,建议写,当后期增加其他内容时,可提高代码可维护性
    public Emp(){}

    // 定义构造器:可使用 alt + insert 快捷键
    public Emp(int id, String name, int age, String job, String hiredate) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.job = job;
        this.hiredate = hiredate;
    }

    // 通过方法重写覆盖,实现 mian 主类中数组对应属性值的调用打印
    @Override
    public String toString(){
        //return id + "\t" + name + "\t" + age + "\t" + job + "\t" + hiredate;
        //推荐使用 get 方法来获取属性值,即取值时尽量使用 get/set 方法,提高代码容错率
        return getId() + "\t" + getName() + "\t" + getAge() + "\t" + getJob() + "\t" + getHiredate();
    }

    // get / set 方法
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    public String getHiredate() {
        return hiredate;
    }
    public void setHiredate(String hiredate) {
        this.hiredate = hiredate;
    }
}

作业留存

作业代码(大概实现了)

package test.jungle.array;

// 使用数组的形式打印一张商品信息表
public class TestArrays05 {
    public static void main(String[] args) {
        Goods goods1 = new Goods(1,"百战牌鼠标","BZ_001",99.21,0.9);
        Goods goods2 = new Goods(2,"键盘侠玩偶","WO_102",403.00,0.7);
        Goods goods3 = new Goods(3,"实战java程序设计","BK_001",89.00,0.8);
        Goods goods4 = new Goods(4,"阿jun的新衣","GQ_XF_12",700.00,0.5);
        Goods goods5 = new Goods(5,"大米牌手机","DM_PH_13",900.00,0.3);

        // 静态初始化一个数组,用于存储这上方 5 个商品对象信息
        Goods[] goods = {goods1,goods2,goods3,goods4,goods5};
        // 将重写的 toString() 方法遍历数组,否则的话,只会打印对象内存地址,不会打印对应内容
        // 打印商品信息
        for (int i=0;i<goods.length;i++){
            System.out.println(goods[i]);
        }
        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        // 输出价格
        for (int i=0;i<goods.length;i++){
            System.out.println(goods[i].getName() + "的最终价格是:" +goods[i].getDiscount() * goods[i].getPrice() + "元");
        }
    }
}

class Goods{
    private int id;            // ID
    private String name;       // 名称
    private String model;      // 型号
    private double price;      // 价格
    private double discount;   // 折扣

    // 预定义一个空构造方法,如果不定义,当有其他构造方法出现时,就不会被系统默认定义
    public Goods(){};

    // 定义一个形参构造方法
    public Goods(int id, String name, String model, double price, double discount) {
        this.id = id;
        this.name = name;
        this.model = model;
        this.price = price;
        this.discount = discount;
    }

    // 重写 toString() 方法,用于主类中 main 方法的调用
    @Override
    public String toString(){
        return getId() + "\t" + getName() + "\t" + getModel() + "\t" + getPrice() + "\t" + getDiscount();
    }
    // 定义 set / get 方法
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public double getDiscount() {
        return discount;
    }

    public void setDiscount(double discount) {
        this.discount = discount;
    }
}

Comparable接口(对不同对象排序)

简述

想对某个类的对象之间做比较,就需要实现 Comparable 接口。
接口中只有一个方法 compareTo ,这个方法定义了对象之间的比较规则。
根据这个 “比较规则”,可以对所有对象实现排序,比如不同对象之间按照年龄 age 的属性值排序。
Java 中排序算法的底层也依赖 Comparable 接口。

接口方法实现

Comparable 接口只有一个 compareTo 方法:

public int compareTo(Object obj)  // 其中 obj 是要比较的对象

方法中,将当前对象和 obj 这个对象进行比较,如果大于返回 1,等于返回 0,小于返回 -1。(此处的 1 也可以是正整数,-1 也可以是负整数)。
compareTo 方法的代码也比较固定。

compareTo 方法代码案例:测试 Comparable 接口:使用 Arrays 类对数组元素进行排序:按照 age 大小排序

package test.jungle.array;

import java.util.Arrays;
// 测试 Comparable 接口:使用 Arrays 类对数组元素进行排序:按照 age 大小排序
public class CompareToTest {
    public static void main(String[] args) {
        Man[ ] m1 = {new Man(12,"阿jun"),new Man(22,"阿jun修炼手册"),new Man(18,"阿junZzz")};
        Arrays.sort(m1);
        System.out.println(Arrays.toString(m1));
    }
}
class Man implements Comparable{
    int age;
    int id;
    String name;
    public Man(int age,String name){
        super();
        this.age = age;
        this.name = name;
    }
    public String toString(){
        return this.name;
    }
    // 定义 compareTo 方法
    public int compareTo(Object o){
        Man man = (Man) o;
        if (this.age < man.age){
            return -1;
        }
        if (this.age > man.age){
            return 1;
        }
        // 等于时返回 0
        return 0;
    }
}
posted @ 2021-12-07 10:58  阿jun  阅读(208)  评论(0编辑  收藏  举报