数组(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?"空闲":"占用")+"]"; } }
第二题总结:
界面做得非常不友好,且没有让酒店前台参与;
对于类和方法的理解不够透彻;
二维数组初始化做得也不够好。