美文网首页
JavaSE进阶-02-数组

JavaSE进阶-02-数组

作者: 努力学习的lfk | 来源:发表于2021-08-21 08:19 被阅读0次

    数组(Array)特性
    1.Java语言中的数组是一种引用数据类型,不属于基本数据类型。数组的父类事Object。
    2.数组实际上是一个容器,可以同时容纳多个元素。(数组是一个数据的集合)
    3.数组当中可以存储基本数据类型的数据,也可以存储引用数据类型的数据。
    4.数组因为是引用类型,所以数组对象是在堆内存当中。(数组是存储在堆当中的)
    5.数组当中如果存储的是Java对象的话,实际上存储的是对象的引用(内存地址),不能直接存储Java对象。
    6.数组一旦创建,在Java中规定,长度不可变。(数组长度不可变)
    7.数组分类:一维数组、二维数组、三维数组、多维数组......
    (一维数组较多,二维数组偶尔使用)
    8.所有数组对象都有length属性(Java自带的),用来获取数组中元素的个数。
    9.Java中的数组要求数组中元素的类型统一。比如int类型数组只能存储int类型,Person类型数组只能存储Person类型。
    10.数组在内存存储时,数组中的元素的内存地址是连续的
    11.数组首元素的内存地址作为整个数组对象的内存地址。
    12.数组中每一个元素都是有下标的,下标从0开始,以1递增,最后一个元素的下标为length-1 。
    13.数组是一种简单的数据结构,其优缺点为
    优点
    查询/查找/检索某个下标上的元素时效率极高,可以说是查询效率最高的一个数据结构。
    ①每一个元素的内存地址在空间存储上是连续的。
    ②每一个元素类型相同,所以占用空间大小相同。
    ③知道第一个元素内存地址,知道每一个元素占用空间大小,又知道下标。所以通过一个数学表达式就可以计算出某个下标上元素的内存地址。直接通过内存地址定位元素,所以数组的检索效率是最高的。
    缺点
    由于为了保证数组中每个元素的内存地址连续,所以在数据上随机删除或者增加元素的时候,效率低。(因为随机增删元素会涉及到后面元素统一向前或向后移的操作。)
    数组不能存储大数据量。(因为很难在内存空间上找到一块特别大的连续的内存空间)
    14.声明/定义一维数组
    语法格式:
    int[] array1;
    double[] array2;
    boolean[] array3;
    String[] array4;
    Object[] array5;
    15.初始化一维数组
    ①静态初始化
    int[] array={100,2100,300,55};
    Object[] objs={new Ojbect(),new Ojbect(),new Ojbect()}
    ②动态初始化
    int[] array=new int{5};
    String[] names=new String[6];

    16.二维数组的初始化
    ①静态初始化
    int[][] arr={{1,2,34},{54,4,34,3},{2,34,4,5}}

    Object[][] arr={
    {new Ojbect(),new Ojbect()},
    {new Ojbect(),new Ojbect(),new Ojbect()},
    {new Ojbect(),new Ojbect(),new Ojbect()}
    }
    

    ②动态初始化
    int[][] arr=new int[3][4]
    Object[][] arr=new Object[4][4];

    数组的内存结果

    静态初始化一维数组及存、取、改、遍历👇

    public class ArrayTest01 {
       public static void main(String[] args) {
           //使用静态初始化的方法声明一个int类型的数组
           int[] a1={1,156,12,3465,8631};
           //所有的数组对象都有length属性
           System.out.println("数组中元素的个数:"+a1.length);
    
           //数组中每个元素都有下标,通过下标对数组元素进行存取。
           System.out.println("第一个元素:"+a1[0]);
           System.out.println("最后一个元素:"+a1[a1.length-1]);
           a1[0]=4465;
           a1[a1.length-1]=4165465;
           System.out.println("第一个元素:"+a1[0]);
           System.out.println("最后一个元素:"+a1[a1.length-1]);
    
           //一维数组从头遍历
           for (int i=0;i<a1.length;i++)
               System.out.println(a1[i]);
           //一维数组从尾遍历
           for (int i=a1.length-1;i>=0;i--)
           System.out.println(a1[i]);
       }
    

    ArrayIndexOutOfBoundsException数组下标越界异常


    mian方法上“String[] args”参数的使用(非重点)

    /*
       main方法上面的String[] args有什么用?
       谁负责嗲用main方法?->JVM
       JVM调用main方法的时候会自动传一个String数组过来
    
    */
    public class ArrayTest05 {
       //这个方法程序员负责写出来,JVM负责调用。JVM调用的时候一盯会传一个String数组过来。
       public static void main(String[] args) {
           //JVM默认传递过来的这个数组对象的长度?->默认0
           System.out.println("JVM给传递过来的String数组参数,它这个数组的长度是:"+args.length);
    
           for (int i = 0; i <args.length ; i++) {
               System.out.println(args[i]);
           }
       }
       public static void printLength(String[] args){
           System.out.println(args.length);
       }
    }
    

    其实这个数组是留给用户的,用户可以在控制台上输入参数,这个参数自动会被转换为“String[] args”。
    例如cmd运行程序:java ArrayTest05 abc def xyz
    那么这个时候JVM会自动将“abc def xyz”通过空格的方式进行分离,分离完成之后,自动放到“String[] args”数组当中
    所以main方法上面的String[] args数组主要是用来接受用户输入参数的
    把abc def xyz转换成字符串数字:{"abc","def","xyz"}



    cmd给main方法传值👆,idea给main方法传值👇



    模拟一个系统,该系统必须输入用户名和密码

    public class ArrayTest06 {
      public static void main(String[] args) {
          if (args.length!=2){
              System.out.println("使用该系统时请输入用户名和密码。例如:zhangsan 123");
              return;
          }
           //程序执行到此处说明用户确实提供了用户名和密码,接下来应判断用户名和密码是否正确
           String username=args[0];
           String userpwd=args[1];
           //这样写即使username和userpwd是空也不会出现空指针异常
           if ("zhangsan".equals(username) && "123".equals(userpwd)) {
               System.out.println("登陆成功,欢迎["+username+"]回来!");
           }else
               System.out.println("登陆失败,用户名或密码错误!");
       }
    }
    

    数组中存储引用类型👇实例

    public class ArrayTest07 {
       public static void main(String[] args) {
           Animal a1=new Animal();
           Animal a2=new  Animal();
           Animal[] animals={a1,a2};
           for (int i = 0; i < animals.length; i++) {
               Animal a=animals[i];
               a.move();
               /*animals[i].move();//也可以这样写*/
           }
    
           Animal[] ans=new Animal[2];
           ans[0]=new Animal();
           /*ans[1]=new Product();//Animal数组中只能存放Animal类型,不能存放Product类型*/
           ans[1]=new Cat();//Animal数组中可以存放Cat类型的数据,因为Cat是一个Animal
           
           Animal[] anis={new Cat(),new Bird()};
           //如果调用的方法是父类中存在的方法不需要向下转型。直接使用父类型引用调用即可。
           /*for (int i = 0; i < anis.length; i++) {
               Animal an=anis[i];
               an.move();
           }*/
    
           //调用子类特有的方法,需要向下转型
           for (int i = 0; i <anis.length ; i++) {
               if(anis[i] instanceof Cat){
                   Cat cat=(Cat)anis[i];
                   cat.catchMouse();
               }else if(anis[i] instanceof Bird){
                   Bird bird=(Bird)anis[i];
                   bird.sing();
               }
           }
       }
    
       static class Animal{
           public void move(){
               System.out.println("Animal move...");
           }
       }
       //商品类
       class Product{}
       //猫类
       static class Cat extends Animal{
           public void move(){
               System.out.println("猫在走...");
           }
           public void catchMouse(){
               System.out.println("猫抓老鼠!");
           }
       }
       //鸟类
       static class Bird extends Animal{
           public void move(){
               System.out.println("鸟在飞...");
           }
           public void sing(){
               System.out.println("鸟在唱歌!");
           }
       }
    }
    
    

    利用arraycopy():(五个参数)源数组、源数组起点、目标数组、目标数组起点、拷贝长度



    在Java开发中,数组长度一旦确定不可变,那么数组满了怎么办?➡扩容➡Java中对数组的扩容是先新建一个大容量的数组,然后将小容量数组中的数据依次拷到大数组中。


    一维数组的扩容👇

       public static void main(String[] args) {
           //源数数组
           int[] src={1,11,22,3,4};
           //目标数组
           int[] dest=new int[20];
           //调用JDK System类中的arraycopy方法,来完成数组的拷贝.
           System.arraycopy(src,1,dest,3,2);
    
           for (int i = 0; i <dest.length ; i++) {
               System.out.print(dest[i]+",");
           }
       }
    

    执行结果:0,0,0,11,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,


    结论:数据扩容效率低,因为涉及到拷贝的问题。所以在以后的开发中请注意:尽可能少的进行数组的拷贝。
    可以在床架你数组对象的时候预估一下多长合适,最好预估准确,这样可以减少数组的扩容次数,提高效率。

    二维数组中元素的读和改
    a[二维数组中的一维数组的下标][一维数组的下标]
    a[0][0]:表示第1个一俄日数组中的第1个元素
    a[3][100]:表示第4个一维数组中的第101个元素
    注意:对a[3][100]来说,其中a[3]是一个整体,[100]是前面a[3]执行的结果,再下标100.

    public class ArrayTest10 {
       public static void main(String[] args) {
           //二维数组
           int[][] a={
                   {34,4,65},
                   {100,200,3900,111},
                   {0}
           };
    
           //读取出二维数组a[][]中的第1个一维数组
           int[] a0=a[0];
           //读取一维数组a0[]中的第1个元素
           int a00=a0[0];
           System.out.println(a00);
    
           //由以上代码合并可得
           System.out.println(a[0][0]);
       }
    }
    

    遍历二维数组

    public class ArrayTest11 {
       public static void main(String[] args) {
           String[][] array={
                   {"java","oaracle","c++","python","c#"},
                   {"张三","李四","王五"},
                   {"lucy","jack","rose"}
           };
           //遍历二维数组
           for (int i = 0; i <array.length ; i++) {
               //遍历一维数组
               for (int j = 0; j <array[i].length ; j++) {
                   System.out.print(array[i][j]+",");
               }
               System.out.println();
           }
       }
    }
    

    第一题:
    使用一维数组,模拟栈数据结构。
    要求:
    1.这个栈可以存储Java中的任何引用类型的数据。
    2.在栈中提供push方法模拟弹栈(栈满了,要有提示信息)
    3.在栈中提供pop方法模拟弹栈。(栈空了,要有提示信息)
    4.编写测试程序,new栈对象,调用push pop方法来模拟压栈弹栈的动作。

    public class day23Work1 {
       public static void main(String[] args) {
    
           //一维数组elements[],模拟栈数据结构
           Object[] elements = new Object[3];
           //测试对象
           Object test1 = "Hello";
           Object test2 = "张三";
           Object test3 = "45455";
           Object test4 = "呵呵哒";
    
          //压栈测试
          System.out.println("=======压栈测试========");
          push(elements,test1);
          push(elements,test2);
          push(elements,test3);
          push(elements,test4);
          for (int i = 0; i <elements.length ; i++) {
              System.out.print(elements[i]+"  ");
          }
           System.out.println();
           System.out.println();
           //弹栈测试
           System.out.println("=======弹栈测试========");
           pop(elements);
           pop(elements);
           for (int i = 0; i <elements.length ; i++) {
               System.out.print(elements[i]+"  ");
           }
       }
    
       /*push方法压栈,表示栈中多一个元素。
       如果栈已满,压栈失败。
       这个方法的参数以及返回值类型自定义。*/
       public static void push(Object[] elements, Object data) {
           int sign=0;
           for (int i = 0; i < elements.length; i++) {
               if (elements[i] == null) {
                   elements[i] = data;
                   sign=1;
                   break;
               }
           }
           if ((sign == 1))
               System.out.println("【"+data+"】压栈成功!");
           else
               System.out.println("【"+data+"】压栈失败...");
       }
    
       /*pop方法弹栈,表示栈中少一个元素。
       如果栈已空,弹栈失败。
       这个方法的参数以及返回值类型自定义。*/
       public static void pop(Object[] elements) {
           int sign=0;
           Object temporary = null;
           for (int i = elements.length-1; i >=0; --i) {
               if (elements[i] != null) {
                   temporary=elements[i];
                   elements[i]=null;
                   sign=1;
                   break;
               }
           }
           if ((sign == 1))
               System.out.println("【"+temporary+"】弹栈成功!");
           else
               System.out.println("弹栈失败...");
       }
    }
    

    第一题答案:

    package com.bjpowernode.javase.array.homework;
    
    public class Answer1Test {
       public static void main(String[] args) {
           //创建一个栈对象,初始化容量是10
           Answer1 answer1=new Answer1(10);
           //调用方法压栈
           answer1.push(new Object());
           answer1.push(new Object());
           answer1.push(new Object());
           answer1.push(new Object());
           answer1.push(new Object());
           answer1.push(new Object());
           answer1.push(new Object());
           answer1.push(new Object());
           answer1.push(new Object());
           answer1.push(new Object());
           answer1.push(new Object());
           //调用弹栈方法,最后压的最先弹出
           answer1.pop();
           answer1.pop();
           answer1.pop();
           answer1.pop();
           answer1.pop();
           answer1.pop();
           answer1.pop();
           answer1.pop();
           answer1.pop();
           answer1.pop();
           answer1.pop();
       }
    }
    
    
    package com.bjpowernode.javase.array.homework;
    
    public class Answer1 {
       //封装 第一步:属性私有化,第二步:对外提供set和get方法
       private Object[] elements;
       //栈帧:永远指向栈顶部元素
       private int index;
    
       public Object[] getElements() {
           return elements;
       }
       public void setElements(Object[] elements) {
           this.elements = elements;
       }
       public int getIndex() {
           return index;
       }
       public void setIndex(int index) {
           this.index = index;
       }
    
       //调用有参构造:一维数组默认动态初始化,默认初始化容量是n
       public Answer1(int n) {
           this.elements = new Object[n];
           this.index=-1;
       }
    
       //压栈方法
       public void push(Object object){
           if (this.index>=this.elements.length-1){
               //所有的System.out.println方法输出引用,会自动调用引用的toString方法
               System.out.println("压栈失败,栈已满!");
               return;
           }
           //程序能走到这里,说明栈没有满
           //向栈中加一个元素,栈帧向上移动一个位置。(先自加再操作)
           this.elements[++index]=object;
           System.out.println("压栈【"+object+"】元素成功,栈帧指向->"+index);
       }
    
       //弹栈方法
       public void pop(){
           if (this.index<0) {
               System.out.println("弹栈失败,栈已空!");
               return;
           }
           //程序能够执行到此处说明栈没有空
           System.out.print("弹栈【"+elements[index]+"】元素成功,");
           //栈帧向下移动一位
           index--;
           System.out.println("栈帧指向->"+index);
       }
    }
    

    第一题总结:
    对于成员变量的使用有了更深刻的理解;
    对封装,有了初步的认识;
    代码分离,可读性强。


    第二题:
    为某个酒店编写程序:酒店管理系统,模拟订房、退房、打印所有房间状态等功能。
    1、该系统的用户是:酒店前台
    2、酒店中所有的房间使用一个二维数组来模拟
    3、酒店中的每一个房间应该是一个java对象:Room
    4、每一个房间Room应该有:房间编号、房间类型属性、房间是否空闲
    5、系统应该对外提供的功能:
    ①可以预定房间:用户输入房间编号->订房
    ②可以退订房间:用户输入房间编号->退房
    ③可以查看所有房间的状态:用户输入某个指令应该可以查看所有房间状态。

    public class day23Work2 {
      public static void main(String[] args) {
          System.out.println("=========初始化==========");
          Room[] room=new Room[3];
           initialRoom(room,1001,"单人间","空闲");
           initialRoom(room,1002,"双人间","空闲");
           initialRoom(room,1003,"豪华间","占用");
           selectRoom(room);
          System.out.println();
    
           System.out.println("========订房===========");
           //订房测试
           reserveRoom(room,1005);
           selectRoom(room);
          System.out.println();
           
           System.out.println("=========退房==========");
           //退订测试
           cancelRoom(room,1001);
           selectRoom(room);
       }
    
    
       //记录房间数
       static int pointer=0;
       //房间初始化
       private static void initialRoom(Room[] room,int room_id,String room_type,String room_free){
           Room rm=new Room(room_id,room_type,room_free);
           room[pointer]=rm;
           pointer++;
       }
    
       //订房
       private static void reserveRoom(Room[] room,int room_id){
           //sign用来判断房间id是否存在
           int sign=0;
           for (int i = 0; i <room.length ; i++) {
               if (room_id==room[i].getRoom_id()){
                   if ("占用".equals(room[i].getRoom_free())) {
                       System.out.println("房间id为【" + room_id + "】的房间正在使用,无法预定...");
                       sign=1;
                       break;
                   }
                   else {
                       room[i].setRoom_free("占用");
                       System.out.println("房间id为【"+room_id+"】的房间,预定成功!");
                       sign=1;
                       break;
                   }
               }
           }
           if (sign==0)
               System.out.println("id为【"+room_id+"】的房间不存在,请重新输入房间id。");
       }
    
    
       //退房
       private static void cancelRoom(Room[] room,int room_id){
           //sign用来判断房间id是否存在
           int sign=0;
           for (int i = 0; i <room.length ; i++) {
               if (room_id==room[i].getRoom_id()){
                   if ("空闲".equals(room[i].getRoom_free())) {
                       System.out.println("房间id为【" + room_id + "】的房间处于空闲,无法退订!请检查是否输错房间id...");
                       sign=1;
                       break;
                   }
                   else {
                       room[i].setRoom_free("空闲");
                       System.out.println("房间id为【"+room_id+"】的房间,退订成功!");
                       sign=1;
                       break;
                   }
               }
           }
           if (sign==0)
               System.out.println("id为【"+room_id+"】的房间不存在,请重新输入房间id。");
       }
    
       //打印房间信息
    private static void selectRoom(Room[] room){
        for (int i = 0; i < room.length; i++) {
            System.out.println(room[i]);
        }
      }
    }
    
    //房间类
    class Room{
       private int room_id;
       private String room_type;
       private String room_free;
    
       public int getRoom_id() {
           return room_id;
       }
    
       public void setRoom_id(int room_id) {
           this.room_id = room_id;
       }
    
       public String getRoom_type() {
           return room_type;
       }
    
       public void setRoom_type(String room_type) {
           this.room_type = room_type;
       }
    
       public String getRoom_free() {
           return room_free;
       }
    
       public void setRoom_free(String room_free) {
           this.room_free = room_free;
       }
    
       public Room() {}
       public Room(int room_id, String room_type, String room_free) {
           this.room_id = room_id;
           this.room_type = room_type;
           this.room_free = room_free;
       }
    
       @Override
       public String toString() {
           return  "room_id:" + room_id +
                   ", room_type:" + room_type +
                   ", room_free:" + room_free  ;
       }
    }
    

    第二题答案:

    package com.bjpowernode.javase.array.homework;
    
    import java.util.Scanner;
    
    public class Answer2 {
       public static void main(String[] args) {
           //创建酒店对象
           Hotel hotel=new Hotel();
           /*
              首先输出一个欢迎页面
           */
           System.out.println("欢迎使用酒店管理系统,请认真阅读以下使用说明");
           System.out.println("功能编号对应的功能:[1]表示查看房间列表。[2]表示订房。[3]表示退房。[0]表示退出系统。");
           Scanner s=new >Scanner(System.in);
           while (true){
               System.out.print("请输入功能编号:");
               int i=s.nextInt();
               if (i == 1) {
                   //[1]表示查看房间列表
                   hotel.print();
               }else if (i == 2){
                   //[2]表示订房
                   System.out.print("请输入预定房间编号:");
                   i=s.nextInt();
                   hotel.order(i);
               }else if (i == 3) {
                   //[3]表示退房
                   System.out.print("请输入退订房间编号:");
                   i=s.nextInt();
                   hotel.exit(i);
               }else if (i == 0) {
                   //[0]表示退出系统
                   System.out.println("再见,欢迎下次使用!");
                   return;
               }else {
                   //输入非法字符
                   System.out.println("非法字符!请重新输入!");
               }
           }
       }
    }
    
    package >com.bjpowernode.javase.array.hom>ework;
    
    //酒店对象,酒店中有二维数组,二维数组模拟大厦
    public class Hotel {
       /*二维数组,模拟大厦所有房间*/
       private Room[][] rooms;
       //盖楼通过构造方法盖
       public Hotel(){
           //一共有基层,每层的房间类型是什么,每个房间的编号是什么
           rooms = new  Room[3][10];
           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 {
                       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++) {
                   Room room= rooms[i][j];
                   System.out.print(room);
               }
               System.out.println();
           }
       }
    
       //订房方法:酒店前台需要传递一个房间编号过来
       public void order(int roomNO){
           //订房最主要的是将房间对象的status修改为false
           rooms[roomNO/100-1][roomNO%100-1].setStatus(false);
           System.out.println(roomNO+"已订房");
       }
    
       //退房方法
       public void exit(int roomNO){
           //退房最主要的是将房间对象的status修改为true
           rooms[roomNO/100-1][roomNO%100-1].setStatus(true);
           System.out.println(roomNO+"已退房");
       }
    }
    
    package >com.bjpowernode.javase.array.homework;
    
    import java.util.Objects;
    
    public class Room {
       /* 房间编号
       1楼:101 102 103 104 105 106 ..
       2楼:101 102 103 104 105 106 ..
       3楼:101 102 103 104 105 106 ..
       */
       private int room_id;
       /*房间类型:标准间、单人间、总统套件*/
       private String type;
       /*房间状态
       true表示空闲,房间可以被预定。
       false表示占用,房间不能被预定。*/
       private boolean status;
       //set和get方法
       public int getRoom_id() {
           return room_id;
       }
       public void setRoom_id(int room_id) {
           this.room_id = room_id;
       }
       public String getType() {
           return type;
       }
       public void setType(String type) {
           this.type = type;
       }
       public boolean isStatus() {
           return status;
       }
       public void setStatus(boolean status) {
           this.status = status;
       }
       //构造方法
       public Room() {}
       public Room(int room_id, String type, boolean status) {
           this.room_id = room_id;
           this.type = type;
           this.status = status;
       }
       //equals方法
       @Override
       public boolean equals(Object o) {
           if (this == o) return true;
           if (o == null || getClass() != o.getClass()) return false;
           Room room = (Room) o;
           return room_id == room.room_id &&
                   status == room.status;
       }
       //toString方法
       @Override
       public String toString() {
           return  "["+room_id+","+type+","+(status?"空闲":"占用")+"]";
       }
    }
    

    第二题总结:
    界面做得非常不友好,且没有让酒店前台参与;
    对于类和方法的理解不够透彻;
    二维数组初始化做得也不够好。


    笔记来源:B站动力节点Java零基础教程视频

    视频链接:https://www.bilibili.com/video/BV1Rx411876f

    相关文章

      网友评论

          本文标题:JavaSE进阶-02-数组

          本文链接:https://www.haomeiwen.com/subject/gzutiltx.html