笔记整理4----Java语言高级(四)16 JAVA常用API-高级+17 泛型与常见数据结构+18 Map与Set集合+19 异常处理+20 IO流-高级

16 JAVA常用API-高级+17 泛型与常见数据结构+18 Map与Set集合+19 异常处理+20 IO流-高级

第05天 API

今日内容介绍
 Object类 & System类
 日期相关类
 包装类&正则表达式

第1章Object类 & System类

1.1Object类
1.1.1概述
Object类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。所有类在创建对象的时候,最终找的父类就是Object。
在Object类众多方法中,我们先学习equals方法与toString方法,其他方法后面课程中会陆续学到。
1.1.2toString()方法

由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。
1.1.2.1案例代码一:

    package com.itheima_01;
/*
 * String toString()  : 返回该对象的字符串表示
 * 		 return getClass().getName() + "@" + Integer.toHexString(hashCode());
 * 		 getClass():返回一个字节码对象
 * 		 Integer.toHexString():返回指定参数的十六进制字符串形式
 * 		 hashCode():返回该对象的哈希码值(内部地址)
 * 
 * 	
 * 
 * boolean equals(Object obj)  
 * 
 */
public class ObjectDemo {
	public static void main(String[] args) {
		Student s = new Student();
		s.name = "zhangsan";
		s.age = 18;
		System.out.println(s.toString());//com.itheima_01.Student@737951b0
		System.out.println(s);//说明我们输出一个对象就是默认输出这个对象的toString()方法
	}
}

class Student extends Object {
	String name;
	int age;
	/*
	public String toString() {
		return name + "@" + age;
	}
	*/
	
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	
	
}

1.1.3equals()方法

equals方法,用于比较两个对象是否相同,它其实就是使用两个对象的内存地址在比较。Object类中的equals方法内部使用的就是==比较运算符。
在开发中要比较两个对象是否相同,经常会根据对象中的属性值进行比较,也就是在开发经常需要子类重写equals方法根据对象的属性值进行比较。
1.1.3.1案例代码二:

package com.itheima_01;
import java.util.ArrayList;

/*
 * boolean equals(Object obj)  
 * 		使用==来比较两个对象是否相等,则比较地址值是否相等
 */
public class ObjectDemo2 {
	public static void main(String[] args) {
		Person p = new Person("zhangsan",18);
		Person p2 = new Person("zhangsan",19);
		
		//boolean flag = p.equals(p2);
		
		boolean flag = p.equals(new ArrayList());
		System.out.println(flag);
	}
}

class Person {
	String name;
	int age;
	
	public Person(String name,int age) {
		this.name = name;
		this.age = age;
	}


	@Override
	public boolean equals(Object obj) {
		//提高效率
		if (this == obj)
			return true;
		
		if (obj == null)
			return false;
		//提高健壮性
		if (getClass() != obj.getClass())
			return false;
		
		//向下转型
		Person other = (Person) obj;
		
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
	
	/*@Override
	public boolean equals(Object o) {
		//提高效率 当前对象和传递进来的对象地址值一样,则不用比较成员
		if(this == o) {
			return true;
		}
		
		//提高代码的健壮性
		if(this.getClass() != o.getClass()) {
			return false;
		}
		
		//向下转型
		Person other = (Person) o;
		
		if(!this.name.equals(other.name)) {
			return false;
		}
		
		if(this.age != other.age) {
			return false;
		}
		
		return true;
	}*/
}

1.2System类
System 类包含一些有用的类字段和方法。它不能被实例化。
1.2.1成员方法
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) :
从src源数组的srcPos索引开始,复制length个元素
从destPost位置开始将这些元素放至到dest数组中
static long currentTimeMillis()
返回以毫秒为单位的当前时间
static void exit(int status)
终止当前正在运行的 Java 虚拟机
static void gc()
运行垃圾回收器
1.2.2案例代码三:

package com.itheima_02;
/*
 * System:包含一些有用的类字段和方法。它不能被实例化
 * static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)  
 * static long currentTimeMillis()  
 * static void exit(int status) 
   static void gc()  
 * 
 */
public class SystemDemo {
	public static void main(String[] args) {
		//method();
		//method2();
		//method3();
		
		//static void gc()  
		//Demo d = new Demo();
		new Demo();
		System.gc();
	}

	private static void method3() {
		//static void exit(int status) :终止虚拟机
		
		for (int i = 0; i < 100000; i++) {
			System.out.println(i);
			if(i == 100) {
				System.exit(0);
			}
		}
	}

	private static void method2() {
		/*
		 *  static long currentTimeMillis() :以毫秒值返回当前系统时间
		 *  这个毫秒的时间是相对时间,相对于1970-1-1 00:00:00 : 0
		 *  1970-1-1 00:00:01 : 1000
		 *  1970-1-1 00:01:00: 1000 * 60
		 *  1970-1-1 01:00:00: 1000 * 60 * 60
		 *  1000毫秒 = 1秒
		 *  
		 */
		//System.out.println(System.currentTimeMillis());
		
		
		long start = System.currentTimeMillis();
		for (int i = 0; i < 100000; i++) {
			System.out.println(i);
		}
		long end = System.currentTimeMillis();
		System.out.println(end - start);
	}

	private static void method() {
		/*
		 * static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)  
		 * 复制数组
		 * 参数1:源数组
		 * 参数2:源数组的起始索引位置
		 * 参数3:目标数组
		 * 参数4:目标数组的起始索引位置
		 * 参数5:指定接受的元素个数
		 */
		int[] src = {1,2,3,4,5};
		int[] dest = new int[5];
		System.arraycopy(src, 2, dest, 4, 3);
		
		for (int i = 0; i < dest.length; i++) {
			System.out.print(dest[i]);
		}
	}
}

class Demo {
	@Override
	protected void finalize() throws Throwable {
		System.out.println("我被回收了");
	}
}

第2章日期相关类

2.1Date类
Date: 表示特定的瞬间,精确到毫秒,他可以通过方法来设定自己所表示的时间,可以表示任意的时间
2.1.1Date类的构造方法
Date() :创建的是一个表示当前系统时间的Date对象
Date(long date) :根据"指定时间"创建Date对象
2.1.2案例代码四:

package com.itheima_03;

import java.util.Date;

/*
 * Date: 表示特定的瞬间,精确到毫秒,他可以通过方法来设定自己所表示的时间,可以表示任意的时间
 * System.currentTimeMillis():返回的是当前系统时间,1970-1-1至今的毫秒数
 * 
 * 构造方法:
 * 		Date() :创建的是一个表示当前系统时间的Date对象
		Date(long date) :根据"指定时间"创建Date对象
 
 */
public class DateDemo {
	public static void main(String[] args) {
		//Date()
		//Date d = new Date();
		//System.out.println(d);//Thu Aug 26 14:17:28 CST 2049
		//System.out.println(d.toLocaleString());
		
		//Date(long date) 
		Date d2 = new Date(1000 * 60 * 60 * 24);//时区 有时差
		System.out.println(d2.toLocaleString());

	}
}

2.1.3Date类常用方法
void setTime(long time)
long getTime()
2.1.4案例代码五:

  package com.itheima_03;

import java.util.Date;

/*
 * Date的常用用方法
		毫秒值 --- Date
			设置
			返回值是void,参数long
			void setTime(long time)  
			Date(long date)
		Date --- 毫秒值
			获取
			返回long,无参数
			long getTime()  
 */
public class DateDemo2 {
	public static void main(String[] args) {
		Date d = new Date();//默认当前系统时间
		//d.setTime(1000 * 60 * 60 * 24 * 2);
		System.out.println(d.toLocaleString());
		System.out.println(d.getTime());//172800000
		
		
		d.setTime(172800000L);
		System.out.println(d.toLocaleString());
	}
}

2.2DateFormat类 & SimpleDateFormat
DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。日期/时间格式化子类(如 SimpleDateFormat类)允许进行格式化(也就是日期 -> 文本)、解析(文本-> 日期)和标准化。
我们通过这个类可以帮我们完成日期和文本之间的转换。
继续阅读API,DateFormat 可帮助进行格式化并解析任何语言环境的日期。对于月、星期,甚至日历格式(阴历和阳历),其代码可完全与语言环境的约定无关。
2.2.1DateFormat&SimpleDateFormat的常用方法
要格式化一个当前语言环境下的日期也就是日期 -> 文本),要通过下面的方法来完成。DateFormat是抽象类,我们需要使用其子类SimpleDateFormat来创建对象。
A:SimpleDateFormat构造方法

B:DateFormat类方法

2.2.2案例代码六:

package com.itheima_04;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * SimpleDateFormat:
 * 		格式化:
 * 			Date --- String
 * 			2049-8-26 2049年8月26日
 * 			String format(Date date) 
 * 		解析:
 * 			String --- Date
 * 			"2049-8-26"
 * 			Date parse(String source) 
 * 
 * 构造方法:
 * 		SimpleDateFormat() :使用默认的模式进行对象的构建
 * 		SimpleDateFormat(String pattern) :使用的指定的模式进行对象的构建
 * 
 * 注意:Exception in thread "main" java.text.ParseException: Unparseable date: "49年9月26日  下午1:29"
 * 	    解析的字符串,模式必须和构建对象的模式一样
 *
 */
public class SimpleDateFormatDemo {
	public static void main(String[] args) throws ParseException {
		//method();
		//method2();
		//使用指定的模式进行对象的构建
		//1999年9月1日 10:10:10
		//4个小姨2个大美眉和2个小弟弟
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
		
		//格式化
		Date date = new Date();
		String s = sdf.format(date);
		System.out.println(s);//2049年08月26日 13:39:12

		
		//解析
		Date d = sdf.parse("2049年08月26日 13:39:12");
		System.out.println(d.toLocaleString());


		

	}

	private static void method2() throws ParseException {
		//使用指定的模式进行对象的构建
		//1999年9月1日
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
		//格式化
		Date date = new Date();
		String s = sdf.format(date);
		System.out.println(s);//2049年08月26日
		
		//解析
		Date d = sdf.parse("2049年08月26日");
		System.out.println(d.toLocaleString());
	}

	private static void method() throws ParseException {
		//使用默认模式进行对象的构建
		SimpleDateFormat sdf = new SimpleDateFormat();
		//创建日期对象
		Date date = new Date();
		
		//格式化 把日期对象转换成字符串
		String s = sdf.format(date);
		System.out.println(s);//49-8-26 下午1:29
		
		//解析 把字符串转换成日期对象
		Date d = sdf.parse("49年9月26日  下午1:29");
		System.out.println(d.toLocaleString());
	}

}

2.3Calendar类
2.3.1Calendar类概述
Calendar是日历类,在Date后出现,替换掉了许多Date的方法。该类将所有可能用到的时间信息封装为静态成员变量,方便获取。
Calendar为抽象类,由于语言敏感性,Calendar类在创建对象时并非直接创建,而是通过静态方法创建,将语言敏感内容处理好,再返回子类对象,如下:
Calendar类静态方法

Calendar c = Calendar.getInstance(); //返回当前时间
2.3.2Calendar类常用方法

2.3.3案例代码七:

package com.itheima_05;

import java.util.Calendar;

/*
 * Calendar:日历,提供了一些操作年月日时的方法
 * 
 * 获取
 * 修改
 * 添加
 * 
 * 
 */
public class CalendarDemo {
	public static void main(String[] args) {
		//static Calendar getInstance()  
		Calendar c = Calendar.getInstance();
		
		//void set(int field, int value) :把指定的字段修改成指定的值
		//c.set(Calendar.DAY_OF_MONTH, 20);
		
		//void add(int field, int amount): 在指定的字段上加上指定的值
		c.add(Calendar.DAY_OF_MONTH, -1);
		
		//int get(int field) // 返回给定日历字段的值
		//public static final int YEAR 1 
		//System.out.println(Calendar.YEAR);
		
		//int year = c.get(1);
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		int day = c.get(Calendar.DAY_OF_MONTH);
		
		
		System.out.println(year + "年" + month + "月" + day + "日");
		 
	}
}

第3章包装类&正则表达式

3.1包装类
在实际程序使用中,程序界面上用户输入的数据都是以字符串类型进行存储的。而程序开发中,我们需要把字符串数据,根据需求转换成指定的基本数据类型,如年龄需要转换成int类型,考试成绩需要转换成double类型等。那么,想实现字符串与基本数据之间转换怎么办呢?
Java中提供了相应的对象来解决该问题,基本数据类型对象包装类:java将基本数据类型值封装成了对象。封装成对象有什么好处?可以提供更多的操作基本数值的功能。
8种基本类型对应的包装类如下:

其中需要注意int对应的是Integer,char对应的Character,其他6个都是基本类型首字母大写即可。
3.2包装类的常用方法
A:构造方法:

B:成员方法:

3.2.1案例代码八:

package com.itheima_06;
/*
 * 需求:判断一个数是否符合int类型的范围
 * 由于基本数据类型只能做一些简单的操作和运算,所以Java为我们封装了基本数据类型,为每种基本数据类型提供了包装类
 * 包装类就是封装了基本数据类型的类,为我们提供了更多复杂的方法和一些变量
 * 
 * byte		Byte
 * short	Short
 * char		Character
 * int		Integer
 * long		Long
 * float	Float
 * double	Double
 * boolean	Boolean
 * 
 * Integer:
 * 		String --- int
 * 			方式1:int intValue()
 * 			方式2: static int parseInt(String s) 
 * 		int --- String
 * 			方式1: + ""
 * 			方式2:String toString()
 * 
 * 构造方法:
 * 		Integer(int value) 
 * 		Integer(String s) 

 
 */
public class IntegerDemo {
	public static void main(String[] args) {
		/*int n = 10;
		if(n >= Math.pow(-2, 31) && n <= Math.pow(2, 31) -1) {
			System.out.println("符合");
		}
		else {
			System.out.println("不符合");
		}*/
		
		 
		Integer i = new Integer("10");
		System.out.println(i);
		
	 
		int a = i.intValue();
		System.out.println(a + 10 );
		
 
		int b = Integer.parseInt("20");
		System.out.println(b + 30);
		
		
		 
		Integer i2 = new Integer(40);
		String s = i2.toString();
		System.out.println(s);
		
		 
		String s2 = Integer.toString(50);
		System.out.println(s2);
		
	}
}

3.3包装类的自动装箱与拆箱
在需要的情况下,基本类型与包装类型可以通用。有些时候我们必须使用引用数据类型时,可以传入基本数据类型。
比如:
基本类型可以使用运算符直接进行计算,但是引用类型不可以。而基本类型包装类作为引用类型的一种却可以计算,原因在于,Java”偷偷地”自动地进行了对象向基本数据类型的转换。
相对应的,引用数据类型变量的值必须是new出来的内存空间地址值,而我们可以将一个基本类型的值赋值给一个基本类型包装类的引用。原因同样在于Java又”偷偷地”自动地进行了基本数据类型向对象的转换。
自动拆箱:对象转成基本数值
自动装箱:基本数值转成对象
3.3.1案例代码九:

package com.itheima_06;
import java.util.ArrayList;
/*
 * JDK1.5特性:自动装箱和拆箱
 * 
 */
public class IntegerDemo2 {
	public static void main(String[] args) {
		//Integer i = new Integer(10);
		
		//自动装箱
		//相当于: Integer i = new Integer(10);
		//Integer i = 10;
		
		//自动拆箱
		//相当于 int a = i.intValue();
		//Integer i = 10;
		//int a = i;
		
		Integer i = 10;
		Integer i2 = 20;
		Integer i3 = i + i2;
		/*
		 * Integer i3 = new Integer(i.intValue() + i2.intValue());
		 * 
		 */
		
		ArrayList list = new ArrayList();
		list.add(1);//自动装箱,list.add(new Integer(1));
	}
}

3.4正则表达式
3.4.1正则表达式概述
正则表达式是专门解决字符串规则匹配的工具。
正则表达式也是一个字符串,用来定义匹配规则。
参照帮助文档,在Pattern类中有简单的规则定义,可以结合字符串类的方法使用。

3.4.2正则表达式匹配规则
参照帮助文档,在Pattern类中有正则表达式的的规则定义,正则表达式中明确区分大小写字母。我们来学习语法规则。
正则表达式的语法规则:
字符:x
含义:代表的是字符x
例如:匹配规则为 “a”,那么需要匹配的字符串内容就是 ”a”

字符:\
含义:代表的是反斜线字符’’
例如:匹配规则为"\" ,那么需要匹配的字符串内容就是 ”\”

字符类:[abc]
含义:代表的是字符a、b 或 c
例如:匹配规则为"[abc]" ,那么需要匹配的内容就是字符a,或者字符b,或字符c的一个

字符类:[^abc]
含义:代表的是除了 a、b 或 c以外的任何字符
例如:匹配规则为"[^abc]",那么需要匹配的内容就是不是字符a,或者不是字符b,或不是字符c的任意一个字符

字符类:[a-zA-Z]
含义:代表的是a 到 z 或 A 到 Z,两头的字母包括在内
例如:匹配规则为"[a-zA-Z]",那么需要匹配的是一个大写或者小写字母

字符类:[0-9]
含义:代表的是 0到9数字,两头的数字包括在内
例如:匹配规则为"[0-9]",那么需要匹配的是一个数字

字符类:[a-zA-Z_0-9]
含义:代表的字母或者数字或者下划线(即单词字符)
例如:匹配规则为" [a-zA-Z_0-9] ",那么需要匹配的是一个字母或者是一个数字或一个下滑线

预定义字符类:.
含义:代表的是任何字符
例如:匹配规则为" . “,那么需要匹配的是一个任意字符。如果,就想使用 . 的话,使用匹配规则”\."来实现

预定义字符类:\d [0-9]
含义:代表的是 0到9数字,两头的数字包括在内,相当于[0-9]
例如:匹配规则为"\d ",那么需要匹配的是一个数字

预定义字符类:\w [a-zA-Z_0-9]
含义:代表的字母或者数字或者下划线(即单词字符),相当于[a-zA-Z_0-9]
例如:匹配规则为"\w “,,那么需要匹配的是一个字母或者是一个数字或一个下滑线
数量词:X?
含义:代表的是X出现一次或一次也没有
例如:匹配规则为"a?”,那么需要匹配的内容是一个字符a,或者一个a都没有

数量词:X*
含义:代表的是X出现零次或多次
例如:匹配规则为"a*" ,那么需要匹配的内容是多个字符a,或者一个a都没有

数量词:X+
含义:代表的是X出现一次或多次
例如:匹配规则为"a+",那么需要匹配的内容是多个字符a,或者一个a

数量词:X{n}
含义:代表的是X出现恰好 n 次
例如:匹配规则为"a{5}",那么需要匹配的内容是5个字符a

数量词:X{n,}
含义:代表的是X出现至少 n 次
例如:匹配规则为"a{5, }",那么需要匹配的内容是最少有5个字符a

数量词:X{n,m}
含义:代表的是X出现至少 n 次,但是不超过 m 次
例如:匹配规则为"a{5,8}",那么需要匹配的内容是有5个字符a 到 8个字符a之间
3.4.3案例代码十:

 package com.itheima_07;
/*
 * 	校验qq号码
* 		要求必须是5-15位
* 		0不能开头
* 		必须都是数字
	
	正则表达式:就是一套规则,可以用于匹配字符串
	
	boolean matches(String regex) :判断当前字符串是否匹配指定的正则表达式,如果匹配则返回true,否则返回false
* 
*  
 */
public class RegexDemo {
	public static void main(String[] args) {
		String qq = "12a345";
		/*boolean flag = checkQQ(qq);
		System.out.println(flag);*/
		
		
		boolean flag = qq.matches("[1-9][0-9]{4,14}");
		System.out.println(flag);
	}
	
	public static boolean checkQQ(String qq) {
		int length = qq.length();
		//要求必须是5-15位
		if(length < 5 || length > 15) {
			return false;
		}
		
		//0不能开头
		if(qq.startsWith("0")) {
			return false;
		}
		
		//必须都是数字
		for (int i = 0; i < length; i++) {
			//得到参数的每一个字符
			char c = qq.charAt(i);
			if(c < '0' || c > '9') {
				return false;
			}
		}
		return true;//符合要求
	}
}

第06天 集合

今日内容介绍
 集合&迭代器
 增强for & 泛型
 常见数据结构
 List子体系

第1章集合&迭代器

1.1集合体系结构
1.1.1集合体系图

在最顶层的父接口Collection中一定定义了所有子类集合的共同属性和方法,因此我们首先需要学习Collection中共性方法,然后再去针对每个子类集合学习它的特有方法

1.1.2案例代码一:

 package com.itheima_01;

import java.util.ArrayList;

/*
 *  ArrayList
 *  集合的体系结构:
 *  	由于不同的数据结构(数据的组织,存储方式),所以Java为我们提供了不同的集合,
 *  	但是不同的集合他们的功能都是相似,不断的向上提取,将共性抽取出来,这就是集合体系结构形成的原因
 *  
 *  体系结构:
 *  		怎么学习?最顶层开始学习,因为最顶层包含了所有的共性
 *  		怎么使用?使用最底层,因为最底层就是具体的实现
 *  
 *  Collection
 *  List
 *  ArrayList
 */
public class CollectionDemo {
	public static void main(String[] args) {		
		//创建集合对象
		ArrayList al = new ArrayList();
		//添加元素
		al.add("hello");
		al.add("world");
		al.add("java");
		//遍历集合
		for(int x = 0;x < al.size();x++) {
			System.out.println(al.get(x));
		}
		
	}
}

1.2Collection中的常用功能
boolean add(Object e): 向集合中添加元素
void clear():清空集合中所有元素
boolean contains(Object o):判断集合中是否包含某个元素
boolean isEmpty():判断集合中的元素是否为空
boolean remove(Object o):根据元素的内容来删除某个元素
int size():获取集合的长度
Object[] toArray():能够将集合转换成数组并把集合中的元素存储到数组中
1.2.1案例代码二:

 package com.itheima_01;
import java.util.ArrayList;
import java.util.Collection;

/*
 * 	Collection 	
 * 			boolean add(E e)  
 * 			void clear()  
 * 			boolean contains(Object o)  
 * 			boolean isEmpty() 
 * 			boolean remove(Object o) 
 * 			int size() 
 * 			Object[] toArray() 
 * Iterator<E> iterator()  
 
 * 		
 */
public class CollectionDemo2 {
	public static void main(String[] args) {		
		//创建集合对象
		//Collection c = new Collection();//Collection是接口,不能实例化
		Collection c = new ArrayList();//多态,父类引用指向子类对象  
		
		//boolean add(E e)  
		System.out.println(c.add("hello"));//永远可以添加成功,因为ArrayList他允许重复
		System.out.println(c.add("world"));
		
		//void clear():清空集合
		//c.clear();
		
		//boolean contains(Object o)  :判断集合中是否包含指定元素
		//System.out.println(c.contains("java"));
		
		//boolean isEmpty() :是否为空
		//System.out.println(c.isEmpty());
		
		
		//boolean remove(Object o) :删除元素
		//System.out.println(c.remove("java"));
		
		//int size() :返回集合中的元素个数
		//System.out.println(c.size());
		
		//Object[] toArray()  :将集合转换成一个Object类型的数组
		Object[] objs = c.toArray();
		for (int i = 0; i < objs.length; i++) {
			System.out.println(objs[i]);
		}
		System.out.println(c);
	}
}

1.3迭代器
java中提供了很多个集合,它们在存储元素时,采用的存储方式不同。我们要取出这些集合中的元素,可通过一种通用的获取方式来完成。
Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
集合中把这种取元素的方式描述在Iterator接口中。Iterator接口的常用方法如下
hasNext()方法:判断集合中是否有元素可以迭代
next()方法:用来返回迭代的下一个元素,并把指针向后移动一位。
1.3.1案例代码三:

 package com.itheima_02;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/*
 * 集合的遍历方式:
 * 		1.toArray(),可以把集合转换成数组,然后遍历数组即可
 * 		2.iterator(),可以返回一个迭代器对象,我们可以通过迭代器对象来迭代集合
 * 
 * Iterator:可以用于遍历集合
 * 	E next()  :返回下一个元素
 *  boolean hasNext()  :判断是否有元素可以获取
 * 
 *  注意:Exception in thread "main" java.util.NoSuchElementException
 *  	使用next方法获取下一个元素,如果没有元素可以获取,则出现NoSuchElementException
	
 */
public class IteratorDemo {
	public static void main(String[] args) {
		//method();
		//创建集合对象
		Collection c = new ArrayList();
		//添加元素
		c.add("hello");
		c.add("world");
		c.add("java");
		
		//获取迭代器对象
		Iterator it = c.iterator();
		
		//Object next()  :返回下一个元素
		//boolean hasNext()  :判断是否有元素可以获取
		
		/*if(it.hasNext())
			System.out.println(it.next());
		if(it.hasNext())
			System.out.println(it.next());
		if(it.hasNext())
			System.out.println(it.next());
		if(it.hasNext())
			System.out.println(it.next());*/
		
		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}

	private static void method() {
		//创建集合对象
		Collection c = new ArrayList();
		//添加元素
		c.add("hello");
		c.add("world");
		c.add("java");
		//获取数组
		Object[] objs = c.toArray();
		//遍历数组
		for (int i = 0; i < objs.length; i++) {
			System.out.println(objs[i]);
		}
	}

	

}

1.4并发修改异常:
并发修改异常产生原因:
当使用迭代器遍历集合的时候,使用了集合中的 增加/删除 方法,导致并发修改异常产
1.4.1案例代码四:

package com.itheima_02;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/*
 * 需求:判断集合中是否包含元素java,如果有则添加元素android
 * Exception in thread "main" java.util.ConcurrentModificationException:并发修改异常
 * 迭代器是依赖于集合的,相当于集合的一个副本,当迭代器在操作的时候,如果发现和集合不一样,则抛出异常
 * 
 * 解决方案:
 * 		你就别使用迭代器
 * 		在使用迭代器进行遍历的时候使用迭代器来进行修改
 */
public class IteratorDemo3 {
	public static void main(String[] args) {
		//method();
		
		//创建集合对象
		//Collection c = new ArrayList();
		List c = new ArrayList();
		//添加元素
		c.add("hello");
		c.add("world");
		c.add("java");
		
		//我们可以通过遍历来获取集合中的每一个元素,然后进行比较即可
		/*Iterator it = c.iterator();
		while(it.hasNext()) {
			String s = (String)it.next();
			if(s.equals("java")) {
				c.add("android");
			}
		}*/
		
		ListIterator lit = c.listIterator();
		while(lit.hasNext()) {
			String s = (String)lit.next();
			if(s.equals("java")) {
				lit.add("android");
			}
		}
		
		System.out.println(c);
	}

	private static void method() {
		//创建集合对象
		Collection c = new ArrayList();
		//添加元素
		c.add("hello");
		c.add("world");
		c.add("java");
		//判断集合中是否包含元素java
		if(c.contains("java")) {
			c.add("android");
		}
		System.out.println(c);
	}

}

并发修改异常解决方案:
A:不使用迭代器遍历集合,就可以在遍历的时候使用集合的方法进行增加或删除
B:依然使用迭代器遍历,那么就需要使用Iterator的子接口ListIterator来实现向集合中添加

第2章增强for&泛型

2.1泛型
2.1.1泛型的引入
在前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换

2.1.1.1案例代码五:

package com.itheima_03;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/*
 * 使用集合存储自定义对象并遍历
 * 由于集合可以存储任意类型的对象,当我们存储了不同类型的对象,就有可能在转换的时候出现类型转换异常,
 * 所以java为了解决这个问题,给我们提供了一种机制,叫做泛型
 * * 			
 */
public class GenericDemo {
	public static void main(String[] args) {
		//创建集合对象
		Collection  c = new ArrayList();
		//创建元素对象
		Student s = new Student("zhangsan",18);
		Student s2 = new Student("lisi",19);
		//添加元素对象
		c.add(s);
		c.add(s2);
		//遍历集合对象
		
		Iterator  it = c.iterator();
		while(it.hasNext()) {
			 String str = (String)it.next();
			 System.out.println(str);
			
	 
		}
	}
}

class Student {
	String name;
	int age;
	public Student(String name,int age) {
		this.name = name;
		this.age = age;
	}
}

以上代码会发生强制转换异常,原因就是String str = (String)it.next() ,存入集合的是Student,而强转为String,String与Student之间没有任何子父关系不能强转,未使用泛型前有可能发声强制转换异常的问题
2.1.2泛型的使用
当类上定义<>的时候就可以使用泛型,例如ArrayList类的定义:
class ArrayList,那么我们在创建ArrayList对象的时候就可以指定<>中E的类型
ArrayList al=new ArrayList(),那么String就把E替换掉了
2.1.2.1案例代码六:

package com.itheima_03;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/*
 * 使用集合存储自定义对象并遍历
 * 由于集合可以存储任意类型的对象,当我们存储了不同类型的对象,就有可能在转换的时候出现类型转换异常,
 * 所以java为了解决这个问题,给我们提供了一种机制,叫做泛型
 * 
 * 泛型:是一种广泛的类型,把明确数据类型的工作提前到了编译时期,借鉴了数组的特点
 * 泛型好处:
 * 			避免了类型转换的问题
 * 			可以减少黄色警告线
 * 			可以简化我们代码的书写
 * 
 * 什么时候可以使用泛型?
 * 		问API,当我们看到<E>,就可以使用泛型了
 * 			
 */
public class GenericDemo {
	public static void main(String[] args) {
		//创建集合对象
		Collection<Student> c = new ArrayList<Student>();
		//创建元素对象
		Student s = new Student("zhangsan",18);
		Student s2 = new Student("lisi",19);
		//添加元素对象
		c.add(s);
		c.add(s2);
		//遍历集合对象
		
		Iterator<Student> it = c.iterator();
		while(it.hasNext()) {
			//String str = (String)it.next();
			//System.out.println(str);
			
			Student stu = it.next();
			System.out.println(stu.name);
		}
	}
}

class Student {
	String name;
	int age;
	
	public Student(String name,int age) {
		this.name = name;
		this.age = age;
	}
}

2.2增强for
增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
格式:
for(元素的数据类型 变量 : Collection集合or数组){
}
它用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。
2.2.1案例代码七:

package com.itheima_04;
import java.util.ArrayList;
import java.util.Collection;

/*
 * foreach:增强for循环,一般用于遍历集合或者数组
 * 格式:
 * 		for(元素的类型 变量 : 集合或者数组对象) {
 * 			可以直接使用变量;
 * 		}
	注意:在增强for循环中不能修改集合,否则会出现并发修改异常。
	
	public interface Iterable<T>
	实现这个接口允许对象成为 "foreach" 语句的目标。

 */
public class ForEachDemo {
	public static void main(String[] args) {
		 //创建集合对象
		Collection<String> c = new ArrayList<String>();
		//添加元素
		c.add("hello");
		c.add("world");
		c.add("java");
		
		//增强for循环遍历集合
		/*for(Object obj : c) {
			System.out.println(obj);
		}*/
		
		
		/*for(String s : c) {
			System.out.println(s.toUpperCase());
		}*/
		
		for (String string : c) {
			c.add("android");
			System.out.println(string);
		}
	}
}

第3章常见数据结构

3.1数组
数组,采用该结构的集合,对元素的存取有如下的特点:
查找元素快:通过索引,可以快速访问指定位置的元素
增删元素慢 ,每次添加元素需要移动大量元素或这创建新的数组

3.2链表
链表,采用该结构的集合,对元素的存取有如下的特点:
A:多个节点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的右手拉住下个人的左手,依次类推,这样多个人就连在一起了。
B:查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素
C:增删元素快:
增加元素:只需要修改连接下个元素的地址即可。
删除元素:只需要修改连接下个元素的地址即可

3.3栈&队列
A:堆栈,采用该结构的集合,对元素的存取有如下的特点:
先进后出(即,存进去的元素,要在后它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上面,当开枪时,先弹出上面的子弹,然后才能弹出下面的子弹。
B:队列,采用该结构的集合,对元素的存取有如下的特点:
先进先出(即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)。例如,安检。排成一列,每个人依次检查,只有前面的人全部检查完毕后,才能排到当前的人进行检查。

第4章List子体系

4.1List子体系特点
A:有序的(存储和读取的顺序是一致的)
B:有整数索引
C:允许重复的
4.2List的特有功能
void add(int index, E element) :将元素添加到index索引位置上
E get(int index) :根据index索引获取元素
E remove(int index) :根据index索引删除元素
E set(int index, E element):将index索引位置的的元素设置为element
4.2.1案例代码八:

package com.itheima_05;
import java.util.ArrayList;
import java.util.List;
/*
 * List:
 * 		有序的(存储和读取的顺序是一致的)
 * 		有整数索引
 * 		允许重复的
 * 
 * List的特有功能:
 * 			void add(int index, E element)  
 * 			E get(int index)  
 * 			E remove(int index)  
 *  		E set(int index, E element)
 *  
 *   增删改查
 

 *   
 */
public class ListDemo {
	public static void main(String[] args) {
		//创建的列表对象
		List list = new ArrayList();
		
		//void add(int index, E element)  : 在指定索引位置添加指定元素
		list.add(0, "hello");
		list.add(0, "world");
		list.add(1, "java");
		
		//E get(int index)  :根据索引返回元素
		/*System.out.println(list.get(0));
		System.out.println(list.get(1));
		System.out.println(list.get(2));*/
		//System.out.println(list.get(3));
		
		/*for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}*/
		
		//E remove(int index)  : 删除指定元素并返回
		
		//System.out.println(list.remove(5));
		
		//E set(int index, E element) : 将指定索引位置的元素替换为指定元素,并将原先的元素返回
		System.out.println(list.set(0, "android"));
		
		System.out.println(list);
	}
}

4.3LinkedList特有功能
LinkedList底层使用的是链表结构,因此增删快,查询相对ArrayList较慢
void addFirst(E e) :向链表的头部添加元素
void addLast(E e):向链表的尾部添加元素
E getFirst():获取链头的元素,不删除元素
E getLast():获取链尾的元素,不删除元素
E removeFirst():返回链头的元素并删除链头的元素
E removeLast():返回链尾的元素并删除链尾的元素
4.3.1案例代码九:

 package com.itheima_06;
import java.util.LinkedList;

/*
 * List的常用子类:
 * 		ArrayList
 * 			底层是数组结构,查询快,增删慢
 * 		LinkedList
 * 			底层结构是链表,查询慢,增删快
 * 
 * 如何选择使用不同的集合?
 * 		如果查询多,增删少,则使用ArrayList
 * 		如果查询少,增删多,则使用LinkedList
 * 		如果你不知道使用什么,则使用ArrayList
 * 
 * LinkedList的特有功能:
 * 			void addFirst(E e)  
 * 			void addLast(E e) 
 			E getFirst()  
 			E getLast()  
 			E removeFirst() 
 			E removeLast() 
 * 				
 */
public class LinkedListDemo {
	public static void main(String[] args) {
			LinkedList list = new LinkedList();
			list.add("hello");
			list.add("world");
		
			//void addFirst(E e)  :将元素添加到索引为0的位置
 			//void addLast(E e) :将元素添加到索引为size()-1的位置
			list.addFirst("java");
			list.addLast("android");
			
 			//E getFirst()  :获取索引为0的元素
 			//E getLast()  :获取索引为size()-1的元素
			//System.out.println(list.getFirst());
			//System.out.println(list.getLast());
			
 			//E removeFirst() :删除索引为0的元素并返回
 			//E removeLast() :删除索引为size()-1的元素并返回
			System.out.println(list.removeFirst());
			System.out.println(list.removeLast());
			
			
			System.out.println(list);
	}
}

4.4案例代码九

package com.itheima_07;
import java.util.ArrayList;
import java.util.List;

/*
 * 需求:定义一个方法,返回指定列表中指定元素的索引位置
 * 
 * 判断元素是否存在
 * 
 */
public class ListTest {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("hello");
		list.add("world");
		list.add("java");
		
		//int index = index(list,"php");
		//System.out.println(index);
		
		//boolean flag = contains(list, "php");
		//System.out.println(flag);
		
		boolean flag = list.contains("php");
		System.out.println(flag);
	}
	
	public static int index(List list,Object other) {
		for(int x = 0;x < list.size();x++) {
			//获取列表中的元素
			Object obj = list.get(x);
			//使用列表中的元素和指定的元素进行比较
			if(obj.equals(other)) {
				return x;
			}
		}
		//查找不到指定的元素
		return -1;
	}
	
	public static boolean contains(List list,Object other) {
		//获取指定元素在指定列表中的索引位置
		int index = index(list,other);
		//如果索引位置大于等于0,则认为元素存在,否则不存在
		if(index >= 0) {
			return true;
		}
		else {
			return false;
		}
	}
	
	
	
}

第07天 集合

今日内容介绍
 HashSet集合
 HashMap集合

第1章HashSet集合

1.1Set接口的特点
Set体系的集合:
A:存入集合的顺序和取出集合的顺序不一致
B:没有索引
C:存入集合的元素没有重复
1.2HashSet使用&唯一性原理
1.2.1HashSet的使用
1.2.1.1案例代码一:

    public class HashSetDemo2 {
	public static void main(String[] args) {
		//创建集合对象
		HashSet<Student> hs = new HashSet<Student>();
		//创建元素对象
		Student s = new Student("zhangsan",18);
		Student s2 = new Student("lisi",19);
		Student s3 = new Student("lisi",19);
		//添加元素对象
		hs.add(s);
		hs.add(s2);
		hs.add(s3);
		//遍历集合对象
		for (Student student : hs) {
			System.out.println(student);
		}
		 
	}
		 
}

1.2.2HashSet唯一性原理
规则:新添加到HashSet集合的元素都会与集合中已有的元素一一比较
首先比较哈希值(每个元素都会调用hashCode()产生一个哈希值)
如果新添加的元素与集合中已有的元素的哈希值都不同,新添加的元素存入集合
如果新添加的元素与集合中已有的某个元素哈希值相同,此时还需要调用equals(Object obj)比较
如果equals(Object obj)方法返回true,说明新添加的元素与集合中已有的某个元素的属性值相同,那么新添加的元素不存入集合
如果equals(Object obj)方法返回false, 说明新添加的元素与集合中已有的元素的属性值都不同, 那么新添加的元素存入集合
1.2.2.1案例代码二:

  package com.itheima_01;

import java.util.HashSet;

/*
 *	使用HashSet存储自定义对象并遍历 	
 *	通过查看源码发现:
 *				HashSet的add()方法,首先会使用当前集合中的每一个元素和新添加的元素进行hash值比较,
 *				如果hash值不一样,则直接添加新的元素
 *				如果hash值一样,比较地址值或者使用equals方法进行比较
 *				比较结果一样,则认为是重复不添加
 *				所有的比较结果都不一样则添加

 */
public class HashSetDemo2 {
	public static void main(String[] args) {
		//创建集合对象
		HashSet<Student> hs = new HashSet<Student>();
		//创建元素对象
		Student s = new Student("zhangsan",18);
		Student s2 = new Student("lisi",19);
		Student s3 = new Student("lisi",19);
		//添加元素对象
		hs.add(s);
		hs.add(s2);
		hs.add(s3);
		//遍历集合对象
		for (Student student : hs) {
			System.out.println(student);
		}
		 
	}
		 
}

class Student {
	String name;
	int age;
	
	public Student(String name,int age) {
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}

	@Override
	public boolean equals(Object obj) {
		//System.out.println("-------------------");
		Student s = (Student)obj;//向下转型,可以获取子类特有成员
		
		//比较年龄是否相等,如果不等则返回false
		if(this.age != s.age) {
			return false;
		}
		
		//比较姓名是否相等,如果不等则返回false
		if(!this.name.equals(s.name)) {
			return false;
		}
		
		//默认返回true,说明两个学生是相等的
		return true;
	}
	
	@Override
	public int hashCode() {
		return 1;
	}
	
}

1.2.2.2hashCode方法优化:
如果让hashCode()方法返回一个固定值,那么每个新添加的元素都要调用equals(Object obj)方法比较,那么效率较低
只需要让不同属性的值的元素产生不同的哈希值,那么就可以不再调用equals方法比较提高效率
1.2.2.3案例代码三:

package com.itheima_02;

public class Person {
	String name;
	int age;
	
	public Person(String name,int age) {
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
	/*
	@Override
	public int hashCode() {
		
		 * 我们发现当hashCode方法永远返回整数1时,所有对象的hash值都是一样的,
		 * 有一些对象他的成员变量完全不同,但是他们还需要进行hash和equals方法的比较,
		 * 如果我们可以让成员变量不同的对象,他们的hash值也不同,这就可以减少一部分equals方法的比较
		 * 从而可以提高我们程序的效率
		 * 
		 * 可以尝试着让hashCode方法的返回值和对象的成员变量有关
		 * 可以让hashCode方法返回所有成员变量之和,
		 * 让基本数据类型直接想加,然后引用数据类型获取hashCode方法返回值后再相加(boolean不可以参与运算)
		 * 
		 
		//return age;
		return age + name.hashCode();
	}
	
	@Override
	public boolean equals(Object obj) {
		System.out.println("-------------");
		
		//提高效率
		if(this == obj) {
			return true;
		}
		
		//提高健壮性
		if(this.getClass() != obj.getClass()) {
			return false;
		}
		
		
		
		//向下转型
		Person p = (Person)obj;
		
		if(!this.name.equals(p.name)) {
			return false;
		}
		
		if(this.age != p.age) {
			return false;
		}
		
		return true;
		
	}*/
	
	
	
}
package com.itheima_02;

import java.util.HashSet;

public class HashSetDemo3 {
	public static void main(String[] args) {
		//创建集合对象
		HashSet<Person> hs = new HashSet<Person>();
		//创建元素对象
		Person p = new Person("zhangsan",18);
		Person p2 = new Person("lisi",18);
		Person p3 = new Person("lisi",18); 
       
		//添加元素对象
		hs.add(p);
		hs.add(p2);
		hs.add(p3);
		//遍历集合对象
		for (Person person : hs) {
			System.out.println(person);
		}
	}
}

1.3Collections中的方法
1.3.1案例代码四:

package com.itheima_03;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/*
 * Collections:
 * 面试题:Collection和Collections有什么区别?
 * 		Collection是集合体系的最顶层,包含了集合体系的共性
 * 		Collections是一个工具类,方法都是用于操作Collection
 * 
 */
public class CollectionsDemo {
	public static void main(String[] args) {
		//static void swap(List list, int i, int j) :将指定列表中的两个索引进行位置互换
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(4);
		Collections.swap(list, 0, 1);
		
		System.out.println(list);
	
	}

	private static void method6() {
		//static void  sort(List<T> list) :按照列表中元素的自然顺序进行排序
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(4);
		list.add(3);
		list.add(2);
		
		Collections.sort(list);
		System.out.println(list);
	}

	private static void method5() {
		//static void shuffle(List list):傻否,随机置换  
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		Collections.shuffle(list);
		System.out.println(list);
	}

	private static void method4() {
		//static void reverse(List list)  :反转
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		
		Collections.reverse(list);
		System.out.println(list);
	}

	private static void method3() {
		//static void fill(List list, Object obj) :使用指定的对象填充指定列表的所有元素
		List<String> list = new ArrayList<String>();
		list.add("hello");
		list.add("world");
		list.add("java");
		System.out.println(list);
		
		Collections.fill(list, "android");
		
		System.out.println(list);
	}

	private static void method2() {
		//static void copy(List dest, List src) :是把源列表中的数据覆盖到目标列表
		//注意:目标列表的长度至少等于源列表的长度
		//创建源列表
		List<String> src = new ArrayList<String>();
		src.add("hello");
		src.add("world");
		src.add("java");
		
		//创建目标列表
		List<String> dest = new ArrayList<String>();
		dest.add("java");
		dest.add("java");
		dest.add("java");
		dest.add("java");
		Collections.copy(dest, src);
		System.out.println(dest);
	}

	private static void method() {
		//static int  binarySearch(List list, Object key) 使用二分查找法查找指定元素在指定列表的索引位置 
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		
		int index = Collections.binarySearch(list, 4);
		System.out.println(index);
	}
}

1.4斗地主案例
具体规则:
1. 组装54张扑克牌
2. 将54张牌顺序打乱
3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张留作底牌。
4. 查看三人各自手中的牌、底牌
1.4.1案例代码五:

package com.itheima_03;

import java.util.ArrayList;
import java.util.Collections;

/*
 *	模拟斗地主发牌 
 	
 	买牌
 	洗牌
 	发牌
 
 */
public class CollectionsTest {
	public static void main(String[] args) {
		//买牌
		String[] arr = {"黑桃","红桃","方片","梅花"};
		String[] arr2 = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
		
		ArrayList<String> box = new ArrayList<String>();
		//添加每张牌
		for (int i = 0; i < arr.length; i++) {
			//获取每一个花色
			for (int j = 0; j < arr2.length; j++) {
				//获取每一个数
				box.add(arr[i] + arr2[j]);
			}
			
		}
		box.add("大王");
		box.add("小王");
		//System.out.println(box.size());
		
	 	//洗牌
		Collections.shuffle(box);
		//System.out.println(box);
		
	 	//发牌
		ArrayList<String> 林志玲 = new ArrayList<String>();
		ArrayList<String> 林心如 = new ArrayList<String>();
		ArrayList<String> 舒淇 = new ArrayList<String>();
		
		//留三张底牌给地主
		for (int i = 0; i < box.size() - 3; i++) {
			/*
			 *  i = 0;i % 3 = 0;
			 *  i = 1;i % 3 = 1;
			 *  i = 2;i % 3 = 2;
			 *  i = 3;i % 3 = 0;
			 *  i = 4;i % 4 = 1;
			 *  i = 5;i % 5 = 2;
			 */
			
			if(i % 3 == 0) {
				林志玲.add(box.get(i));
			}
			else if(i % 3 == 1) {
				林心如.add(box.get(i));
			}
			else if(i % 3 == 2) {
				舒淇.add(box.get(i));
			}
		}
		
		System.out.println("林志玲:" + 林志玲);
		System.out.println("林心如:" + 林心如);
		System.out.println("舒淇:" + 舒淇);
	 
	
		System.out.println("底牌:");
	/*	System.out.println(box.get(box.size() - 1));
		System.out.println(box.get(box.size() - 2));
		System.out.println(box.get(box.size() - 3));*/
		
		for (int i = box.size() - 3; i < box.size(); i++) {
			System.out.println(box.get(i));
		}
	}
	
}

第2章HashMap集合

2.1Map接口概述
我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同,如下图。
A:Collection中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储
B:Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。
C:Collection中的集合称为单列集合,Map中的集合称为双列集合。
需要注意的是,Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。

2.2Map常用功能
A:映射功能:
V put(K key, V value) :以键=值的方式存入Map集合
B:获取功能:
V get(Object key):根据键获取值
int size():返回Map中键值对的个数
C:判断功能:
boolean containsKey(Object key):判断Map集合中是否包含键为key的键值对
boolean containsValue(Object value):判断Map集合中是否包含值为value键值对
boolean isEmpty():判断Map集合中是否没有任何键值对
D:删除功能:
void clear():清空Map集合中所有的键值对
V remove(Object key):根据键值删除Map中键值对
E:遍历功能:
Set<Map.Entry<K,V>> entrySet():将每个键值对封装到一个个Entry对象中,再把所有Entry的对象封装到Set集合中返回
Set keySet() :将Map中所有的键装到Set集合中返回
Collection values():返回集合中所有的value的值的集合
2.2.1案例代码四:

package com.itheima_01;

import java.util.HashMap;
import java.util.Map;

/*
 * 	Map的常用功能:
 * 		映射功能:
 * 			 	V put(K key, V value) 
 * 		获取功能:
 * 				V get(Object key) 
 * 				int size() 
 * 		判断功能:
 * 				boolean containsKey(Object key) 
 				boolean containsValue(Object value) 
 				boolean isEmpty() 
 
 * 		删除功能:
 * 				void clear()  
 * 				V remove(Object key)  
 * 
 * 		遍历功能:
 * 				Set<Map.Entry<K,V>> entrySet() 
 * 
 * 
 * 			Set<K> keySet()  
 * 			Collection<V> values()  
 
 */
public class MapDemo2 {
	public static void main(String[] args) {
		//创建Map对象
		Map<String,String> map = new HashMap<String,String>();
		
		//V put(K key, V value) :就是将key映射到value,如果key存在,则覆盖value,并将原来的value返回
		System.out.println(map.put("ITCAST001", "张三"));
		System.out.println(map.put("ITCAST002", "李四"));
		System.out.println(map.put("ITCAST001", "王五"));
		
		//void clear() : 清空所有的对应关系  
		//map.clear();
		
		//V remove(Object key) :根据指定的key删除对应关系,并返回key所对应的值,如果没有删除成功则返回null
		//System.out.println(map.remove("ITCAST005"));
		
		//boolean containsKey(Object key) : 判断指定key是否存在
		//System.out.println(map.containsKey("ITCAST003"));
		
		//boolean containsValue(Object value):判断指定的value是否存在
		//System.out.println(map.containsValue("王五"));
		
		//boolean isEmpty() : 判断是否有对应关系
		//System.out.println(map.isEmpty());
		
		//int size() : 返回对应关系的个数
		//System.out.println(map.size());
		
		//V get(Object key) : 根据指定的key返回对应的value
		System.out.println(map.get("ITCAST002"));
		
		System.out.println(map);
	}
}

2.2.2案例代码五:

 package com.itheima_01;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
 * 	Set<K> keySet()  
 * 	Collection<V> values() 
 */
public class MapDemo3 {
	public static void main(String[] args) {
		//创建Map对象
		Map<String,String> map = new HashMap<String,String>();
		//添加映射关系
		map.put("ITCAST001", "张三");
		map.put("ITCAST002", "李四");
		map.put("ITCAST005", "李四");
		
		//Set<K> keySet() : 以Set的形式获返回所有的key
		Set<String> keys = map.keySet();
		for (String key : keys) {
			System.out.println(key);
		}
		System.out.println("-----------");
		
		//Collection<V> values() :
		Collection<String> values = map.values();
		for (String value : values) {
			System.out.println(value);
		}
	}
}

2.3Map的两种遍历方式
2.3.1利用keySet()方法遍历

   package com.itheima_01;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
 * 	Map的第一种遍历方式:
 * 			首先召集所有的丈夫
 * 			遍历所有的丈夫
 * 			获取每一个丈夫
 * 			让每一个丈夫去找他自己的媳妇
 */
public class MapDemo4 {
	public static void main(String[] args) {
		//创建Map对象
		Map<String,String> map = new HashMap<String,String>();
		//添加映射关系
		map.put("谢婷疯", "张箔纸");
		map.put("陈关西", "钟欣桶");
		map.put("李亚碰", "王飞");
		//遍历Map对象
		
		//首先召集所有的丈夫
		Set<String> keys = map.keySet();
		//遍历所有的丈夫
		for (String key : keys) {
			//让每个丈夫去找他自己的媳妇就可以了
			String value = map.get(key);
			System.out.println("丈夫:" + key + "---" + "媳妇:" + value);
		}
		
	}
}

2.3.2利用entrySet()方法遍历

package com.itheima_01;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
 * 	Map的第二种遍历方式:
 * 		通过结婚证对象来获取丈夫和媳妇
 * 
 *  class 结婚证<K,V> {
 *  	K 丈夫;
 *  	V 媳妇;
 *  
 *  	public 结婚证(K 丈夫,V 媳妇) {
 *  		this.丈夫 = 丈夫;
 *  		this.媳妇 = 媳妇;
 *  	}
 *  
 *  
 *  	public K get丈夫() {
 *  		return 丈夫;
 *  	}
 *  
 *  	public V get媳妇() {
 *  		return 媳妇;
 *  	}
 *  }
 *  
 *  
 *  class Entry<K,V> {
 *  	K key;
 *  	V value;
 *  
 *  	public Entry(K key,V value) {
 *  		this.key = key;
 *  		this.value = value;
 *  	}
 *  
 *  
 *  	public K getKey() {
 *  		return key;
 *  	}
 *  
 *  	public V getValue() {
 *  		return value;
 *  	}
 *  }
 *  
 *  Set<Map.Entry<K,V>> entrySet()  
 * 
 */
public class MapDemo5 {
	public static void main(String[] args) {
		//创建Map对象
		Map<String,String> map = new HashMap<String,String>();
		//添加映射关系
		map.put("尹志平", "小龙女");
		map.put("令狐冲", "东方菇凉");
		map.put("玄慈", "叶二娘");
		//获取所有的结婚证对象
		Set<Map.Entry<String,String>> entrys = map.entrySet();
		//遍历包含了结婚证对象的集合
		for (Map.Entry<String, String> entry : entrys) {
			//获取每个单独的结婚证对象
			//通过结婚证对象获取丈夫和媳妇
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println("丈夫:" + key + "---" + "媳妇:" + value);
		}
		
	}
}

2.3.3练习:
A:以key为学号字符串,value为学生姓名存入HashMap集合,分别以两种方式遍历集合
2.3.3.1案例代码一:

package com.itheima_02;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
 * 
 * 使用HashMap存储数据并遍历(字符串作为key)
 * 
 */
public class HashMapDemo {
	public static void main(String[] args) {
		//创建Map对象
		HashMap<String,String> hm = new HashMap<String,String>();
		//添加映射关系
		hm.put("ITCAST001", "张三");
		hm.put("ITCAST002", "李四");
		hm.put("ITCAST003", "王五");
		hm.put("ITCAST003", "赵六");
		//遍历Map对象
		
		//方式1 获取所有的key,通过key来获取value
		Set<String> keys = hm.keySet();
		for (String key : keys) {
			String value = hm.get(key);
			System.out.println(key + "=" + value);
		}
		
		System.out.println("------------------");
		
		//方式2:获取所有的结婚证对象,然后通过结婚证对象获取丈夫和媳妇
		Set<Map.Entry<String, String>> entrys = hm.entrySet();
		for (Map.Entry<String, String> entry : entrys) {
			String key = entry.getKey();
			String value = entry.getValue();
			System.out.println(key + "=" + value);
		}
	}
}

B: 定义一个学生类,学生类中有name和age两个属性,创建三个学生对象,分别对name和age赋值,然后以key为学生对象,value为学生的学号的方式存入HashMap集合,利用两种方式遍历这个Map
2.3.3.2案例代码二:

package com.itheima_02;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/*
 * 
 * 使用HashMap存储数据并遍历(自定义对象作为key)
 * 
 */
public class HashMapDemo2 {
	public static void main(String[] args) {
		//创建Map对象
		HashMap<Student,String> hm = new HashMap<Student,String>();
		//创建key对象
		Student s = new Student("zhangsan",18);
		Student s2 = new Student("lisi",20);
		Student s3 = new Student("lisi",20);
		
		//添加映射关系
		hm.put(s, "ITCAST001");
		hm.put(s2, "ITCAST002");
		hm.put(s3, "ITCAST002");
		
		//遍历Map对象
		//方式1: 获取所有的key,通过key来获取value
		Set<Student> keys = hm.keySet();
		for (Student key : keys) {
			String value = hm.get(key);
			System.out.println(key + "=" + value);
		}
		System.out.println("-----");
		
		//方式2:获取所有结婚证对象,通过结婚证对象获取丈夫和媳妇
		Set<Map.Entry<Student, String>> entrys = hm.entrySet();
		for (Entry<Student, String> entry : entrys) {
			Student key = entry.getKey();
			String value = entry.getValue();
			
			System.out.println(key + "=" + value);
		}
		
	}
}

第08天 异常

今日内容介绍
 异常体系&异常处理
 Throwable常用方法&自定义异常
 递归

第1章异常产生&异常处理

1.1异常概述
什么是异常?Java代码在运行时期发生的问题就是异常。
在Java中,把异常信息封装成了一个类。当出现了问题时,就会创建异常类对象并抛出异常相关的信息(如异常出现的位置、原因等)。
在Java中使用Exception类来描述异常。

查看API中Exception的描述,Exception 类及其子类是 Throwable 的一种形式,它用来表示java程序中可能会产生的异常,并要求对产生的异常进行合理的异常处理。

继续观察,我们可以发现Exception有继承关系,它的父类是Throwable。Throwable是Java 语言中所有错误或异常的超类,即祖宗类。

另外,在异常Exception类中,有一个子类要特殊说明一下,RuntimeException子类,RuntimeException及其它的子类只能在Java程序运行过程中出现。

我们再来观察Throwable类,能够发现与异常Exception平级的有一个Error,它是Throwable的子类,它用来表示java程序中可能会产生的严重错误。解决办法只有一个,修改代码避免Error错误的产生。

1.1.1案例代码一:

    package com.itheima_01;

import java.io.FileWriter;

/*
 * Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.itheima_01.ExceptionDemo.main(ExceptionDemo.java:5)
	我们在写代码的时候,经常的出现一些小问题,那么为了方便我们处理这些问题,java为我们提供了异常机制
	
	异常包含了错误的类型、原因以及位置
	
	异常:不正常,我们在代码的时候出现的编译或者运行时的错误
	
	异常的体系结构:
			Throwable(最顶层)
					Error:出现的不能够处理的严重问题
					Exception:可以处理的问题
					
	电脑坏了:
		系统中毒:重装系统就可以了
		主板坏了:买一台新的
 * 
 */
public class ExceptionDemo {
	public static void main(String[] args) {
		//int a = 10 / 0;
		//System.out.println(a);
		
		//FileWriter fw = new FileWriter("a.txt");
	}
}

1.2异常处理
1.2.1JVM默认处理方式
如果出现异常我们没有处理,jvm会帮我们进行处理,他会把异常的类型,原因还有位置显示在命令行并且还终止了程序,异常后面的代码将不在执行
1.2.1.1案例代码二:

package com.itheima_01;
import java.io.FileWriter;
import java.io.IOException;

/*
 * 	异常的处理方式:

 * 		
 * 
 *  jvm处理异常的方式:
 *  	如果出现异常我们没有处理,jvm会帮我们进行处理,他会把异常的类型,原因还有位置显示在命令行
 *  	并且还终止了程序,异常后面的代码将不在执行
 */
public class ExceptionDemo2 {
	public static void main(String[] args) throws Exception {
	   System.out.println(2/0);
	   System.out.println("hello");
     		
	}
	
 
}

1.2.2try…catch方式处理异常
捕获:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理捕获异常格式:
try {
//需要被检测的语句。
}
catch(异常类 变量) { //参数。
//异常的处理语句。
}
finally {
//一定会被执行的语句。
}
try:该代码块中编写可能产生异常的代码。
catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。
1.2.2.1案例代码三:

    package com.itheima_01;
import java.io.FileWriter;
import java.io.IOException;

/*
 * 	异常的处理方式:
 * 			捕获处理
 * 				try...catch语句
 * 
 * 				try {
 * 					有可能出现问题的代码;
 * 				} catch(ArithmeticException ae) {
 * 					处理异常;
 * 				}
 * 
 * 				try...catch的执行顺序:
 * 					首先执行try语句
 * 						如果发现异常,异常下面的代码不在执行,直接跳入catch语句中,catch语句结束后,整个try...catch结束
 * 						如果没有发现异常,try语句执行结束后,try...catch直接结束, 不在执行catch语句
 * 
 * 
 
 * 		
 * 
 *  jvm处理异常的方式:
 *  	如果出现异常我们没有处理,jvm会帮我们进行处理,他会把异常的类型,原因还有位置显示在命令行
 *  	并且还终止了程序,异常后面的代码将不在执行
 */
public class ExceptionDemo2 {
	public static void main(String[] args) throws Exception {
		try {
			System.out.println(1);
			//System.out.println(2 / 0);
			System.out.println(2);
		} catch(ArithmeticException ae) {
			System.out.println("除数不能为0");
		}
		
		System.out.println(3);
		
	}
}

1.2.3throws方式处理异常
A:throws使用:
权限修饰符 返回值类型 方法名(形参列表) throws 异常类型1,异常类型2….{
}
1.2.3.1案例代码四:

   package com.itheima_01;

import java.io.FileWriter;
import java.io.IOException;

/*
 * 	异常的处理方式:
 * 			捕获处理
 * 				try...catch语句
 * 
 * 				try {
 * 					有可能出现问题的代码;
 * 				} catch(ArithmeticException ae) {
 * 					处理异常;
 * 				}
 * 
 * 				try...catch的执行顺序:
 * 					首先执行try语句
 * 						如果发现异常,异常下面的代码不在执行,直接跳入catch语句中,catch语句结束后,整个try...catch结束
 * 						如果没有发现异常,try语句执行结束后,try...catch直接结束, 不在执行catch语句
 * 
 * 
 * 			抛出去
 * 				当我们不想处理异常,或者没有能力处理的时候,我们可以选择抛出异常,谁调用方法谁处理异常
 * 				使用关键字throws在方法的声明出抛出异常

 * 		
 * 
 *  jvm处理异常的方式:
 *  	如果出现异常我们没有处理,jvm会帮我们进行处理,他会把异常的类型,原因还有位置显示在命令行
 *  	并且还终止了程序,异常后面的代码将不在执行
 */
public class ExceptionDemo2 {
	public static void main(String[] args) throws Exception {
		//method();
		
		function();
		
	}
	
	public static void function() throws Exception {
		FileWriter fw = new FileWriter("a.txt");
	}

	private static void method() {
		try {
			System.out.println(1);
			//System.out.println(2 / 0);
			System.out.println(2);
		} catch(ArithmeticException ae) {
			System.out.println("除数不能为0");
		}
		
		System.out.println(3);
	}

}

1.2.4多异常处理
A:对代码进行异常检测,并对检测的异常传递给catch处理。对每种异常信息进行不同的捕获处理。
void show(){ //不用throws
try{
throw new Exception();//产生异常,直接捕获处理
}catch(XxxException e){
//处理方式
}catch(YyyException e){
//处理方式
}catch(ZzzException e){
//处理方式
}
}
注意:这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。
1.2.4.1案例代码五:

   package com.itheima_01;
/*
 * 	如何处理多个异常:
 * 		可以使用多个try...catch语句
 * 		使用一个try和多个catch
 * 
 * 多个catch之间的顺序:
 * 			多个catch之间可以有子父类
 * 			平级之间没有顺序关系
 * 			如果有子父类,父类异常必须放在后面
 * 			
 * 	
 */
public class ExceptionDemo3 {
	public static void main(String[] args) {
		try {
			String s = null;
			System.out.println(s.length());
			
			//int[] arr = new int[5];
			//System.out.println(arr[8]);
			
			//System.out.println(2 / 0);
			
		} 
		
		catch(ArrayIndexOutOfBoundsException e) {
			System.out.println("出现数组越界了");
		} 
		catch(NullPointerException e) {
			System.out.println("出现空指针了");
		}
		catch(Exception e) {
			System.out.println("出现异常了");
		}
		/*try {
		} catch(ArrayIndexOutOfBoundsException e) {
			System.out.println("出现数组越界了");
		}*/
		

	}

	private static void method() {
		try {
			String s = null;
			System.out.println(s.length());
		} catch(NullPointerException e) {
			System.out.println("出现空指针了");
		}
		
		try {
			int[] arr = new int[5];
			System.out.println(arr[8]);
		} catch(ArrayIndexOutOfBoundsException e) {
			System.out.println("出现数组越界了");
		}
	}

}

第2章Throwable常用方法&自定义异常

2.1Throwable常用方法
String getMessage() 返回此 throwable 的详细消息字符串
String toString() 返回此 throwable 的简短描述
void printStackTrace() 打印异常的堆栈的跟踪信息
2.1.1案例代码六:

package com.itheima_01;
/*
 * Throwable的常用方法:
		String getMessage()  
		String toString()  
		void printStackTrace()  
 * 	
 */
public class ExceptionDemo4 {
	public static void main(String[] args) {
	
		
		try {
			System.out.println(2 / 0);
		} catch (ArithmeticException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void method() {
		try {
			System.out.println(2 / 0);
		} catch(ArithmeticException e) {
			//String getMessage() : 原因
			//System.out.println(e.getMessage());
			
			//String toString()  类型和原因
			//System.out.println(e.toString());

			//void printStackTrace():类型原因和位置
			e.printStackTrace();
		}
		
		//System.out.println("hello");
	}
}

2.2finally的概述和应用场景
finally使用格式:
try{
}catch(异常类型 异常变量){
}finally{
//释放资源的代码
}
2.2.1案例代码七:

   package com.itheima_01;
import java.io.FileWriter;
import java.io.IOException;

/*
 *  finally:组合try...catch使用,用于释放资源等收尾工作,无论try...catch语句如何执行,finally的代码一定会执行
 *  
 *  try {
 *  	有可能出现问题的代码;
 *  
 *  } catch(异常对象) {
 *  	处理异常;
 *  } finally {
 *  	释放资源;
 *  	清理垃圾;
 *  }
 *  
 */
public class ExceptionDemo5 {
	public static void main(String[] args) {
		//method();
		
		FileWriter fw = null;
		try {
			System.out.println(2 / 0);
			fw = new FileWriter("a.txt");
			fw.write("hello");
			fw.write("world");
			//System.out.println(2 / 0);
			fw.write("java");
			
			//fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			//释放资源
			try {
				if(fw != null) {
					fw.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

	private static void method() {
		try {
			System.out.println(2 / 1);
			
		} catch(ArithmeticException e) {
			System.out.println("除数不能为0");
		} finally {
			
			System.out.println("清理垃圾");
		}
	}

	

}

2.3编译时异常&运行时异常
A: 编译时期异常:是Exception的子类,非RuntimeExcpetion的子类,在编译时期必须处理
B:RuntimeException和他的所有子类异常,都属于运行时期异常。NullPointerException,ArrayIndexOutOfBoundsException等都属于运行时期异常.
运行时期异常的特点:
方法中抛出运行时期异常,方法定义中无需throws声明,调用者也无需处理此异常
运行时期异常一旦发生,需要程序人员修改源代码.
2.3.1案例代码八:

package com.itheima_01;

import java.io.FileWriter;
import java.io.IOException;

/*
 * 异常的分类:
		运行时期异常:RuntimeException的子类就是运行时期异常,在编译时期可以自由选择处理或者不处理
		编译时期异常:是Exception的子类,非RuntimeExcpetion的子类,在编译时期必须处理
 
 */
public class ExceptionDemo6 {
	public static void main(String[] args) {
		//System.out.println(2 / 0);
		
		//String s = null;
		//System.out.println(s.length());
		
		try {
			FileWriter fw = new FileWriter("a.txt");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

2.4自定义异常
需求:写一个方法,接受考试成绩,如果考试成绩的范围在0-100之间则属于正常,否则属于异常
2.4.1案例代码九:
当成绩不在0~100范围内,抛出一个运行时异常或者编译时异常,阻止程序继续向下执行

     package com.itheima_01;
/*
 * 需求:写一个方法,接受考试成绩,如果考试成绩的范围在0-100之间则属于正常,否则属于异常
 * 
 * throws:处理异常的一种方式,把异常抛出,由调用者来处理
 * throw:制造异常的方式,并且结束方法
 * 
 * 注意:如果抛出(throw)的是编译时期异常,必须在方法声明处抛出(throws)
 * 
 * 如何自定义一个异常类呢?
 * 		非常简单,写一个类去继承Exception或者RuntimeException,然后实现多个构造即可
 * 
 *  */
public class ExceptionDemo7 {
	public static void main(String[] args) {
		/*boolean flag = checkScore(-10);
		System.out.println(flag);*/
		
		
		
		try {
			checkScore(110);
		} catch (Exception e) {
			//System.out.println(e.getMessage());
			e.printStackTrace();
		}
		
		
		//checkScore(110);
	}
	
/*	public static boolean checkScore(int score) {
		//判断考试成绩是否符合范围,如果不符合则返回false
		if(score < 0 || score > 100) {
			return false;
		}
		
		//符合
		return true;
		
	}*/
	
	public static void checkScore(int score) throws Exception {
		if(score < 0 || score > 100) {
			throw new RuntimeException("考试成绩不符合要求");
			//throw new Exception("考试成绩不符合要求");
		} 
		
		System.out.println("考试成绩符合要求");
	}
	
	
}

2.4.2案例代码十:
我们也可以自定义一个编译时异常或者运行时异常来抛出:

   package com.itheima_01;

public class MyException extends /*RuntimeException*/ Exception{

	public MyException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public MyException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}
	/*public MyException() {
		super();
	}
	
	public MyException(String s) {
		super(s);
	}*/
	
	
}



package com.itheima_01;
/*
 * 需求:写一个方法,接受考试成绩,如果考试成绩的范围在0-100之间则属于正常,否则属于异常
 * 
 * throws:处理异常的一种方式,把异常抛出,由调用者来处理
 * throw:制造异常的方式,并且结束方法
 * 
 * 注意:如果抛出(throw)的是编译时期异常,必须在方法声明处抛出(throws)
 * 
 * 如何自定义一个异常类呢?
 * 		非常简单,写一个类去继承Exception或者RuntimeException,然后实现多个构造即可
 * 
 *  */
public class ExceptionDemo7 {
	public static void main(String[] args) {
		/*boolean flag = checkScore(-10);
		System.out.println(flag);*/
		
		
		
		try {
			checkScore(110);
		} catch (Exception e) {
			//System.out.println(e.getMessage());
			e.printStackTrace();
		}
		
		
		//checkScore(110);
	}
	
 
	public static void checkScore(int score) throws Exception {
		if(score < 0 || score > 100) {
		 
			throw new MyException("考试成绩不符合要求");
		} 
		
		System.out.println("考试成绩符合要求");
	}
	
	
}

第3章递归

3.1递归
递归,指在当前方法内调用自己的这种现象
public void method(){
System.out.println(“递归的演示”);
//在当前方法内调用自己
method();
}

3.2递归练习

3.2.1递归求5的阶乘
利用递归求出5!的结果
3.2.1.1案例代码十一:

    package com.itheima_01;
/*
 * 需求:求5的阶乘
 * 5! = 5 * 4 * 3 * 2 * 1;  //120
 * 5! = 5 * 4!;					//120
 * 		4! = 4 * 3!;			//24
 * 			3! = 3 * 2!;		//6
 * 				2! = 2 * 1!;	//2
 * 					1! = 1;     //1
	n! = n * (n - 1)!
	
	递归:把大问题拆成很多小问题,然后再把小问题拆成更多的小问题,
			当我们把更多小问题解决了,小问题也解决了
				随着小问题的解决,大问题也随之解决了
	在方法本身不断的调用方法自己
	
	递归注意事项:
			递归一定要有出口,内存溢出
			递归次数不宜过多,内存溢出
			
	public void show(int n) {//5
		//出口
		if(n == 0) {
			return;
		}
		
		show(n - 1);
	}
	
	从前有座山,山里有个庙,庙里有个老和尚,老和尚在给小和尚讲故事
 * 		从前有座山,山里有个庙,庙里有个老和尚,老和尚在给小和尚讲故事
 * 			从前有座山,山里有个庙,庙里有个老和尚,老和尚在给小和尚讲故事
 * 				从前有座山,山里有个庙,庙里有个老和尚,老和尚在给小和尚讲故事
 * 					从前有座山,山里有个庙,庙里有个老和尚,老和尚在给小和尚讲故事
 * 					...
 * 
 * 	学习编程...找工作...赚钱...娶媳妇...生娃娃
		学习编程...找工作...赚钱...娶媳妇...生娃娃
			学习编程...找工作...赚钱...娶媳妇...生娃娃
				学习编程...找工作...赚钱...娶媳妇...生娃娃
					学习编程...找工作...赚钱...娶媳妇...生娃娃
					...
 * 
 */
public class RecurrenceDemo {
	public static void main(String[] args) {
		int result = jC(5);
		System.out.println(result);//120
	}
	
	
	//求一个数的阶乘
	public static int jC(int n) {
		//必须要有出口
		if(n == 1) {
			return 1;
		}
		else {
			return n * jC(n - 1);
		}
	}
	
}

3.2.2斐波纳挈数列
有一对兔子,从出生后第3个月起每个月都生一对兔子,
小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,
问第二十个月的兔子对数为多少?
3.2.2.1案例代码十二:

    package com.itheima_01;
/*
 * 古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,
 * 		     小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,
 *  	     问第二十个月的兔子对数为多少?
 *  
 *  
 *  1
 *  1
 *  2
 *  3
 *  5
 *  8
 *  13
 *  
 *  规律:除了第一个月和第二月以外,其余每个月都是前两个月之和
 *  斐波那契列数
 *  
 */
public class RecurrenceDemo2 {
	public static void main(String[] args) {
		int result = method(20);//6765
		System.out.println(result);
	}
	
	public static int method(int n) {
		//如果是第一个月,只有一对兔子
		if(n == 1) {
			return 1;
		}
		//如果是第二个月,也只有一对兔子
		else if(n == 2) {
			return 1;
		}
		else {
			//如果不是第一个月和第二个月,则兔子的数量是前两个月之和
			return method(n - 1) + method(n - 2);
		}
	}
}

第09天 IO流

今日内容介绍
 File类
 字符流与字节流

第1章File类

1.1File概述
打开API,搜索File类。阅读其描述:File文件和目录路径名的抽象表示形式。即,Java中把文件或者目录(文件夹)都封装成File对象。也就是说如果我们要去操作硬盘上的文件,或者文件夹只要找到File这个类即可,那么我们就要研究研究File这个类中都有那些功能可以操作文件或者文件夹呢
1.2File类的构造函数
File(String pathname) :将一个字符串路径封装成File对象
File(String parent,String child):传入一个父级路径和子级路径
File(File parent,String child):传入一个File类型的父级路径和子级路径
1.2.1案例代码一:

package com.itheima_01;
import java.io.File;
/*
 * File:文件和目录路径名的抽象表示形式,File 类的实例是不可变的
 * 
 * 构造方法:
 * 		File(File parent, String child) 
 * 		File(String pathname) 
 * 		File(String parent, String child) 	 
 * 
 * 
 */
public class FileDemo {
	public static void main(String[] args) {
		//File(String pathname) :将指定的路径名转换成一个File对象
		//File f = new File("D:\\a\\b.txt");
		
		//File(String parent, String child) : 根据指定的父路径和文件路径创建File对象
		//File f2 = new File("D:\\a","b.txt");
		
		//File(File parent, String child) :根据指定的父路径对象和文件路径创建File对象
		//File parent = new File("D:\\a");
		//File f3 = new File(parent,"b.txt");
		
		File f4 = new File(new File("D:\\a"),"b.txt");
		
	}
}

1.3File类创建和删除功能
boolean createNewFile():指定路径不存在该文件时时创建文件,返回true,否则返回false
boolean mkdir():当指定的单级文件夹不存在时创建文件夹并返回true,否则返回false
boolean mkdirs():当指定的多级文件夹某一级文件夹不存在时,创建多级文件夹并返回true,否则返回false
boolean delete():删除文件或者删除单级文件夹
1.3.1案例代码二:

package com.itheima_01;

import java.io.File;
import java.io.IOException;

/*
 * 	创建功能
 * 		boolean createNewFile()  
 * 		boolean mkdir()  
 * 		boolean mkdirs()  
 * 	删除功能
 * 		boolean delete() 
 * 
 *  绝对路径:固定不可改变的路径,以盘符开头
 *  相对路径:相对某个参照物,不能以盘符开头
 *  		在eclipse中相对路径相对应当前项目的根目录
 *  
 *  
 *  注意:删除一个文件夹,这个文件夹下面不能有其他的文件和文件夹

 */
public class FileDemo2 {
	public static void main(String[] args) throws IOException {
		  File f = new File("d:\\a\\b.txt");//绝对路径
		  File f2 = new File("a.txt");//相对路径
		
		 //boolean createNewFile() : 当指定文件不存在时创建文件并返回true,否则返回false
		 System.out.println(f2.createNewFile());
		
		 
		//boolean mkdir()   : 当指定文件夹不存在时创建文件夹并返回true,否则返回false
		File f3 = new File("b");
		System.out.println(f3.mkdir());
		
		//boolean mkdirs() : 创建指定文件夹,当文件夹所在的目录不存在,则顺道一块创建了
		File f4 = new File("c\\d\\e");
		System.out.println(f4.mkdir());
		System.out.println(f4.mkdirs());
		
		File f5 = new File("c.txt");
		System.out.println(f5.mkdir());
		
		//boolean delete() :当指定的文件或文件夹存在时删除文件或者文件夹 并返回true,否则返回false
		System.out.println(f2.delete());
		System.out.println(f3.delete());

		File f6 = new File("c");
		System.out.println(f6.delete());
		
	}
}

1.4File类的判断功能
boolean exists():判断指定路径的文件或文件夹是否存在
boolean isAbsolute():判断当前路路径是否是绝对路径
boolean isDirectory():判断当前的目录是否存在
boolean isFile():判断当前路径是否是一个文件
boolean isHidden():判断当前路径是否是隐藏文件
1.4.1案例代码三:

package com.itheima_01;
import java.io.File;
import java.io.IOException;

/*
 *	判断功能
 * 		boolean exists()  
 * 		boolean isAbsolute()  
 * 		boolean isDirectory() 
 		boolean isFile()  
 		boolean isHidden() 
 */
public class FileDemo3 {
	public static void main(String[] args) throws IOException {
		//method();
		//method2();
		//method3();
		
		method4();
		
		
		
	}

	private static void method4() {
		File f = new File("d:\\a\\b.txt");
		//boolean isHidden() :判断File对象指向的路径是否有隐藏属性,如果隐藏了则返回true,否则返回false
		
		System.out.println(f.isHidden());
	}

	private static void method3() {
		File f = new File("a.txt");
		File f2 = new File("b");
		//boolean isDirectory() :判断File对象指向的路径是否是文件夹,如果是则返回true,否则返回false
		//boolean isFile()  : 判断File对象指向的路径是否是文件,如果是则返回true,否则返回false
		
		//System.out.println(f.isDirectory());
		//System.out.println(f2.isDirectory());
		
		System.out.println(f.isFile());
		System.out.println(f2.isFile());
	}

	private static void method2() {
		//File f = new File("a.txt");
		File f2 = new File("d:\\a\b.txt");
		
		//boolean isAbsolute() :判断File对象指向的路径是否是绝对路径,如果是绝对路径则返回true,否则返回false
		System.out.println(f2.isAbsolute());
	}

	private static void method() {
		File f = new File("a.txt");
		//f.createNewFile();
		
		//boolean exists() : 判断文件或者文件夹是否存在,如果存在则返回true,否则返回false
		System.out.println(f.exists());
	}
}

1.5File类的获取功能和修改名字功能
File getAbsoluteFile():获取文件的绝对路径,返回File对象
String getAbsolutePath():获取文件的绝对路径,返回路径的字符串
String getParent():获取当前路径的父级路径,以字符串形式返回该父级路径
File getParentFile():获取当前路径的父级路径,以字File对象形式返回该父级路径
String getName():获取文件或文件夹的名称
String getPath():获取File对象中封装的路径
long lastModified():以毫秒值返回最后修改时间
long length():返回文件的字节数
boolean renameTo(File dest): 将当前File对象所指向的路径 修改为 指定File所指向的路径
1.5.1案例代码四:

  package com.itheima_01;

import java.io.File;
import java.io.IOException;

/*
 *	获取功能
 		File getAbsoluteFile()  
 * 		String getAbsolutePath() 
 * 		String getParent()  
 * 		File getParentFile() 
 * 		String getName() 
 * 		String getPath()  
  		long lastModified() 
  		long length() 
  	修改功能:
 		boolean renameTo(File dest)
 */
public class FileDemo4 {
	public static void main(String[] args) throws IOException  {
		//method();
		//method2();
		//method3();
		
		File f = new File("d.txt");
		File f2 = new File("e.txt");
		
		//boolean renameTo(File dest) : 将当前File对象所指向的路径 修改为 指定File所指向的路径
		//注意:修改的文件路径不能存在,如果存在则修改失败
		System.out.println(f.renameTo(f2));
	}

	private static void method3() {
		File f = new File("a.txt");
		File f2 = new File("d:\\a\\b.txt");
		File f3 = new File("b");
		
		//String getName() : 获取文件和文件夹的名称
		//System.out.println(f.getName());
		//System.out.println(f2.getName());
		//System.out.println(f3.getName());
		
		//String getPath() : 返回创建File对象时给的路径
		//System.out.println(f.getPath());
		//System.out.println(f2.getPath());
		//System.out.println(f3.getPath());
		
		//long lastModified() : 以毫秒值的形式返回最后修改时间
		//System.out.println(f.lastModified());
		//2514023311294
		//Date d = new Date(2514023311294L);
		//System.out.println(d.toLocaleString());
		
		//long length() : 返回文件的字节数
		System.out.println(f.length());
		System.out.println(f3.length());
	}

	private static void method2() throws IOException {
		//File f = new File("a.txt");
		
		//File f2 = new File("b","c.txt");
		//System.out.println(f2.createNewFile());
		
		File parent = new File("b");
		File f3 = new File(parent,"c.txt");
		if(!parent.exists()) {
			parent.mkdirs();
		}
		System.out.println(f3.createNewFile());
		
		//String getParent() 
		System.out.println(f3.getParent());
		//File getParentFile() 
		System.out.println(f3.getParentFile());
	}

	private static void method() {
		File f = new File("d:\\a\\b.txt");
		File f2 = new File("a.txt");
		
		//File getAbsoluteFile()  :以File对象的形式返回当前File对象所有指向的绝对路径
		System.out.println(f2.getAbsoluteFile());
		//String getAbsolutePath() : 返回File对象所指向的绝对路径
		System.out.println(f2.getAbsolutePath());
	}

}

1.6File类的其它获取功能
String[] list():以字符串数组的形式返回当前路径下所有的文件和文件夹的名称
File[] listFiles():以File对象的形式返回当前路径下所有的文件和文件夹的名称
static File[] listRoots():获取计算机中所有的盘符
1.6.1案例代码五:

package com.itheima_01;
import java.io.File;

/*
 * 	String[] list() 
 	File[] listFiles() 
 	static File[] listRoots() 
 */
public class FileDemo5 {
	public static void main(String[] args)  {
		//method();
		//method2();
		
		//static File[] listRoots() :  返回的是所有盘符
		File[] files = File.listRoots();
		for (File file : files) {
			System.out.println(file);
		}
		
		
	}

	private static void method2() {
		File f = new File("b");
		File f2 = new File("D:\\workspace\\myFile");
		File f3 = new File("c.txt");
		
		//File[] listFiles()
		File[] files = f3.listFiles();
		for (File file : files) {
			System.out.println(file.getName());
		}
	}

	private static void method() {
		File f = new File("b");
		File f2 = new File("D:\\workspace\\myFile");
		File f3 = new File("c.txt");
		
		//String[] list() : 返回当前路径下所有的文件和文件夹名称
		//注意:只有指向文件夹的File对象才可以调用该方法
		String[] files = f3.list();
		for (int i = 0; i < files.length; i++) {
			System.out.println(files[i]);
		}
	}


}

1.7File类两个案例
1.7.1案例代码六

输出指定目录下所有的java文件名(包含子目录)

package com.itheima_02;

import java.io.File;

/*
 * 需求:输出指定目录下所有的java文件名(包含子目录)
 */
public class RecurrenceTest {
	public static void main(String[] args) {
		File f = new File("src");
		//File f = new File("src\\com\\itheima_01\\RecurrenceDemo.java");
		method(f);
	}
	
	public static void method(File file) {
		if(file.isDirectory()) {
			File[] files = file.listFiles();
			for (File f : files) {
				//判断是否是文件对象
				if(f.isFile()) {
					if(f.getName().endsWith(".java")) {
						System.out.println(f.getName());
					}
				}
				else if(f.isDirectory()){
					//是一个目录对象
					method(f);
				}
			}
		}
	}
	
	
	//输出指定目录下的所有java文件名(不包含子目录)
	public static void method2(File file) {
		if(file.isDirectory()) {
			File[] files = file.listFiles();
			for (File f : files) {
				//判断是否是文件对象
				if(f.isFile()) {
					if(f.getName().endsWith(".java")) {
						System.out.println(f.getName());
					}
				}
			}
		}
	}
	
}

1.7.2案例代码七
删除指定的目录(包含子目录)

package com.itheima_02;

import java.io.File;

/*
 * 需求:删除指定的目录(包含子目录)
 * 
 * 注意:如果要删除一个目录,则需要先删除这个目录下的所有子文件和子目录
 * 
 */
public class RecurrenceTest2 {
	public static void main(String[] args) {
		File f = new File("d:\\a");
		method(f);
	}
	
	//删除指定目录下所有文件和目录
	public static void method(File file) {
		if(file.isDirectory()) {
			//干掉自己所有的子文件和子目录
			//获取所有的子文件和子目录
			File[] files = file.listFiles();
			for (File f : files) {
				if(f.isFile()) {
					//直接干掉他
					System.out.println(f.getName());
					f.delete();
				}
				else if(f.isDirectory()) {
					//继续查看是否还有文件和子目录
					method(f);
				}
			}
			
			//干掉自己
			System.out.println(file.getName());
			file.delete();
		}
	}
}

第2章字符流与字节流

2.1概述
IO流分类:
流向
输入流 读取数据 FileReader Reader
输出流 写出数据 FileWriter Writer
数据类型
字节流
字节输入流 读取数据 InputStream
字节输出流 写出数据 OutputStream
字符流
字符输入流 读取数据 Reader
字符输出流 写出数据 Writer
2.2利用字符流复制文本文件
利用字符流将当前工程下的IODemo.java拷贝到d盘的a文件夹下
2.2.1案例代码八:

package com.itheima_02;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/*
 * 使用字符流复制文本文件
 * 
 * 数据源		IODemo.java
 * 目的地		d:\\IODemo.java

 * 	
 */
public class FileCopyDemo {
	public static void main(String[] args) throws IOException  {
		//创建字符输入流对象
		FileReader fr = new FileReader("IODemo.java");
		//创建字符输出流对象
		FileWriter fw = new FileWriter("d:\\IODemo.java");
		
		//一次读写一个字符
		
		/*int ch;
		while((ch = fr.read()) != -1) {
			fw.write(ch);
			fw.flush();
		}*/
		
		//一次读写一个字符数组
		int len;//用于存储读到的字符个数
		char[] chs = new char[1024];
		while((len = fr.read(chs)) != -1) {
			fw.write(chs,0,len);
			fw.flush();
		}
		
		//释放资源
		fw.close();
		fr.close();
	}
}

2.3利用字节流复制文本文件
利用字节流将当前工程下的IODemo.java拷贝到d盘下
2.3.1案例代码九:

    package com.itheima_03;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 使用字节流复制文本文件
 * 
 * 数据源		IODemo.java
 * 目的地		d:\\a\\IODemo.java
 * 

 */
public class FileCopyDemo {
	public static void main(String[] args) throws IOException  {
		//创建字节输入流对象
		FileInputStream fis = new FileInputStream("IODemo.java");
		//创建字节输出流对象
		FileOutputStream fos = new FileOutputStream("d:\\a\\IODemo.java");
		
		//一次读写一个字节
		/*int by;
		while((by = fis.read()) != -1) {
			fos.write(by);
		}*/
		//一次读写一个字节数组
		int len;//存储读到的字节个数
		byte[] bys = new byte[1024];
		while((len = fis.read(bys)) != -1) {
			fos.write(bys,0,len);
		}
		
		
		//释放资源
		fos.close();
		fis.close();
	}
}

2.4复制图片
字节流可以操作所有类型的文件,因为所有的文件在计算机中都是以字节形式存储
而字符流只能用来操作纯文本类型的文件,不能操作字节类型的文件
2.4.1案例代码十:

package com.itheima_04;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/*
 * 分别使用字符流和字节流复制图片
 * 
 * 二进制文件只能使用字节流进行复制(使用windows自带记事本打开读不懂的)
 * 文本文件的复制即可使用字符流,也可以使用字节流
 * 
 */
public class CopyImage {
	public static void main(String[] args) throws IOException  {
		//method();
		
		//创建字节输入流对象
		FileInputStream fis = new FileInputStream("传智学院.jpg");
		//创建字节输出流对象
		FileOutputStream fos = new FileOutputStream("d:\\传智学院.jpg");
		
		//一次读写一个字节数组
		int len;//用于存储读到的字节个数
		byte[] bys = new byte[1024];
		while((len = fis.read(bys)) != -1) {
			fos.write(bys,0,len);
		}
		
		//释放资源
		fos.close();
		fis.close();
	}

	private static void method() throws FileNotFoundException, IOException {
		//创建字符输入流对象
		FileReader fr = new FileReader("传智学院.jpg");
		//创建字符输出流对象
		FileWriter fw = new FileWriter("d:\\传智学院.jpg");
		
		//一次读写一个字符数组
		int len;//用于存储读到的字符个数
		char[] chs = new char[1024];
		while((len = fr.read(chs)) != -1) {
			fw.write(chs,0,len);
			fw.flush();
		}
		
		//释放资源
		fw.close();
		fr.close();
	}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值