目录
数组
二维数组
总结
作业
Arrays工具类
数组总结 及 静态初始化一维数组
/*
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、数组这种数据结构的优点和缺点是什么?
优点:查询/查找/检索某个下标上的元素时效率极高。可以说是查询效率最高的一个数据结构
为什么效率高?
1、每一个元素的内存地址在空间存储上是连续的
2、每一个元素类型相同,所以占用空间大小一样
3、知道第一个元素内存地址,知道每一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址,直接通过内存地址定位元素,所以数组的检索率是最高的。
数组中存储100个元素,或存储100万个元素,在元素查询/检索方面,效率是相同的。因为数组中元素查找的时候不会一个一个找,是通过数学表达式计算出来的(算出一个内存地址,直接定位的)
缺点:
1、由于为了保证数组中每个元素的内存地址连续,所以在数组上随机增加/删除元素时,效率较低,
因为随机增删会涉及到后面元素统一向前或向后位移的操作。
2、数组不能存储大数据
因为很难在内存空间上找到一块特别大的连续的内存空间。
注意:对于数组中最后一个元素的增删,是没有效率影响的。
14、怎么声明/定义一个一维数组
语法格式:
int[] array1;
double[] array2;
boolean[] array3;
String[] array4;
Object[] array5;
15、怎么初始化一个一维数组?
包括两种方式:静态初始化一维数组,动态初始化一维数组。
静态初始化语法格式:
int[] array = {100,2100,200,30};
动态初始化语法格式:
//初始化一个5长度的int类型数组,每个元素默认值:0
int[] array = new int[5]; //这里的5表示数组的元素个数。
//初始化一个6个长度的String类型数组,每个元素默认值:null
String [] names = new String[6]
*/
public class ArrayText01 {
public static void main(String[] args){
//声明一个int类型的数据,使用静态初始化的方式
int[] ii = {1,100,200,30,49,500};
//这是C++风格,虽然可以运行,但不建议在java中使用。
//int i[] = {1,100,200,30,49,500};
//所有的数组对象都有length属性
System.out.println("数组i中元素的个数:"+ii.length);
//数组中每一个元素都有下标,通过下标堆数组中的元素进行存和取。
//取(读)
System.out.println("i数组中 第一个元素"+ii[0]);
System.out.println("i数组中 最后一个元素"+ii[5]);
System.out.println("i数组中 最后一个元素"+ii[ii.length-1]);
//存(改)
ii[0] = 111;
ii[ii.length-1] = 888;
System.out.println("i数组中 第一个元素"+ii[0]);
System.out.println("i数组中 最后一个元素"+ii[5]);
//一维数组 取遍历
for(int i = 0;i < ii.length;i++){//i<6,取到5就停止了。
System.out.println("ii数组中第"+(i+1)+"个元素:"+ii[i]);// i是从 0 到 5,是下标
}
//下标为6表示第七个元素,第七个元素没有,下标越界了,会出现什么异常呢?
//System.out.println(ii[6]);//ArrayIndexOutOfBoundsException 下标越界异常
//从最后一个元素遍历到第一个元素。
for(int i =ii.length-1 ; i>=0 ;i--){
System.out.println("ii数组中第"+(i+1)+"个元素:"+ii[i]);
}
}
}
动态初始化一维数组,以及何时使用静态/动态初始化数组的方式。
/*
关于每个类型的默认值
数据类型 默认值
------------------------------------
byte 0
short 0
int 0
long 0L
float 0.0F
double 0.0
boolean false
char \u0000
引用数据类型 null
什么时候采用静态初始化方式,什么时候采用动态初始化方式?
当创建一个数组时:
确定数组中存储哪些具体的元素时,采用静态初始化的方式。
不确定将来数组中存储哪些数据,可以采用静态初始化的方式,预先分配空间。
*/
public class ArrayText02 {
public static void main(String[] args){
//声明/定义一个数组,采用动态初始化的方式创建
int[] ii = new int[4]; //创建一个长度为4的int数组,数组中每个元素的默认值是0
//遍历数组
for (int i = 0 ; i < ii.length ; i++) {
System.out.println("ii数组中下标为"+i+"的元素是:"+ii[i]);
}
//后期赋值
ii[0] = 111;
ii[1] = 222;
ii[2] = 333;
ii[3] = 444;//注意下标不要越界
for (int i = 0 ; i < ii.length ; i++) {
System.out.println("ii数组中下标为"+i+"的元素是:"+ii[i]);
}
//初始化一个Object类型的数组,采用动态初始化方式
Object[] objs = new Object[3]; //3个长度,动态初始化,所以每个元素默认值是null
for (int i = 0 ; i < objs.length ; i++) {
System.out.println("objs数组中下标为"+i+"的元素是:"+objs[i]);
}
System.out.println("====================");
//
String[] strS = new String[3];
for (int i = 0 ; i < strS.length ; i++) {
System.out.println("strS数组中下标为"+i+"的元素是:"+strS[i]);
}
//采用静态初始化的方式
String[] strS2 = {"abc","def","xyz"};
for (int i = 0 ; i < strS2.length ; i++) {
System.out.println("strS2数组中下标为"+i+"的元素是:"+strS2[i]);
}
//存储Object ,采用静态初始化呢?
/*
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
Object[] objects = {o1,o2,o3};
*/
//以上还可以简化为:
Object[] objects = {new Object(),new Object(),new Object()};
for (int i = 0 ; i < objects.length ; i++) {
System.out.println("objects数组中下标为"+i+"的元素是:"+objects[i]);
/*
相当于: Object o = objects[i];
System.out.println(o);
*/
/*
输出结果:objects数组中下标为0的元素是:java.lang.Object@1b6d3586
objects数组中下标为1的元素是:java.lang.Object@4554617c
objects数组中下标为2的元素是:java.lang.Object@74a14482
object[i] 输出的是此数组中存储的对象,即o1、o2、o3。输出引用会出输出这个对象的内存地址
而数组刚好就是存储内存地址的。
*/
}
}
}
当一个方法的参数类型为数组时,如何传参数
//当一个方法上,参数的类型是数组时,我们应该如何传递参数。
public class ArrayText03 {
//java的main方法编写方式
//public static void main(String[] args) {}
//还可以采用C++的语法格式!
public static void main(String args[]) {
//java风格
int[] ii = {1,2,3};
for (int i = 0; i
当一个方法的参数是一个数组时,我们还可以采用这种方式传输
//当一个方法的参数是一个数组时,我们还可以采用这种方式传输
public class ArrayText04 {
public static void main(String[] args){
//静态初始化一维数组
int[] ii = {1,2,3};
printArray(ii);
//动态初始化一维数组
int[] ii2 = new int[2];
printArray(ii2);
printArray(new int[3]);
System.out.println("=================");
//没有这种语法
//printArray({1,2,3,4});
//如果直接传递一个静态数组的话,必须这样写:
printArray(new int[]{1,2,3,4});
}
//这里为什么用静态方法?
//方便,不需要new对象。
public static void printArray(int[] array){
for (int i = 0; i
main方法中的String[] args 作用:接收用户输入参数
/*
main方法上面的String[] args 有什么用?
分析一下:谁负责调用main方法——JVM
JVM调用main方法时,会自动传一个String数组过来
*/
public class ArrayText05 {
//这个方法是程序员负责写出来,JVM负责调用,JVM调用的时候,一定会传一个String数组过来
public static void main(String[] args){
//JVM默认传过来的这个数组对象的长度:默认0
//通过测试得出:args不为null
System.out.println("JVM给传递过来的String数组参数,它这个数组长度是:"+ args.length);
//以下这一行代码表示的含义:数组对象创建了,但是数组中没有任何数据。
String[] strS = new String[0];
String[] strS2 = {}; //静态初始化数组,里面没有传东西
printLength(strS); //0
printLength(strS2); //0
/*
这个数组什么时候里面会有值呢?
其实这个数组是留给用户的,用户在控制台上输入参数,这个参数会自动被转换为“String[] args”
例如在cmd中这样运行程序:java ArrayText05 abc def xyz
那么这个时候JVM会自动将“abc def xyz” 通过空格的方式进行分离,分离完之后,自动放到“String[] args”数组当中
所以main方法上面的String[] args 数组主要是用来接收用户输入参数的
把abc def xyz 转换成字符串数组:{"abc","def","xyz"}
*/
//遍历数组
for (int i = 0; i
模拟一个系统,假设这个要使用必须输入用户名和密码
//模拟一个系统,假设这个系统要使用,必须输入用户名和密码
public class ArrayText06 {
//用户名和密码输入到String[] args数组当中
public static void main(String[] args){
if(args.length != 2){
System.out.println("使用该系统时请输入程序参数,参数中包括用户名和密码信息,例如:zhangsan 123");
}
//程序执行到这里说明用户确实提供了用户名和密码,接下来应该判断用户名和密码是否正确
//取出用户名
String useName =args[0];
//取出密码
String password =args[1];
//假设用户名是admin,密码是123的时候表示登录成功,其他一律失败。
//判断两个字符串是否相等,需要使用equals方法
//(useName.equals("admin")与(password.equals("123")
//以下这样编写可以避免空指针异常
//采用以下编码风格,即使userName和password都是null,也不会出现空指针异常。
if("admin".equals(useName)){
if("123".equals(password)){
System.out.println("登录成功");
}else {
System.out.println("密码输入有误,请确认后重新输入");
}
}else {
System.out.println("用户名输入错误");
}
}
}
数组中存储的类型为:引用数据类型时
//一维数组的深入,数组中存储的类型为:引用数据类型。
//对于数组来说,实际上只能存储java对象的“内存地址”,数组中存储的每个元素都是“引用”
public class ArrayText07 {
public static void main(String[] args){
//创建一个Animal类型的数组
Animal a1 = new Animal();
Animal a2 = new Animal();
Animal[] animals = {a1,a2};
//对Animal数组进行遍历
for (int i = 0; i
数组的扩容,数组的拷贝
/*
关于一维数组的扩容
在java开发中,数组长度一旦确定后不可再改变,那么数组满了之后怎么办?
数组满了,需要扩容
java中对数组的扩容:
先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中。
结论:数组扩容效率较低,因为涉及到了拷贝的问题,所以在以后的开发中请注意:尽可能少的进行数据的拷贝。
可以在创建数组对象的时候预估计一下多长合适,最好预估准确,这样可以减少数组的扩容次数。提高效率。
*/
public class ArrayText08 {
public static void main(String[] args){
//java中数组扩容时使用System.arraycopy()方法进行拷贝
// System.arraycopy(5个参数);
// public static native void arraycopy(
// Object src, //拷贝源,需要扩容的小容量数组
// int srcPos, //从哪个位置开始,起始元素下标
// Object dest, //拷贝目标:要拷贝到的那个大容量数组中
// int destPos, //从哪个位置开始存放
// int length); //要拷贝的长度
//拷贝源(从这个数组中拷贝,需要扩容的数组)
int[] src = {1,22,33,4,5};
//拷贝目标(拷贝到这个目标数组中)
int[] dest = new int[10]; //初始化一个长度为10的数组,每一个元素默认值为0
//调用JDK中System类中的arraycopy方法,来完成数组的拷贝
System.arraycopy(src,1,dest,3,2);
//遍历目标数组
for(int i = 0; i
二维数组的初始化
/*
关于java中的二维数组
1、二维数组其实是一个特殊的一维数组,特殊在这个一维数组当中的每一个元素是一个一维数组。
2、三维数组是什么?
三维数组是一个特殊的二维数组,特殊在这个二维数组中每一个元素是一个一维数组。
实际的开发中使用最多的就是一维数组。二维数组也很少使用。三维数组几乎不用。
3、二维数组静态初始化
int[][] array = {{1,1,1},{10,20,30},{4,3,65,12,3,3}}
*/
public class ArrayText09 {
public static void main(String[] args){
//一维数组
int[] array = {100,200,300};
System.out.println(array.length);//3
//二维数组
//里面的是四个一维数组,可以有n多个一维数组。
int[][] a = {
{100,200,300},
{10,30,50},
{99,44,66,75,23},
{0}
};
System.out.println("------------------");
System.out.println(a.length);//4
System.out.println(a[0].length);//3 这是a这个二维数组中下标为0的元素的那个一维数组的长度
System.out.println(a[1].length);//3
System.out.println(a[2].length);//5
System.out.println(a[3].length);//1
int[][] a2 = {
{100,200,300},
{10,30,50},
{99,44,66,75,23},
{0},
{93,234,2938,493},
{102,3948,2}
};
System.out.println(a2.length);//6
}
}
二维数组中元素的读和改
/*
关于二维数组中元素的:读和改
a[二维数组中一维数组的下标][二维数组中的一维数组中的元素下标]
a[0][0]:表示第一个一维数组中的第一个元素。
a[3][100]:表示第四个一维数组中的第101个元素。
对于a[3][100]来说,其中a[3]是一个整体,[100]是前面a[3]直接结束的结果然后再下标100,
*/
public class ArrayText10 {
public static void main(String[] args){
//二维数组
int[][] a = {
{102,192,394},
{123,293,49},
{10,203,30}
};
//请取出以上二维数组中的第一个一维数组,以及第一个一维数组中的第一个元素
int[] a1 = a[0];
System.out.println(a1[0]);//第一个元素
//合并:
System.out.println(a[0][0]);
//取出第二个一维数组中的第三个元素
System.out.println("第二个一维数组中的第三个元素:"+a[1][2]);
//取出第3个一维数组中的第1个元素
System.out.println("第3个一维数组中的第1个元素:"+a[2][0]);
//改
a[2][0] = 1111111;
//修改数组3中的第一个元素后再次取出
System.out.println("修改后的第3个一维数组中的第1个元素:"+a[2][0]);
//注意下标不能越界
}
}
二维数组的遍历
//二维数组的遍历
public class ArrayText11 {
public static void main(String[] args) {
String[][] strings ={
{"java","oracle","c++","python","C#"},
{"张三","李四","王五","赵七"},
{"lucy","ben","jack"},
};
//遍历二维数组
for (int i = 0; i
动态初始化二维数组
//动态初始化二维数组
public class ArrayText12 {
public static void main(String[] args){
//3行四列
//三个一维数组,每一个一维数组中有四个元素
int[][] ints = new int[3][4];
printArray(ints);
//二维数组的遍历
// for (int i = 0; i
数组总结:
1、数组的优点和缺点,并且要理解为什么。
空间存储上,内存地址是连续的
每个元素占用的空间大小相同
知道首元素的内存储地址
通过下标可以计算出偏移量
通过一个数学表达式,就可以快速计算出某个下标位置上元素的内存地址,直接通过内存地址定位,效率非常高
优点:检索效率高
缺点:随机增删效率低,数组无法存储大数据量
注意:数组最后一个元素的增删效率不受影响。
2、一维数组的静态初始化和动态初始化
静态初始化:
int[] array = {1,2,3,4};
Object[] objs ={new Object(),new Object(),new Object()};
动态初始化:
int[] array = new int[4]; //四个长度的一维数组,每个元素默认值0
Object[] objs = new Object(4); //四个长度,每个元素默认值null
3、一维数组的遍历:
for(int i = 0; i< array.length ; i++){
System.out.println(array[i]);
}
4、二维数组的静态初始化 、动态初始化:
静态初始化:
int[][] array = {
{1,2,3,4},
{29,293,04,3984,38},
{10,293,84,85,919},
{0,4,3}
}
Object[][] array = {
{new Object(),new Object()},
{new Object(),new Object(),new Object(),new Object()},
{new Object(),new Object(),new Object()},
{new Object(),new Object(),new Object(),new Object(),new Object()}
}
动态初始化:
int[][] array = new int[3][4];
Object[][] array = new Object[4][4];
//Animal类型数组,里面可以存储Animal类型对象,以及Animal类型的子类型都可以。
Animal[][] array = new Animal[5][2];
5、二维数组的遍历
for(int i = 0; i < array.length ; i++){ //外层for循环负责遍历二维数组中的元素。
//内层for循环负责遍历一维数组里的元素
for(int j = 0 ; j
第一题:使用一维数组,模拟栈数据结构
自己做的
/*
第一题:
编写程序,使用一维数组,模拟栈数据结构。
要求:
1、这个栈可以存储java中的任何引用类型的数据。
2、在栈中提供push方法模拟压栈。(栈满了,要有提示信息。)
3、在栈中提供pop方法模拟弹栈。(栈空了,也有有提示信息。)
4、编写测试程序,new栈对象,调用push pop方法来模拟压栈弹栈的动作。
public class MyStack{ // 栈类
// 提供一个数组来存储栈中的元素
Object[] elements;
// 栈帧(永远指向栈顶部的元素)
// 每加1个元素,栈帧+1
// 每减1个元素,栈帧-1
int index;
// 构造方法
// 构造方法是不是应该给一维数组一个初始化容量。
// push方法(push方法压栈)
// 压栈表示栈中多一个元素。
// 但是栈如果已满,压栈失败。
// 这个方法的参数以及返回值类型自己定义。
// pop方法(pop方法弹栈)
// 弹栈表示栈中少一个元素。
// 但是栈如果已空,弹栈失败。
// 这个方法的参数以及返回值类型自己定义。
}
main(){
测试...
}*/
public class ArrayHomeWork1 {
public static void main(String[] args) {
MyStack ms1 = new MyStack();
System.out.println("压栈————————————————");
//压栈
ms1.push(new Object());
System.out.println(ms1.elements[0]);
System.out.println(ms1.index);
ms1.push(new Object());
System.out.println(ms1.elements[1]);
System.out.println(ms1.index);
System.out.println(ms1.elements[ms1.index-1]);
ms1.push(new Object());
ms1.push(new Object());
ms1.push(new Object());
ms1.push(new Object());
ms1.push(new Object());
ms1.push(new Object());
ms1.push(new Object());
ms1.push(new Object());
System.out.println(ms1.elements[9]);
ms1.push(new Object());
System.out.println(ms1.elements[ms1.index-1]);
System.out.println("-------------------------------------------");
MyStack ms2 = new MyStack(2);
System.out.println(ms2.elements.length);
ms2.push(new Object());
ms2.push(new Object());
ms2.pop();
ms2.pop();
}
}
//每创建一个栈对象,
class MyStack{ //栈类
//因为要求java中所有的数据类型都可以存储,所以数组类型要定义为Object类型的数组
Object[] elements ;
//栈帧,指向最顶部的元素。
int index;
//默认创建一个长度为10的一维数组
public MyStack(){
this.elements =new Object[10];
}
//创建栈对象时,传进来一个数,把这个数作为栈的容量
public MyStack(int i){
//默认创建一个一位数组
this.elements = new Object[i];
}
//压栈方法:push,表示在数组中增加一个元素
public void push(Object object){
if(this.index ==this.elements.length){
System.out.println("栈满了,压栈失败");
}else{
//压栈时,栈帧每次+1,此时传递一个元素进去,用下标接收,下标=栈帧-1,
elements[index] = object;
this.index += 1;
System.out.println("压栈成功");
}
}
//弹栈方法 :pop,表示在数组中删除一个元素
public void pop(){
//弹栈时,帧里有东西才会弹,如果没有,则弹栈失败。即:index大于0时才会弹栈,如果index为0,则说明栈中没有元素了
//所以大于0才会弹栈,弹栈后,栈里的元素-1,
if(this.index > 0){
this.index -= 1;
elements[index] = null;
System.out.println("弹栈成功");
if(index == 0){
System.out.println("栈干净了");
}
}else {
System.out.println("栈已空,弹栈失败");
}
}
}
根据视频做出来的
/*
编写程序,使用一维数组,模拟栈数据结构。
要求:
1、这个栈可以存储java中的任何引用类型的数据。
2、在栈中提供push方法模拟压栈。(栈满了,要有提示信息。)
3、在栈中提供pop方法模拟弹栈。(栈空了,也有有提示信息。)
4、编写测试程序,new栈对象,调用push pop方法来模拟压栈弹栈的动作。
5、假设栈的默认初始化容量是10,(请注意无参构造方法的编写方式)
*/
public class MyStack {
//向栈中存储元素,我们这里使用一维数组模拟。存到栈中,就表示存储到数组中。因为数组是我们学习java的第一个容器
//为什么选择Object类型数组?因为这个栈可以存储java中的任何引用数据类型的数据。
//new Animal() 对象可以放进去,new Person()对象也可以放进去,因为Animal和Person的超级父类就是Object。
//包括String也可以放进去,因为String父类也是Object。
//注意:“abc”这是一个字符串对象,字符串在java中有优待,不需要new也是一个对象。“abc”字符串也是java对象,属于String类型。
private Object[] elements ;//private Object[] elements = new Object[10]; 也可以在这里直接赋值。
//栈帧,永远指向栈顶部元素 赋值-1,与下标同步增加。
private int index = -1;
//无参构造方法
public MyStack() {
//一维数组动态初始化,默认初始化为10。
this.elements = new Object[10];
}
public MyStack(int i) {
this.elements = new Object[i];
}
//set和get也许用不上,但你必须写上,这是规矩。使用IDEA生成就可以。
//封装第一步:属性私有化,第二步:对外提供set和get方法。
public Object[] getElements() {
return elements;
}
public void setElements(Object[] elements) {
this.elements = elements;
}
//压栈的方法,object:被压入的元素
public void push(Object object){
if(this.index >= this.elements.length-1){
System.out.println("栈已满,压栈失败");
return;
}
//程序执行到这里,说明栈里还有空间,可以继续加元素
//this.index++ ;
//elements[index] = object;
//可合并为: ++index ,表示先加1再赋值,默认index为-1,压入后index为0,与压入元素的下标相同
elements[++index] = object;
//所有的System.out.println()方法执行时,如果输出引用的话,自动调用引用的toString()方法。
System.out.println("元素 "+object+" 压栈成功,栈帧此时指向"+index);
}
//弹栈方法
public void pop(){
if(index <= -1){
System.out.println("栈已空,弹栈失败");
return;
}
//程序执行到这里说明栈还没空,
System.out.println("元素 " + elements[index] +" 弹栈成功,此时栈帧指向:"+ --index);
}
}
测试
public class MyStackText {
public static void main(String[] args){
//创建一个栈对象
MyStack stack = new MyStack();
//调用方法压栈
stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());
stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());
//压满之后
stack.push(new Object()); //栈已满,压栈失败
//弹栈
stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();
stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();
//栈空后
stack.pop();//栈已空,弹栈失败
//调用有参构造创建一个栈对象
MyStack stack2 = new MyStack(3);
//压栈
stack2.push(new Object());stack2.push(new Object());stack2.push(new Object());
//栈满
stack2.push(new Object());//栈已满,压栈失败
//弹栈
stack2.pop();stack2.pop();stack2.pop();
//栈空
stack2.pop();//栈已空,弹栈失败
}
}
第二题:酒店管理系统
自己做没什么思路,根据老师说的做出来的
房间类
// 酒店房间
public class Room {
/*
* 房间编号:
* 1楼:101 102 103 104 105.....
* 2楼:201 202 203 204 205......
* 3楼:......
* ......
* */
private int no;
//房间类型:单人间 双人间 总统套房
private String type;
/*
* 房间状态:
* true:表示空闲,房间可以被预定
* flase:表示房间已被使用,不能再被订
* */
private boolean status;
//构造方法
public Room() {
}
public Room(int no, String type, boolean status) {
this.no = no;
this.type = type;
this.status = status;
}
//set和get方法
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
//idea工具类型的boolean类型的变量,生成的get方法的方法名:isXxx()
//public boolean isStatus() { return status; }
//如果你不喜欢,可以修改为:getXxx()
public boolean getStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
/**
* 自己做的时候没想到这里,不知道如何打印房间状态。
*/
//equals方法重写
//equals是用来比较两个对象是否相等的
//如何比较,自己定。你认为两个房间编号相同,就表示同一个房间,那么你写代码编写比较房间编号就可以。
public boolean equals(Object obj) {
if (obj == null ||!(obj instanceof Room)) return false;
if (this ==obj) return true;
Room room =(Room)obj;
//如果两个房间的房间号相同,我们就说他们是同一个房间
return this.getNo() == room.getNo() ;
}
//toString方法重写
//toString方法的目的是将java对象转换成字符串形式。
//如何转,转成什么格式,自己定。目的:简单,清晰明了。
//如:这里不要看对象的内存地址。要看具体的信息
public String toString() {
//return "[101,单人间,使用中]";
//return "[102,双人间,空闲]";
//动态打印出房间状态信息(把一个变量塞到一个字符串当中,口诀:加一个双引号,双引号中间加 + ,两个加号中间加变量名 【"+name+"】)
//return "["+no+","+type+","+status+"]";
//status这里true时输出:空闲,false时输出:使用中,所以使用三目运算符
return "["+no+","+type+","+(status ? "空闲":"使用中")+"]";
//语法规则:布尔表达式?表达式1:表达式2
//当布尔表达式的结果是true时,选择表达式1作为整个表达式的执行结果。
//当布尔表达式的结果是false时,选择表达式2作为整个表达式的执行结果。
}
//编写一个临时程序测试一下,测试完删除
/* public static void main(String[] args) {
Room room = new Room(101,"单人间",true);
Room room1 = new Room(102,"豪华VIP套间",false);
System.out.println(room.toString());
System.out.println(room1);//room1是一个引用,输出引用时,会自动调用引用的toString()方法。
System.out.println(room.equals(room1));
//查看一个类中的所有的属性和方法快捷键:ctrl +F12
}*/
}
酒店类
import java.util.Scanner;
//酒店对象,酒店中有二维数组,二维数组模拟大厦
public class Hotel {
//二维数组,模拟大厦的房间
private Room[][] rooms;
//盖楼通过构造方法来盖
public Hotel(){
//一共有几层,每层的房间是什么,每个房间的编号是什么。
//我们可以先写死,一共三层,一层是单人间,二层是双人间,三层是总统套房。每层有10个房间
rooms = new Room[3][10];
//创建30个对象,放到数组当中。
//怎么放?二维数组遍历
for(int i = 0; i
测试类
import java.lang.reflect.Parameter;
import java.util.Scanner;
/*
第二题:(java软件工程师人生路上第一个小型项目。锻炼一下面向对象。)
为某个酒店编写程序:酒店管理系统,模拟订房、退房、打印所有房间状态等功能。
1、该系统的用户是:酒店前台。
2、酒店使用一个二维数组来模拟。“Room[][] rooms;”
3、酒店中的每一个房间应该是一个java对象:Room
4、每一个房间Room应该有:房间编号、房间类型、房间是否空闲.
5、系统应该对外提供的功能:
可以预定房间:用户输入房间编号,订房。
可以退房:用户输入房间编号,退房。
可以查看所有房间的状态:用户输入某个指令应该可以查看所有房间状态。
*/
public class HotelManagementSystem {
public static void main(String[] args) {
Hotel hotel = new Hotel();
// hotel.printStatus();
//
// hotel.order(102);
// System.out.println("=-------------------------------====");
// hotel.printStatus();
//首先输出一个欢迎界面
System.out.println("欢迎使用酒店管理系统,请认真阅读使用说明");
while (true) {
System.out.println("编号对应相应功能:【1】表示查看房间列表、【2】订房、【3】退房、【4】打印正在使用中的房间、【0】退出系统");
Scanner s = new Scanner(System.in);
int i = s.nextInt();
if(i == 1){
hotel.printStatus();
}else if(i == 2){
System.out.println("请输入所要订的房间号");
Scanner roomNo = new Scanner(System.in);
hotel.order(roomNo.nextInt());
}else if(i == 3){
System.out.println("请输入要退的房间号");
Scanner roomNo = new Scanner(System.in);
hotel.out(roomNo.nextInt());
}else if(i == 0){
System.out.println("谢谢使用本系统,欢迎下次再来");
return;
}else if(i == 4){
System.out.println("正在使用中的房间:");
hotel.printFalse();
}else{
System.out.println("输入有误,请重新输入");
}
}
}
}
常见的算法:
排序算法:
冒泡排序算法
选择排序算法
查找算法:
二分法查找
以上算法在以后的java实际开发中我们不需要使用的。因为java已经封装好了,直接调用就可以。以后面试时可能会碰到。
算法实际上在java中不需要精通,因为java中已经封装好了,要排序就调用方法就行。例如:java中提供了一个数组工具类:
java.util.Arrays
Arrays是一个工具类
其中有一个sort方法,可以排序。静态方法,直接使用类名调用就可以。
简单的排序
import java.util.Arrays;
//使用一下SUN公司提供的数组工具类:java.util.arrays;
public class ArraysText01 {
public static void main(String[] args){
int[] ints = {2,8,4,6,193,123,39};
//工具类中的方法大部分都是静态的
Arrays.sort(ints);
//遍历输出
for (int i = 0; i
冒泡排序算法
/*
冒泡排序算法
1、每一次循环结束之后,都要找出最大的数据,放到参与比较的这堆数据的最右边。(冒出最大的那个气泡)
2、核心:
拿着左边的数字和右边的数字比对,当 左边 > 右边 的时候,交换位置。
原始数据:
3,2,7,6,8
第一次循环:(最大的跑到最右边)
2,3,7,6,8 3和2比较,2<3,所以2和3交换位置
2,3,7,6,8 虽然不需要交换位置:但是3和7还是需要比较一次
2,3,6,7,8 6<7 6和7交换位置
2,3,6,7,8 虽然不需要交换位置:但是7和8还是需要比较一次
经过第一次循环,此时剩下参与比较的数据:2,3,6,7
第二次循环
2,3,6,7 2和3比较,不需要交换位置
2,3,6,7 3和6比较,不需要交换位置
2,3,6,7 6和7比较,不需要交换位置
经过第二次循环,此时剩下参与比较的数据:2,3,6
第三次循环
2,3,6 2和3比较,不需要交换位置
2,3,6 3和6比较,不需要交换位置
经过第三次循环,此时剩下参与比较的数据:2,3
第四次循环
2,3 2和3比较,不需要交换位置
原始数据:9 8 10 7 6 0 11
第一次循环:
8 9 10 7 6 0 11 第1次比较后:交换
8 9 10 7 6 0 11 第2次比较后:不交换
8 9 7 10 6 0 11 第3次比较后:交换
8 9 7 6 10 0 11 第4次比较后:交换
8 9 7 6 0 10 11 第5次比较后:交换
8 9 7 6 0 10 11 第6次比较后:不交换
最终冒出的最大数据在右边:11
经过第一次循环,此时剩下参与比较的数据: 8 9 7 6 0 10
第二次循环
8 9 7 6 0 10 第1次比较后:不交换
8 7 9 6 0 10 第2次比较后:交换
8 7 6 9 0 10 第3次比较后:交换
8 7 6 0 9 10 第4次比较后:交换
8 7 6 0 9 10 第5次比较后:不交换
最终冒出的最大数据在右边:10
经过第二次循环,此时剩下参与比较的数据: 8 7 6 0 9
第三次循环
7 8 6 0 9 第1次比较后:交换
7 6 8 0 9 第2次比较后:交换
7 6 0 8 9 第3次比较后:交换
7 6 0 8 9 第4次比较后:不交换
最后冒出的最大数据在右边:9
经过第三次循环,此时剩下参与比较的数据:7 6 0 8
第四次循环
6 7 0 8 第1次比较后:交换
6 0 7 8 第2次比较后:交换
6 0 7 8 第3次比较后:不交换
最后冒出的最大数据在右边:8
经过第四次循环,此时剩下参与比较的数据:6 0 7
第五次循环
0 6 7 第1次比较后:交换
0 6 7 第2次比较后:不交换
最后冒出的最大数据在右边:7
经过第五次循环,此时剩下参与比较的数据:0 6
第六次循环
0 6 第1次比较后:不交换
//7条数据比6次
//6条数据比5次
//5条数据比4次
//4条数据比3次
//3条数据比2次
//2条数据比1次
*/
public class BubbleSort {
public static void main(String[] args){
//这是int类型的数组对象
// int[] arr = {3,2,7,6,8};
int[] arr = {9,8,10,7,6,0,11};
//经过冒泡排序算法对以上数组中元素进行排序
//冒泡排序算法的核心是什么?
//对arr数组中的七条数据进行冒泡排序
/*
数组中有七条数据,第一次循环7条数据要比较6次,第二次循环6条数据要比较5次,第三次循环5条数据要比较4次...第6次循环2条数据要比较1次
意思是:最外层循环要循环6次,内层循环每经过一次循环要根据所要比较的数据相应减少一次。
外层的是要控制需要进行6次循环比较,内层控制的是数组中数据的比较。
*/
//查看循环几次
int count = 0;
for (int i = arr.length-1; i >0 ; i--) {
//i刚开始是6,循环到1,刚好是循环了6次
for (int j =0 ; j < i ; j++) {
//不管是否交换,只要循环一次,就加1;
count++;
//内层循环里,j < i,就是几条数据循环几条-1次,如有5条数据,就循环四次
//交换位置
if(arr[j] >arr[j+1]){
int temp ;
temp = arr[j];
arr[j] =arr[j+1];
arr[j+1] =temp;
}
}
}
for (int i = 0; i
选择排序:
选择排序比冒泡排序的效率高,高在交换位置的次数上。选择排序的交换位置是有意义的
循环一次,然后找出参加比较的这堆数据中最小的,拿着这个最小的值和最前面的数据交换位置。
/*
选择排序:每一次从 这堆参与比较的数据 当中找出 最小值
拿着这个 最小值 和 参与比较的这堆数据中最前面的元素 交换位置
选择排序比冒泡排序好在:每一次的交换位置都是有意义的。
参与比较的数据:3 1 6 2 5 (这一堆参加比较的数据中最左边的元素下标是0)
第一次循环之后的结果是:1 3 6 2 5
参与比较的数据: 3 6 2 5 (这一堆参加比较的数据中最左边的元素下标是1)
第二次循环之后的结果是:2 6 3 5
参与比较的数据是: 6 3 5 (这一堆参加比较的数据中最左边的元素下标是2)
第三次循环之后的结果是:3 6 5
参与比较的数据是:6 5 (这一堆参加比较的数据中最左边的元素下标是3)
第四次循环之后的结果是:5 6
注意:5条数据,循环4次。
关键点:选择排序中的关键在于:怎么找出一堆数据中最小的
3 1 6 2 5
假设:
第一个3是最小的
3和2比较,发现2更小,所以此时最小的是2
继续拿着2往下比对,2和6比较,2仍是最小的
继续拿着2往下比对,2和1比较,发现1更小,所以此时最小的是1
继续拿着1往下比对,1和5比较,1仍是最下的。
拿着1和最左边的3交换位置
2 6 3 5
假设:
第一个2是最小的
。。。
6 3 5
假设6是最小的:
6和3比对,发现3更小,所以此时最小的是3
*/
public class SelectSort {
public static void main(String[] args){
//int[] arr = {3,1,6,2,5};
int[] arr = {9,8,10,7,6,0,11};
//选择排序算法 5条数据循环4次
//每次循环取出最小的值与第一个值交换(外层循环4次)
//设置个变量,查看比较次数
int count =0;
//查看交换次数
int count2 = 0;
for (int i = 0; i
结论:
冒泡排序和选择排序实际上比较的次数没有变,但选择排序的交换位置的次数变少了
数组元素的查找
挨着找:效率低
/*
数组的元素查找
数组元素查找有两种方式:
第一种方式:一个一个挨着找
第二种方式:二分法查找法(算法),这个效率比较高。
*/
public class ArraySearch {
public static void main(String[] args) {
//这个例子演示一下第一种方式
int[] arr ={4,5,5,6,87,8};
//如果有两个相同的元素,则返回的是第一个。因为是挨着找,找到后就结束了,不会再去找剩下的。
/* //找出87的下标,如果没有返回-1。
//一个一个挨着找
for(int i = 0; i < arr.length;i++){
if(arr[i] == 87){
System.out.println("87的元素的下标为:"+i);
return;
}
}
//程序执行到这里,表示没有87
System.out.println("数组中不存在87这个元素");*/
/*
最好以上的程序封装一个方法,思考:传什么参数?返回什么值?
传递的参数:第一个参数是数组,第二个参数是需要查找的元素。
返回值:返回被查找的这个元素的下标。如果找不到返回-1。
*/
int index = arraySearch(arr,5);
System.out.println(index == -1 ?"该元素不存在":"该元素的下标是:"+index);
}
/**
* 从数组中检索某个元素
* @param arr 被检索的数组
* @param element 被检索的元素
* @return 返回大于等于0的数表示元素的下标,-1表示该元素不存在
*/
public static int arraySearch(int[] arr, int element) {
for(int i = 0 ; i < arr.length;i++){
if(arr[i] == element){
return i;
}
}
return -1;
}
}
二分法查找:
第一:二分法查找建立在排序的基础之上。
第二:二分法查找效率要高于“一个挨着一个”的这种查找方式
第三:二分法查找原理
10(下标0) 23 56 89 100 111 222 235 500 600(下标9) arr数组
目标:找出600的下标
(0+9)/2 --------->4 (中间元素的下标)
arr[4] 这个元素就是中间元素:arr[4]是100.
100 < 600
说明被查找的元素在100的右边。那么此时开始下标变成:4+1.
(5+9) / 2 ---> 7(中间元素的下标)
arr[7]对应的是:235
235 < 600
说明被查找的元素在235的右边
开始下标又进行了转变:7 + 1
( 8 + 9 ) /2 ---> 8
arr[8] ---> 500
500 < 600
开始元素的下标又发生了变化:8+1
(9 + 9) / 2 --->9
arr[9] 是600,正好和600相等,此时找到了。
使用二分法进行查找
/*
1、数组工具类:自己写的,不是SUN的。
2、二分法查找算法是基于排序的基础上的(没有排序的数据是无法查找的。)
3、关于查找算法中的:二分法查找
10(下标0) 11 12 13 14 15 16 17 18 19 20(下标10) arr数组
通过二分法查找,找18这个元素的下标:
(0 + 10)/2 ------> 中间元素的下标:5
拿着中间这个元素和目标要查找的元素进行对比:
中间元素是:arr[5]--> 15
15 < 18(被查找的元素)
被查找的元素18在目前中间元素15的右边。
所以开始元素的下标从0变成5+1
再重新计算一个中间元素的下标:
开始下标: 5+1
结束下标:10
(6 + 10)/2 --> 8
8下标对应的元素arr[8] 是18
找到的中间元素正好和被查找的元素18相等,表示找到了:下标为8
二分法查找的终止条件:一面折半,直到中间的按个元素恰好是被查找的元素。
第一:二分法查找建立在排序的基础之上。
第二:二分法查找效率要高于“一个挨着一个”的这种查找方式
第三:二分法查找原理
10(下标0) 23 56 89 100 111 222 235 500 600(下标9) arr数组
目标:找出600的下标
(0+9)/2 --------->4 (中间元素的下标)
arr[4] 这个元素就是中间元素:arr[4]是100.
100 < 600
说明被查找的元素在100的右边。那么此时开始下标变成:4+1.
(5+9) / 2 ---> 7(中间元素的下标)
arr[7]对应的是:235
235 < 600
说明被查找的元素在235的右边
开始下标又进行了转变:7 + 1
( 8 + 9 ) /2 ---> 8
arr[8] ---> 500
500 < 600
开始元素的下标又发生了变化:8+1
(9 + 9) / 2 --->9
arr[9] 是600,正好和600相等,此时找到了。
如果是在前半个里面,则元素下标-1,这个作为终止下标,起始下标不变。
*/
public class ArrayUtil {
public static void main(String[] args){
int[] arr = {100,200,230,235,600,1000,2000,9999};
//找出arr这个数组中200所在的下标
//调用方法
int index = binarySearch(arr,200);
System.out.println(index == -1 ? "该元素不存在":"该元素的下标:"+index);
}
/**
* 使用二分法从数组中查找元素的下标
* @param arr 被查找的数组(这个必须是已经排序的)
* @param dest 目标元素
* @return
*/
public static int binarySearch(int[] arr, int dest) {
//开始下标
int begin = 0;
//结束下标
int end =arr.length-1;
//开始元素下标只要在结束元素下标的左边,就一直循环
while(begin <= end){
//中间元素下标
int mid = (begin+end) / 2;
if(arr[mid] == dest){
return mid;
}else if(arr[mid] < dest){
//目标在中间元素的右边
//起始元素下标 = 中间元素+1
begin = mid + 1 ;//增
}else{
//arr[mid] > dest
//目标在“中间”的左边,修改结束元素的下标
end = mid - 1 ;//减
}
}
return -1;
}
}
java.util.Arrays 工具类
所有的方法都是静态的,直接使用类名调用。使用时要文档,不要死记硬背。
主要使用的是两个方法:排序、二分法查找
import java.util.Arrays;
/*
SUN公司已经为我们程序员写好了一个数组工具类
java.util.Arrays
*/
public class ArraysText02 {
public static void main(String[] args) {
//java.util.Arrays; 工具类中有哪些方法,我们开发的时候要参考API帮助文档
int[] arr = {3,6,4,7,12,1,2,32,5,5};
//排序
Arrays.sort(arr);
//输出
for (int i = 0; i