JavaSE——04数组

89 阅读8分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

04 数组


1、数组的基本概念和语法

1)Java语言中的数组是一种引用数据类型。 不属于基本数据类型。数组的父类是Object。

2)数组实际上是一个容器,可以同时容纳多个元素。(数组是一个数据的集合。)

数组:字面意思是“一组数据”

3)数组当中可以存储"基本数据类型"的数据,也可以存储“引用数据类型”的数据。

4)数据因为是引用类型,所以数据对象是堆内存当中。(数组是存储在堆当中的)

5)数组当中如果存储的是"java对象”的话,实际上存储的是对象的引用(内存地址)”, 数组中不能直接存储java对象。

6)数组一旦创建,在java中规定,长度不可变。 (数据长度不可变);

7)数组的分类:一维数组,二维数组、三维数组、 多维数组… ( 一维数组较多,二维数组偶尔使用)

8) 所有的数组对象都有length属性(java自带的),用来获取数组中元素的个数。

9) java中的数组要求数据中元素的类型统一。比部int 类型数组只能存能int类型. Person类型数组只能存储Person类型。

例加:超市的物,购做袋中只能装苹果,不能同时装苹果和橘子。( 数组中存储的元素类型统一)

10)数组在内存方面存储的时候, 数祖中的元素内存地址(存储的每一个元素都是有规则的挨着排列的)是连续的。 内存地址连续这是数组存储元素的特点(特色)。数组实际上是一种简单的数据结构。

11)所有的数组都是拿“第一个小方框的内存地址“作为整个数组对象的内存地址。

12) 数组这种数据结构的优点和缺点是什么?

优点:查询/查找/检索某个下标上的元素时效率极高。可以说是查询效率最高的一个数据结构。

为什么检索效率高?

第一:每一个元素的内存地址在空间存储上是连续的。

第二:每一个元素类型相同,所以占用空间大小一样。

第三:知道第一个元素内存地址,知道每一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址。直接通过内存地址定位元素,所以数组的检索效率是最高的。

数组中存储100个元素,或者存100万个元素,在元素查询/检索方面,效率是相同的,因为数组中元素查找的时候不会一个一个找 ,而是通过数学表达式计算出来的。 (算出一 个内存地址,直接定位的。)

缺点:

第一:由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候,效率较低,因为随机增加元素会涉及到后面元素统一向前或者向后位移的操作。

第二:数组不能存储大数据量,因为很难在内存空间上找到一块特别大的连续的存储空间

2、声明和初始化一维数组

2.1 声明

数据类型[] 数组名;

e.g.:int[ ] array1; String[ ] array2; Object[ ] array3;

2.2 初始化

静态初始化语法格式

int [ ] array = (1,2,3,4,5);

使用静态方法初始化,方便不需要new对象

动态初始化语法格式

int [ ] array = new int[5]; ,通过for循环赋值

public class HelloWorld{
    public static void main(String[] args) {
        //动态初始化一维数组
        printArray(new int[3]);
        //传递静态数组
        printArray(new int[]{1,2,3});
    }
    public static void printArray(int[] array){
        for(int i = 0;i < array.length;i++){
            System.out.println(array[i]);
        }
    }
}

2.3 实例

采用静态初始化的方法

String[] str = ("abc","ert","ijn");
for(int i=0;i<str.length;i++){
	System.out.println(str[i]);
}

采用动态初始化的方法

Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
Object[] objects = {o1,o2,o3};

//以上四行可换为下面一行
//Object[] object = {new Object(),new Object(),new Object()};
for(int i=0;i<object.length;i++){
    System.out.println(Object[i]);
}

3、main方法的String数组

public class HelloWorld{
    
    public static void main(String[] args) {
 		   
    }
    
}

1)这个方法程序员负责写出来,JVM负责调用,JVM调用的时候传一个数组长度args为0的String数组

2)关于String[ ] args

这个数组是留给用户的,用户可以在控制台输入参数,这个参数会自动转换为"String[ ] args"
在这里插入图片描述​编辑
在这里插入图片描述​编辑

Edit Configurations——>Program arguments 这里可以输入参数,

args.length访问输入字符串长度
args[]可以访问字符串内容

String username = args[0];
String password = args[1];
if(username.equals("admin") && password.equals("123")){
}

username.equals(“admin”) && password.equals(“123”)这样写容易造成空指针异常;

优化:**“admin”.equals(username) && “123”.equals(password)**不容易造成空指针异常;

4、继承关系的数组

数组中可以存放子类的对象,调用的方法是父类中存在的方法不需要向下转型,直接使用父类型引用调用即可

当调用子类中特有的方法时,需要向下转型再调用

public class HelloWorld{
    public static void main(String[] args) {
        Animal[] ani ={new Cat(),new Fish()};
        for (int i =0;i<ani.length;i++){
            ani[i].move();//调用的方法是父类中存在的方法不需要向下转型,直接使用父类型引用调用即可
            if(ani[i] instanceof Cat){
                Cat c = (Cat)ani[i];
                c.catchMouse();//当调用子类中特有的方法时,需要向下转型再调用
            }
            if(ani[i] instanceof Fish){
                Fish f = (Fish)ani[i];
                f.swim();
            }
        }
    }
}
class Animal{
    public void move(){
        System.out.println("动物在移动!");
    }
}
class Cat extends Animal{
    public void move(){
        System.out.println("猫在爬!");
    }
    public void catchMouse(){
        System.out.println("抓老鼠");
    }
}
class Fish extends Animal{
    public void move(){
        System.out.println("鸟儿在飞行!");
    }
    public void swim(){
        System.out.println("鱼游泳");
    }
}

5、一维数组的扩容

先建立一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组中【数组扩容效率较低,减少数组的拷贝和扩容次数,提高效率】

6、数组拷贝

System.arraycopy(源,源的起始下标,目标,目标的起始下标,长度) Ctrl + P可以看提示

//拷贝源(从这个数组中拷贝)
int[] src = {1,11,,22,3,4};

//拷贝目标(拷贝到这个目标数组上)
int[] dest = new int[20];//动态初始化一个长度为20的数组,每一个元素默认值为0

//调用JDK Sydtem类中的arraycopy方法,来完成数据的拷贝
System.arraycopy(src,1,dest,3,2);

数组中如果存储的元素是引用数据类型,也可以拷贝

数组中如果存储的元素是对象,则拷贝的是内存地址

在这里插入图片描述​编辑

7、二维数组

7.1 二维数组的声明和初始化

(二维数组的每个元素是一个一维数组)

int[][] a = { {100,200,300},{12,23,45},{23,54,1},{23,54,1} }

7.2 length属性

//以上面例子说明length属性
a.length = 4;
a[0].length = 3;
//a[0]代表的是{100,200,300};

7.3 关于二维数组中元素的访问

1)取出二维数组中的第一个一维数组

a [0] = {100,200,300}

2)取出二维数组中的第一个一维数组的第一个元素

a [0] [0] = 100


8、数组模拟栈数据结构

8.1 题目要求

1)这个栈可以存储java中的任何引用类型的数据;

2)在栈中提供push方法模拟压栈;(栈满了,要有提示信息)

3)在栈中提供pop方法模拟压栈;(栈空了,要有提示信息)

4)编写测试程序,new栈对象,调用push pop方法来模拟压栈弹栈操作;

5)假设栈的默认初始化容量是10;

8.2 代码呈现

public class Text {
    public static void main(String[] args) {
        //创建一个栈对象,初始化容量是10个
        Stack s = new Stack();
        s.push("12345ty");
        s.push(new Object());
        s.push(new Object());
        s.push(new Object());
        s.push(new Object());
        s.pop();
        s.pop();
        s.pop();
        s.pop();
        s.pop();
        s.pop();
        //可以使用for循环进行压栈和弹栈
    }
}
class Stack{
    //存储任何引用类型数据的数组
    private Object[] elements;
    //有参构造方法
    public Stack(Object[] elements) {
        this.elements = elements;
    }
    //无参构造方法
    public Stack() {
        //一维数组动态初始化
        //默认初始化容量为10
        this.elements = new Object[10];
    }
    //栈帧(永远指向栈顶元素)
    private int index=-1;

    //压栈方法
    public void push(Object obj){
        if(this.index >= this.elements.length-1){
            System.out.println("栈内存已满,压栈失败");
            return;
        }
        index++;
        elements[index] = obj;
        System.out.println(obj + "元素,压栈成功,栈帧指向" + index);
    }

    //弹栈方法
    public void pop(){
        if(this.index <= -1) {
            System.out.println("栈内存已空,弹栈栈失败");
        }
        else
            System.out.println(elements[index] + "元素,弹栈成功,栈帧指向" + --index);
    }

    //static实例变量的get方法
    public Object[] getElements() {
        return elements;
    }
    //static实例变量的set方法
    public void setElements(Object[] elements) {
        this.elements = elements;
    }
    //实例变量栈帧的get方法
    public int getIndex() {
        return index;
    }
    //实例变量栈帧的set方法
    public void setIndex(int index) {
        this.index = index;
    }
}

8.3 问题展现

1)为什么选择Object类型数组?

因为这个栈可以存储java中任何引用类型的数据

new Animal( )对象和new Peaple( )对象包括字符串都可以放进去,因为Animal和Peaple的超级费雷都是Object;

Object [ ] 是一个万能的口袋,这个口袋可以装任何引用数据类型的数据

2)关于字符串

字符串其实是一个字符串对象,但在java中字符串有优待,不需要new也是一个对象

String s = "asdfghj";

String s = new String("asdfghj");

3)关于set和get方法

在类中,大多采用封装机制,所以set和get方法有时候虽然用不到,但也需要写上

4)数组的初始化

数组的初始化可以在定义时直接初始化

this.elements = new Object [10];//赋值也是在构造方法调用的时候初始化

也可以在构造方法中初始化

 public Stack() {
        this.elements = new Object[10];
    }

5)关于System.out.println()方法

所有的System.out.println()方法在执行时,如果输出引用,自动调用引用的toString()方法

e.g.:System.out.println(obj + “元素,压栈成功”);这里的obj其实调用了toString()方法


9、酒店管理系统

9.1 题目要求

为某酒店编写程序:酒店管理程序,模拟订房、退房、打印所有房间状态等功能

1)该系统的用户是:酒店前台

2)酒店使用一个二维数组来模拟"Room[ ] [ ] rooms;"

3)酒店中的每一个房间应该是一个java对象:Room;

4)每一个房间Room应该有:房间编号、房间类型属性、房间是否为空;

5)系统对外提供的功能:

可以预定房间:用户输入房间编号,订房

可以退房:用户输入房间编号,退房;

可以查看所有房间的状态:用户输入某个指令应该可以查看所有房间的状态

9.2 代码呈现

import java.util.Scanner;

public class HotelSystem {
    public static void main(String[] args) {
        //创建酒店对象
        Hotel hotel = new Hotel();
        Scanner s = new Scanner(System.in);
        Scanner roomNo = new Scanner(System.in);
        meau();
        while(true){
            int i = s.nextInt();
            switch (i){
                case 1:
                    hotel.print();break;
                case 2:
                    System.out.println("请输入预定的房间号");
                    hotel.order(roomNo.nextInt());break;
                case 3:
                    System.out.println("请输入退订的房间号");
                    hotel.exit(roomNo.nextInt());break;
                case 0:
                    return;
            }
        }
    }
    public static void meau(){
        //欢迎页面
        System.out.println("_____________________________________________________________________ ");
        System.out.println("**********************┍------------------------┑ *******************");
        System.out.println("**********************   欢迎使用酒店管理系统     ********************");
        System.out.println("**********************┕------------------------┙ *******************");
        System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx菜单xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        System.out.println("====================================================================");
        System.out.println(".......      1.查看房间         ......         2.表示订房      .......");
        System.out.println(".......      3.表示退房         ......         0.退出系统      .......");
        System.out.println("____________________________________________________________________");
        System.out.println("请输入功能编号:");
    }
}
class Room{
    //房间号
    private int no;
    //房间类型
    private String type;
    //房间状态
    private boolean status;
    //重写Object中的toString方法,返回一个含有三个信息的字符串
    public String toString() {
        return "["+no+","+type+","+(status ? "空闲":"占用")+"]";
    }
    //重写Object中的equals方法,若房间号相同则两个对象相同
    public boolean equals(Object obj){
        if(obj == null||!(obj instanceof Room)) return false;
        if(this == obj) return true;
        Room room = (Room)obj;
        return room.getNo()==this.no;
    }

    public Room(int no, String type, boolean status) {
        this.no = no;
        this.type = type;
        this.status = status;
    }

    public Room() {
    }

    public int getNo() {
        return no;
    }

    public String getType() {
        return type;
    }

    public boolean isStatus() {
        return status;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public void setType(String type) {
        this.type = type;
    }

    public void setStatus(boolean status) {
        this.status = status;
    }
}
class Hotel {
    //二维数组模拟酒店房间
    private Room[][] rooms;

    //通过构造方法来盖楼
    public Hotel(){
    //房间编号,房间类型,房间状态
        rooms = new Room[3][10];
        //创建30个对象,放到数组中
        for (int i = 0;i < rooms.length;i++){
            for (int j = 0;j < rooms[i].length;j++){
                if(i==0){
                    rooms[i][j] = new Room((i+1)*100+j+1,"单人间",true);
                }
                else if(i==1){
                    rooms[i][j] = new Room((i+1)*100+j+1,"标准间",true);
                }
                else if(i==2){
                    rooms[i][j] = new Room((i+1)*100+j+1,"豪华间",true);
                }
            }
        }
    }
    //在酒店对象上提供一个打印房间列表的方法
    public void print(){
        for (int i = 0;i < rooms.length;i++){
            for (int j = 0;j < rooms[i].length;j++) {
                System.out.print(rooms[i][j]);
            }
            System.out.println();
        }
    }
    //在酒店对象上提供一个订房的方法
    public void order(int roomNo){
        //最主要的是将房间状态修改为false
        Room room = rooms[roomNo / 100 -1][roomNo % 100-1];
        if(room.isStatus()==false){
            System.out.println("该房已被预定!请重新选择!");
            return;
        }
        room.setStatus(false);
        System.out.println(roomNo + "已定房!");
    }
    //在酒店对象上提供一个退房的方法
    public void exit(int roomNo){
        //最主要的是将房间状态修改为true
        Room room = rooms[roomNo / 100 -1][roomNo % 100-1];
        if(room.isStatus()==true){
            System.out.println("该房已被退订!");
            return;
        }
        room.setStatus(true);
        System.out.println(roomNo + "已退房!");
    }
}import java.util.Scanner;

public class HotelSystem {
    public static void main(String[] args) {
        //创建酒店对象
        Hotel hotel = new Hotel();
        Scanner s = new Scanner(System.in);
        Scanner roomNo = new Scanner(System.in);
        meau();
        while(true){
            int i = s.nextInt();
            switch (i){
                case 1:
                    hotel.print();break;
                case 2:
                    System.out.println("请输入预定的房间号");
                    hotel.order(roomNo.nextInt());break;
                case 3:
                    System.out.println("请输入退订的房间号");
                    hotel.exit(roomNo.nextInt());break;
                case 0:
                    return;
            }
        }
    }
    public static void meau(){
        //欢迎页面
        System.out.println("_____________________________________________________________________ ");
        System.out.println("**********************┍------------------------┑ *******************");
        System.out.println("**********************   欢迎使用酒店管理系统     ********************");
        System.out.println("**********************┕------------------------┙ *******************");
        System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx菜单xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        System.out.println("====================================================================");
        System.out.println(".......      1.查看房间         ......         2.表示订房      .......");
        System.out.println(".......      3.表示退房         ......         0.退出系统      .......");
        System.out.println("____________________________________________________________________");
        System.out.println("请输入功能编号:");
    }
}
class Room{
    //房间号
    private int no;
    //房间类型
    private String type;
    //房间状态
    private boolean status;
    //重写Object中的toString方法,返回一个含有三个信息的字符串
    public String toString() {
        return "["+no+","+type+","+(status ? "空闲":"占用")+"]";
    }
    //重写Object中的equals方法,若房间号相同则两个对象相同
    public boolean equals(Object obj){
        if(obj == null||!(obj instanceof Room)) return false;
        if(this == obj) return true;
        Room room = (Room)obj;
        return room.getNo()==this.no;
    }

    public Room(int no, String type, boolean status) {
        this.no = no;
        this.type = type;
        this.status = status;
    }

    public Room() {
    }

    public int getNo() {
        return no;
    }

    public String getType() {
        return type;
    }

    public boolean isStatus() {
        return status;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public void setType(String type) {
        this.type = type;
    }

    public void setStatus(boolean status) {
        this.status = status;
    }
}
class Hotel {
    //二维数组模拟酒店房间
    private Room[][] rooms;

    //通过构造方法来盖楼
    public Hotel(){
    //房间编号,房间类型,房间状态
        rooms = new Room[3][10];
        //创建30个对象,放到数组中
        for (int i = 0;i < rooms.length;i++){
            for (int j = 0;j < rooms[i].length;j++){
                if(i==0){
                    rooms[i][j] = new Room((i+1)*100+j+1,"单人间",true);
                }
                else if(i==1){
                    rooms[i][j] = new Room((i+1)*100+j+1,"标准间",true);
                }
                else if(i==2){
                    rooms[i][j] = new Room((i+1)*100+j+1,"豪华间",true);
                }
            }
        }
    }
    //在酒店对象上提供一个打印房间列表的方法
    public void print(){
        for (int i = 0;i < rooms.length;i++){
            for (int j = 0;j < rooms[i].length;j++) {
                System.out.print(rooms[i][j]);
            }
            System.out.println();
        }
    }
    //在酒店对象上提供一个订房的方法
    public void order(int roomNo){
        //最主要的是将房间状态修改为false
        Room room = rooms[roomNo / 100 -1][roomNo % 100-1];
        if(room.isStatus()==false){
            System.out.println("该房已被预定!请重新选择!");
            return;
        }
        room.setStatus(false);
        System.out.println(roomNo + "已定房!");
    }
    //在酒店对象上提供一个退房的方法
    public void exit(int roomNo){
        //最主要的是将房间状态修改为true
        Room room = rooms[roomNo / 100 -1][roomNo % 100-1];
        if(room.isStatus()==true){
            System.out.println("该房已被退订!");
            return;
        }
        room.setStatus(true);
        System.out.println(roomNo + "已退房!");
    }
}

9.3 问题展现

1)equals方法重写

equals是用来比较两个字符串对象是否相等的,至于怎么比较程序员自己决定;

你认为两个房间的编号相等就表示同一个房间,那么你写代码标记房间编号就行

2)toString方法重写

toString方法的目的是将java对象转换成字符串形式,怎么转,转成什么形式程序员自己定,可以重写后不转成内存地址

public String toString(){
	//return "[101,单人间,占用]"
	//动态
    return "["+no+","+type+","+(status ? "空闲":"占用")+"]"
}

3)如何把一个变量塞到一个字符串当中,口诀:加一个双引号,双引号中间加两个加号,两个加号中间加变量名

"["+no+","+type+","+(status ? "空闲":"占用")+"]"