三、数组

什么是数组

  • 数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器
  • 数组里面既可以存储基本数据类型,也可以存储引用数据类型,但是只能存储同一种数据类型
  • 数组是一种简单的数据结构,线性的结构
  • 数组一旦创建其长度是不可变得
  • 数组是引用数据类型

一维数组

静态初始化数组

数组初始化就是为数组开辟连续的内存空间,并为每个数组元素赋予值。知道数组首元素的内存地址,要查找的元素只要知道下标就可以快速的计算出偏移量,通过首元素内存地址加上偏移量可以快速计算出要查找元素的内存地址,通过内存地址快速定位该元素,所以数组查找元素的效率较高。

注意:数组下标是从0开始的
下面代码演示了静态初始化一维数组,通过下标定位元素

ackage com.package1024.Array;

public class ArrayTest01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//使用静态初始化方式创建一维数组
		int[] intArray = {1024,2048,256};
		
		String[] str = {"java","Python","C++","php"};
		//创建Object类型的数组
		Object o1 = new Object();
		Object o2 = new Object();
		Object o3 = new Object();
		Object[] obj= {o1,o2,o3};
		
		//访问数组元素
		System.out.println(intArray[0]);
		System.out.println(intArray[1]);
		System.out.println(intArray[2]);
		//System.out.println(intArray[3]); //java.lang.ArrayIndexOutOfBoundsException
		
		//数组的长度
		System.out.println(intArray.length);
		
		//循环获取数组里的元素;使用for循环可以遍历数组中 的元素
		for(int i =0;i<intArray.length;i++) {
			System.out.println(intArray[i]);
		}
		
		//修改数组中的元素
		intArray[1] = 1024;
		System.out.println(intArray[1]);
	}

}

动态初始化数组
动态初始化数组,会先在堆内存中分配这个数组,并且数组中每一个元素都采用默认值。

package com.package1024.Array;
//动态初始化一维数组
public class ArrayTest02 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		//基本数据类型初始化值都为0
		int[] intArray=new int[4]; //10为动态初始化数组的长度;动态创建一个长度是4的数组
		for(int i =0;i<intArray.length;i++) {
			System.out.println(intArray[i]);
		}
		
		//给int类型数组赋值
		intArray[0] = 1024;
		intArray[1] = 1025;
		intArray[2] = 1026;
		intArray[3] = 1027;
		
		for(int i =0;i<intArray.length;i++) {
			System.out.println(intArray[i]);
		}
		
		
		//引用数据类型初始化值都为null
		Object[] objArray = new Object[4];
		for(int i =0;i<objArray.length;i++) {
			System.out.println(objArray[i]);
		}
	}
}

如何选择数组的初始化方式?

  • 如果在创建数组的时候,知道数组中应该存储什么数据,这个时候当然采用静态初始化方式。
  • 如果在创建数组的时候,无法预测到数组中存储什么数据,只是先开辟空间,则使用动态初始化方式。

练习
1、获取一个int类型数组中的最大值
2、将数组元素的值对调,比如将array[0]与最后一个元素对调

main方法参数String[] args

main方法中的String[] args是专门用来接收命令行参数的

public class test {
	public static void main(String[] args) {
		
		//小练习:
		/*
		 * 实现一个用户登录的功能,接收用户输入的用户名和密码,如果正确,则登录成功,否则登录失败
		 * 用户名: admin
		 * 密码Monkey1024
		 * 
		 */
			String name ="admin";
			String pass ="Monkey1024";
			System.out.print(login(name,pass,args)?"登录成功":"登录失败");
			
		}
	
		public static boolean login(String name,String pass,String[] args) {
			System.out.println("欢迎使用,请输入用户名和密码:");
			if(name.equals(args[0])&&(pass.equals(args[1]))) {
				return true;
			}else {
				return false;
			}
		}
	}

二维数组

一维数组里面只需要一个下标即可定位数组中的元素,二维数组需要两个下标才能定位到数组中的元素。可以将我们平时使用的execl理解为是一个二维数组。


静态初始化与动态初始化二维数组


package com.package1024.Array;

public class ArrayTest05 {

	
	/**
	 * 
	 * 静态初始化二维数组
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a1= {1,2,3,4}; //静态初始化一维数组
		//静态定义二维数组
		int[][] a = {{1,2,3},
					{10,15,16},
					{100,101,102},
					{1024,1045,8888}};
		
		System.out.println(a.length);
		
		//遍历二维数组
		for(int i =0;i<a.length;i++) {//这个for循环把一维数组循环一遍
			for(int j=0;j<a[i].length;j++) {//循环一维数组里的每个元素
				System.out.print(a[i][j]+" ");
			}
			System.out.print('\n');
		}
		
		
		//动态初始化定义二维数组
		int[][] a2=new int[3][4];
		a2[1][2]=1024;
		//遍历二维数组
		for(int i =0;i<a2.length;i++) {//这个for循环把一维数组循环一遍
			for(int j=0;j<a2[i].length;j++) {//循环一维数组里的每个元素
				System.out.print(a2[i][j]+" ");
			}
			System.out.print('\n');
		}
	}

}

练习:使用数组实现酒店房间管理系统

有家酒店一共有5层,每层有10个房间,其中:

1,2层是标准间
3,4层是双人间
5层是豪华间
根据以前所学习的知识实现一个酒店管理系统,需要提供房间状态查看,房间预订、退房的功能。

需求分析:
先来抽象,既然要做酒店房间管理系统,那么就会跟酒店和房间打交道,因此将这两个对象使用java语言表现出来:

首先需要定义一个Room类,里面存储房间编号,房间类型,是否空房
其次需要定义一个Hotel类,里面存储所有房间的基本信息。里面提供预定、退房、查看房间状态的方法。
最后需要定义一个Test类,用来接收用户的输入,从而提供房间服务。

package com.test;
/*
 * 
首先需要定义一个Room类,里面存储房间编号,房间类型,是否空房
其次需要定义一个Hotel类,里面存储所有房间的基本信息。里面提供预定、退房、查看房间状态的方法。
最后需要定义一个Test类,用来接收用户的输入,从而提供房间服务。
 */

//酒店的房间
public class Room { //这就相当于创建一个房间模板
	private String id ; //房间编号
	private String type; //房间类型
	private boolean Isuse; //是否空房
	
	//定义一个含参的构造方法,用来初始化该类中的属性值
	public Room(String id, String type, boolean isuse) {
		super();
		this.id = id;
		this.type = type;
		Isuse = isuse;
	}
	
	//定义一个无参的构造方法
	public Room() {}

	//定义set与get方法
	public String getId() {
		return id;
	}

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

	public String getType() {
		return type;
	}

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

	public boolean isIsuse() {
		return Isuse;
	}

	public void setIsuse(boolean isuse) {
		Isuse = isuse;
	}
	
	public String toString() { //重写toString方法,直接将房间的基本信息拼接成字符串返回
		return ("["+id+"  "+type+" "+(Isuse?"占用":"空闲")+"]");
	}
	
	
}

package com.test;
/*
 * 
首先需要定义一个Room类,里面存储房间编号,房间类型,是否空房
其次需要定义一个Hotel类,里面存储所有房间的基本信息。里面提供预定、退房、查看房间状态的方法。
最后需要定义一个Test类,用来接收用户的输入,从而提供房间服务。
 */

/*
 * 酒店里面是一个挨着一个房间,需要将这些房间体现出来
 * 酒店中的房间个数是固定的,在Java中数组的长度是固定的,这里可以使用数组来存储这些房间对象
 * 酒店有多层,所以使用二维数组
 * 定义房间类型的数组,该数组用来存储房间对象
 */

public class Hotel {
	
	private Room[][] room =new Room[5][10]; //动态创建
	
	//无参构造方法,用来初始化房间对象数据
	public Hotel() { //构造函数,创建5x10房间
		//赋值,初始化房间号
		for(int i =0;i<room.length;i++) {  //对[5x10]个数据进行初始化
			for(int j=0;j<room[i].length;j++) {
			if(i==0||i==1) { //1,2两层标准间
				room[i][j]=new Room((i+1)*100+j+"","标准间",false); //引用指向对象
			}
			if(i==2||i==3) { //3,4两层双人间
				room[i][j]=new Room((i+1)*100+j+"","双人间",false);
			}
			if(i==4) { //5层豪华间
				room[i][j]=new Room((i+1)*100+j+"","豪华间",false);
			}
			}
		}
	
		}
		
	//当用户预订时,需要将房间状态改为占用
	//对外提供一个预订酒店的方法
	public void order(String id) { //预定
		for(int i=0;i<room.length;i++) {
			for(int j=0;j<room[i].length;j++) {
				//根据传入的房间编号去数组中查找与之对应的房间
				if(room[i][j].getId().equals(id)) {
					//将房间的状态改成占用
					room[i][j].setIsuse(true); //显示房间已经被预定
					//此时后面就没有必要再继续循环,所以直接return 
					return;
				}
			}
		}
	}
		
	//对外提供一个退房酒店的方法
	public void checkout(String id) { //退房
		for(int i=0;i<room.length;i++) {
			for(int j=0;j<room[i].length;j++) {
				//根据传入的房间编号去数组中查找与之对应的房间
				if(room[i][j].getId().equals(id)) {
					room[i][j].setIsuse(false); //显示房间已经被预定
				}
			}
		}
		
	}
	
	//在使用酒店管理系统时需要查看每个房间的状态,是否已被占用
	//对外提供一个打印酒店房间列表的方法
	public void print() { //查看房间状态
			for(int i=0;i<room.length;i++) {
				for(int j=0;j<room[i].length;j++) {
					System.out.print(room[i][j].toString());
				}
			}
		}
		
	}

package com.test;

import java.util.Scanner;

public class TestHotel {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//初始化酒店
		Hotel h = new Hotel();
		//输出房间列表
		h.print();
		//获取用户输入
		Scanner s = new Scanner(System.in);
		
		System.out.println("欢迎使用酒店管理系统");
		
		
		while(true) {
			System.out.println("请输入预定或者退房");
			String order = s.next();
			//预订房间
			if("预定".equals(order)) {
				System.out.println("请输入房间号");
				String id = s.next();
				h.order(id);
			}else if("退房".equals(order)){
				System.out.println("请输入房间号");
				String id = s.next();
				h.checkout(id);
				
			}else {
				System.out.println("请输入预定或者退房");
			}
			//打印酒店列表
			h.print();
		}

	}

}

数组的扩容

在java语言里面,数组一旦创建好之后,长度是不可变得,倘若数组的长度不够使用了,装不下数据之后需要对数组进行扩容,那该如何扩容呢?可以再重新创建一个长度更大的数组,然后将之前的旧数组拷贝到新的数组里面。

System.arraycopy()

选择排序

package com.sort;
/*
 * 
 * 选择排序
 */
public class SelectSort {
	//选择排序
	public static void main(String[] args) {
		int[] a = {4,5,1,55,0,9,7};
		for(int i =0;i<a.length-1;i++) { //遍历数组长度-1即可实现排序
			for(int j =i+1;j<a.length;j++) { //每次遍历进行比较
				if(a[i]>a[j]) {
					int temp = a[i];
					a[i]=a[j];
					a[j]=temp;
				}
			}
		}
	
		for(int i =0;i<a.length;i++) {
			System.out.print(a[i]+" ");
		}
		
	}

}

冒泡排序

package com.sort;
//冒泡排序
public class MaopaoSort {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a= {1,21,0,2,11,33,7};
		for(int i =a.length-1;i>0;i--) {
			for(int j =0;j<i;j++) { //j<i可以使地排序次数减少,增加效率
				if(a[j]>a[j+1]) {
					//进行位置交换
					int temp =a[j];
					a[j]=a[j+1];
					a[j+1]=temp;
				}
			}
		}
		
		//打印排序之后的列表
		for(int i =0;i<a.length;i++) {
			System.out.print(a[i]+" ");
		}
		
	}
}

二分法查找

二分法查找原理:
使用二分法查找时需要以下两个条件:

  • 没有重复元素
  • 已经排好顺序

假设给定一组排好序且没有重复元素的数字,要从这些数字中快速找到x所在的位置,可以从这组数字的中间位置开始找,如果当前值与x相等,则查找成功,如果小于x则从后半段的中间位置继续找,如果大于x则从前半段的中间位置继续查找,直到找到x所在的位置。

package com.sort;
//二分法查找
public class MyArray {
	
	public static void main(String[] args) {
		int[] a= {1,5,8,15,18,23,30};
		int destElement = 23;
		
		int result = binarySearch(a, destElement);
		System.out.println(result);
	}

	//二分法查找
	public static int binarySearch(int[] a, int destElement) {
		int begin = 0;
		int end = a.length-1;
			
		while(begin<= end) {
			int middle = (begin+end)/2;//数组中间元素下标
			if (a[middle]==destElement) {
				return middle;
			}else if(a[middle]>destElement) { //说明destElement在数组的前半部分
					end = middle -1;
					}else if(a[middle]<destElement) {//说明destElement在数组的后半部分
					begin = middle+1;
			}
		}
		
		return -1;
	}

}

Arrays工具类

在java.util包里面有个Arrays类,里面提供了排序和二分法查找的方法,程序员直接调用就行了,而且这些方法都是静态的,所以在使用时不用创建对象。

package com.Arrays;

import java.util.Arrays;

//Arrays类
//方法:equals方法 比较两个数组里面的内容
//      sort方法:排序
//toString
public class test {
	
	public static void main(String[] args) {
		int[] a = {6,8,1,3,15,23,16,1};
		int [] b=a;
		
		//排序方法
		Arrays.sort(a); //排序方法
		for(int i =0;i<a.length;i++) {
			System.out.print(a[i]+" ");
		}
		
		//比较两个数组里面的内容
		System.out.println(b.equals(a));
		System.out.println(Arrays.equals(a,b));
		
		//二分法查找
		int result = Arrays.binarySearch(a, 23);
		System.out.println(result);
		
		//toString方法
		System.out.println(Arrays.toString(a));
	}

}

猜你喜欢

转载自blog.csdn.net/ZHOUJIAN_TANK/article/details/87863246