Java核心技术笔记
19-计科-秦皓东
目录
第一章 Java概述
1:JDK,Java Development Kit(Java开发工具包)
2:编译javac.exe,从Java文件(源文件)到class文件(字节码文件)
运行Java.exe,执行class文件
3:Java SE:面向PC级应用开发
JavaEE:面向企业级应用开发
JavaME:面向嵌入式应用开发
第二章 Java环境搭建和程序初体验
1:Java从编写到运行
-
编写:利用开发工具完成代码文件(.java)的编写
-
编译:利用JDK中的javac.exe将代码(.java)编译成字节码文件(.class)
-
运行:java.exe读入并解释字节码文件(.class),最终在JVM上运行
2: JDK、JRE(Java Runtime Environment Java运行时环境)、 JVM (Java Virtual Machine Java虚拟机)三者的关系
-
JDK包含JRE,JRE包含JVM(不同OS的JVM不同,因此不同OS下的JDK也不同)
3:JDK有32位与64位之分
4:作业:
第三章 Java类基础知识
1:Java文件必须以.java作为扩展名,且一个Java文件只能有一个public.class文
2:类的构成:
-
成员变量/属性
-
成员方法/函数
3:public static void main(String[] args)
-
其中String[] args是main函数的形参,可以在main函数中可以使用args的值
-
右键ArgumentTest.java,选择Run As->Run Configuration
4:基本数据类型
-
boolean布尔 默认初始值位false
-
byte字节 1byte=8bits(位)/ 默认初始值为0 /[-128,127]
-
short/int/long 短整数/整数/长整数 2字节(16位)/4字节(32位)/8字节(64位) 默认初始值:0/0/0L
-
float/double 浮点数 4字节(32位)/8字节(64位)
-
char 字符类型 2字节(16位)
5:运算符
-
+,-,*,/,%
-
逻辑运算符 &&,||,!
-
位移运算符>>,<<等
-
比较运算符!=,>,<,>=,<=,==
6:&与&&的区别:
-
按位与&:a&b是把a和b都转换成二进制数然后再进行与的运算
-
按位与:例:0&0=0;0&1=0;9&8>>1001&1000=1000
-
按位与&作为逻辑运算符时,&左右两端都会运行,只要有一端为假就会不成立
-
逻辑与&&:&&也叫短路运算符,只要左端条件式为假就直接不成立,不会去判断右端条件式
7:|与||的区别:
-
与上类似,||当第一个为true时就不需执行后面的条件式,|两端都要执行
8:位移运算符>>,<<
-
左移(<<):需要移动的数字<<位移的次数
-
例:10<<2:10的二进制为1010,向左移两位变为101000即为十进制的40
-
结论:左移n位数相当于乘以2的n次方
-
右移(>>):需要移动的数字>>位移的次数
-
结论:右移n位数相当于除以2的n次方
9:选择结构:
-
if
-
if else
-
if ...else if....else
10:多重选择结构:
-
switch(表达式)
11:循环结构结构
-
while
-
do...while
-
for
-
break //中断循环并退出
-
continue //跳出本次循环,继续下次循环
12:自定义函数
-
修饰词 返回值(void) 函数名(形参列表) { 函数体 }
-
方法的重载:同一个类中,函数名称可以相同,即为重载,但是形参列表必须不同,返回值可以相同也可以不相同
-
方法的重写:1.发生在子类与父类之间,方法名,形参列表,返回类型(其中子类的返回类型可以为父类的子类)必须相同 2.子类权限修饰符的限制要大于父类的权限修饰符的限制 3.子类异常范围必须比父类声明的异常范围小
13:权限修饰符的范围比较(从小到大排)
权限修饰符 | 类内部 | 同一个包下 | 不同包的子类 | 同一个工程 |
---|---|---|---|---|
private | YES | |||
(缺醒) | YES | YES | ||
protected | YES | YES | YES | |
public | YES | YES | YES | YES |
(1)四种权限修饰符都可用来修饰类的内部结构:方法、属性、构造器、内部类
(2)类的修饰只能用:public、缺醒
14:作业
(1):请实现程序输出以下5*5数字方格。
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
需要在main函数的输入参数中设置5,输出55的数字方格。如果是输入7,则是77的数字方格。需要提交代码、(Eclipse)设置参数截图、(Eclipse)运行结果截图。
import java.util.Scanner;
public class QJHF {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入n:");
int n = in.nextInt();
int[] jz = new int[n * n];
for (int i = 1; i < n * n + 1; i++) {
jz[i - 1] = i;
}
for (int i = 0; i < n * n; i++) {
if (i % n == 0 && i >= n)
System.out.println();
System.out.print(jz[i] + " ");
}
}
}
(2):请实现程序输出以下星塔。
*
***
*****
***
*
需要在main函数的输入参数中设置5,输出5层星塔。如果是输入7,则是7层星塔。假设输入参数都是奇数,且都大于等于5,小于等于11。需要提交代码、(Eclipse)设置参数截图、(Eclipse)运行结果截图。
import java.util.Scanner;
public class HelloWorld {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.println("请输入整数n:");
int n=in.nextInt();
int t=(n+1)/2;
//上半部分
for (int i = 0; i <t; i++) {
for (int j = t-1-i; j >0 ; j--) {
System.out.print(" ");
}
for (int j = 0; j < 2*i+1; j++) {
System.out.print("*");
}
System.out.println();
}
//下半部分
int t1=(n-1)/2;
for (int i = 0; i <t1; i++) {
for (int j = 0; j <i+1; j++) {
System.out.print(" ");
}
for (int j = 0; j <2*(t1-i)-1; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
第四章 面向对象和类
1:构造函数(构造器)
-
每个Java类都必须有构造函数,且构造器名称与类名称相同,且没有返回值
-
如果没有自定义构造函数,则编译器自动为该类产生一个空参构造器,若已经自定义了构造器,编译器就不会自动生成空参构造器
-
每个子类的构造函数第一句话都是默认调用父类的空参构造器super(),除非子类第一句为super(父类属性),则调用父类的改属性的含参构造器
-
一个类可以有多个构造器,形参列表不同即可,形参列表内的参数若与该类的属性同名,则用this.属性=属性
在构造器首行调用this关键字,调用本类中的构造器
2:内存解析
-
新创建的对象储存在堆空间中,每创建一个新的对象在堆空间中就新开辟一个空间储存
-
因此没有两个对象是完全一样的
-
对象是引用数据类型
3:信息隐藏(封装)
-
类的成员属性是私有的privat
-
类的方法是公共的public通过get set方法对类中私有的成员属性进行操作
4:作业
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//利用hasNextXXX()判断是否还有下一输入项
int a = 0;
int b = 0;
int c = 0;
if (sc.hasNext()) {
a = sc.nextInt();
}
if (sc.hasNext()) {
b = sc.nextInt();
}
if (sc.hasNext()) {
c = sc.nextInt();
}
if (a == 0 || b == 0 || c == 0) {
System.out.println("输入不能为0");
System.exit(-1);
}
MyNumber obj1, obj2, obj3;
//从这里开始,基于swap函数,完善你的程序
obj1 = new MyNumber();
obj2 = new MyNumber();
obj3 = new MyNumber();
obj1.num = a;
obj2.num = b;
obj3.num = c;
//
if (obj1.num > obj2.num)
swap(obj1, obj2);
//
if (obj1.num > obj3.num)
swap(obj1, obj3);
//
if (obj2.num > obj3.num)
swap(obj2, obj3);
//程序结束
System.out.println("从小到大排序后:" + obj1.num + " " + obj2.num + " " + obj3.num);
}
public static void swap(MyNumber m, MyNumber n) {
if (m.num > n.num) {
int s = m.num;
m.num = n.num;
n.num = s;
}
}
}
class MyNumber {
int num;
}
5:章节测试错题
第五章 继承、接口和抽象类
1:继承
-
单根继承原则,每个类都只有一个直接父类,但可以有多个间接父类
-
Java所有类都是单根继承
-
如果不写extends,Java类都默认继承与Java.lang.Object类
-
Object类中默认就有equals,finalize,getClass方法,hashcode,toString方法
-
基本格式 class 子类 extends 父类
2:继承类中的构造器以及方法的重写前面总结过
3:抽象类
-
抽象类关键字(abstract),用abstrac修饰的方法叫做抽象方法
-
含有抽象方法的类一定是抽象类,抽象类不一定含有抽象方法
-
例:public abstract void talk()
-
抽象类不能被实例化,抽象类是用来继承的否则就失去了意义,因此不能用abstract修饰私有方法、final方法、静态方法、final类
-
继承抽象类的类必须重写抽象类中的所有的抽象方法
-
抽象类中有构造器,反之继承的每个类首先都会调用空参构造器,如果不能则矛盾
4:接口
-
接口(interface)是抽象方法和常量值定义的集合
-
接口中的成员变量默认都是public static final修饰的
-
接口中的方法默认都是public abstract修饰的
-
接口中没有构造器
-
接口采用多继承机制
-
例:public interface Runner{public static final int age=21; public abstract void run();}
-
一个类可以实现多个接口,中间使用“,”间隔,当类继承与接口实现同时存在时先extends后implements
-
抽象类中可以定义private的属性和方法(对应抽象类中不一定含有抽象方法),接口中所有的方法属性只能是public
5:类转型
-
子类可以转换成父类,父类不可以转换成子类
-
父类转为子类有一种特殊情况,就是这个父类本身就从子类转换而来
-
例:Human obj1=new Man(); Man obj2=(Man) obj1;
-
父类强转为子类时,编译通过,在运行时才会抛出异常
6:多态
-
类型转换带来的作用就是多态
-
对象的多态性:父类的引用指向子类的对象
-
前提:需要存在继承或者实现关系
-
作用:提高了代码的通用性,常称作接口的重用
-
使用多态时不能调用子类特有的方法
-
多态不适用于属性
-
父类中的属性只属于父类,字符类中的属性同名也互不影响,是两个类中各自所拥有的属性
7:锲约设计
-
类不会直接使用另外一个类,而是采用接口的形式,外部可以“空投”这个接口下的任意子类对象
8:章节测试错题
-
解析:Cb构造器中会调用Ca中的空参构造器,而Ca中没有声明空参构造器,因此会编译报错
解析:使用多态时的对象无法调用子类中的特有的方法
解析:子类执行构造器时,会先执行父类的空参构造器
解析:编译能通过,运行时会抛出异常,父类不能强制转为子类,除非使用多态
第六章static、final和常量设计
1:static
-
可作用于变量、方法、类、匿名方法块
-
在静态方法中只能使用静态变量,不能使用非静态变量
-
静态方法中不能调用非静态方法
-
static变量不管有多少个对象,内存中只有一份
-
static只执行一次,且static>匿名块>构造函数
2:final
-
可以用来修饰类、方法、字段
-
final修饰的类不能被继承
-
如果父类中的有final修饰的方法,子类中不能改写此方法
-
final修饰的变量不能再次赋值
3:单例模式
-
单例设计模式:采取一定的方法,保证啊整个的软件系统中,对某个类只能存在一个对象的实例
-
饿汉式
//形象记忆:饿了就要立马吃饭,因此创建实例时要一步到位
class Singleton{
//1.私有化构造器
private Singleton(){}
//2.内部提供一个当前类的实例,且此实例也必须静态化
private static Singleton single=new Singleton();
//3.提供公共的静态的方法,返回当前值类的对象
public static Singleton getInstance(){
return single;
}
}
-
饿汉式(涉及线程安全问题)
class Singleton{
//1.私有化构造器
private Singleton(){}
//2.内部提供一个当前类的实例并赋值为null,且此实例也必须静态化
private static Singleton single=null;
//3.提供公共的静态的方法,返回当前值类的对象
public static Singleton getInstance(){
if (single==null){
synchronized (Singleton.class){
if (single==null){
single=new Singleton();
}
}
}
return single;
}
}
4:常量
-
一种(static)不会修改(final)的变量
-
常量(public static final)
-
常量的变量名通常大写,如ID_STUDENT
-
接口中定义的变量默认是常量
5:常量池
-
包装类、字符串(String)都建立在常量池
-
常量池中相同的值只存储一份,节省内存,共享访问
-
基本类型的包装类:Integer、Long、Double、Short、Byte、Boolean、Float、Character(char)
-
Float和Double没有常量池
-
凡是通过new对象创建的都放在堆内存中
6:不可变对象
-
一旦创建,此对象就不能被更改了,其内在成员变量的值也不能被更改
-
典型的不可变对象:八个基本类型的包装类、String、BigInteger和BigDecimal等的对象
-
优点:只读,线程安全、并发读,提高性能、可以重复使用
-
缺点:制造垃圾,浪费空间
7:Java 字符串
-
两种定义方式:1. String a="abc"; (堆内存) 2.String a=new String ("abc");(栈内存)
-
字符串内容的比较eauals()方法
-
String中重写了eqauls()方法,如果不重写equals()方法,其用法与==相同,基本数据类型比较内容,引用数据类型比较地址值
-
使用IDEA快捷键重写equals方法与hashcode方法(涉及到集合框架内容,后面再总结)
-
字符串的加法:直接使用+
-
StringBuilder(不同步,效率高,线程不安全)与StringBuffer类(同不,效率差,线程安全)
-
StringBuilder和StringBuffer可以直接对字符串将进行修改(append方法)
8:章节测试错题
-
解析:String类型为引用数据类型,默认初始值为null
解析:匿名内部类的方法,抽象类虽然不能实例化,但是可以声明对象,再通过匿名内部类的方法使这个匿名内部类继承于这个声明对象的类通过{}重写其中的方法
解析:子类与父类中属性名称相同也不会相互影响,归属于两个类所各自拥有,Java中属性不具备多态性
第七章 package、import、classpath
1:package和impot
-
Java通过包(package)来分开类
-
package必须和目录层次一样
-
Java通过引用(import)来导入类
-
import类尽量标准
-
包名和类所在的目录必须严格一致
-
在命令行中,必须依靠classpath来指引所需要的类
-
编译需要文件的全路径,运行需要类的完整名字
2:jar
-
Java特有的一种文件格式,jar文件实际上是一组class文件的压缩包
-
jar文件可以包括多个class,jar经过压缩后只有一个文件
-
jar文件只有class文件,没有源文件(Java),在保护知识版权方面,起到更好的作用
3:Java访问权限
-
该问题在第三章13点总结过
4:作业
第八章 Java常用类
1:数字类
-
整数 Short、Int、Long
-
浮点数 Float、Double
-
大数类 BigInteger、BigDecimal
-
随机数类 Random
-
工具类 Math
2:浮点数的注意事项
-
float a=1.23(erro) float a=1.23f;
-
浮点数不加f是默认为double类型的,double类型的浮点数可以省略掉数字末的d
3:大数字类
-
BigInteger(大整数类),BigDecimal(大浮点是)
-
例:BigInteger i1=new BigInteger("556789876545678"); BigInteger i2=new BigInteger("98989898765432345");
-
两者做乘法运算 i1.multiply(i2);
4:随机数
-
Random()
-
nextInt(),返回一个随机数int
-
nextInt(int a),返回一个[0,a),之间的随即int,注意左闭右开
-
nextDouble,返回一个[0.0,1.0]之间的double
-
Math.Random,随机返回一个[0.0,1.0]之间的double
5:数字工具类
-
绝对值函数abs
-
对数函数log
-
比较函数max、min
-
幂函数pow
-
四舍五入函数round
-
向上向下取整:ceil、floor
-
统一调用方法:Math.方法(参数)
6:字符串
-
该类在之前章节总结过
7:时间类
-
当前多数程序依旧使用的Calendar类处理时间,注意Calendar类是抽象类
-
Java8的时间新特征应用
-
java.util.Date(基本废弃)
-
java.sql.Date(和数据库对应的时间类)
8:Calendar类
-
get(Field) 获取时间的每个属性值。注意:月份为0-11,使用此方法获取到的月份值要+1
-
getTime() 返回相应的Date对象
-
getTimeInMillis 返回1970.1.1以来的毫秒数
-
set(Filed) 设置时间字段
-
add(field,amount) 根据指定字段增加/减少时间(amount设置为负数即可)
-
roll(field,amount) 根据指定字段增加/减少时间,但不影响上一级的时间(若改变的月份导致年份发生了改变,则只改变月份不会改变年份)
-
import java.util.Calendar; import java.util.GregorianCalendar; public class CalendarClassTest { public static void main(String[] args) { Calendar gc=Calendar.getInstance(); System.out.println(gc.getClass().getName()); GregorianCalendar gc2=new GregorianCalendar(); System.out.println(gc2.getClass().getName()); //该结果显示Calendar.getInstance();返回的是GregorianCalendar对象,对应上面所说的Calendar是抽象类不能有实例化的对象,只能调用.getInstance()方法 //获取年 int year=gc.get(Calendar.YEAR); //获取月 int month=gc.get(Calendar.MONTH)+1;//注意+1 System.out.println("year="+year+","+"month="+month); //增加一年 gc.add(Calendar.YEAR,1); //求某月的最后一天:先求下一个月的第一天再减一 gc.set(gc.get(Calendar.YEAR),9,1);//今年的9.1 gc.add(Calendar.DATE,-1); //获取日 int day=gc.get(Calendar.DAY_OF_MONTH); System.out.println("8月最后一天为"+day+"号");//八月的最后一天为30号 gc.set(2021,12,8); gc.roll(Calendar.DAY_OF_MONTH,-8); int year=gc.get(Calendar.YEAR); int month=gc.get(Calendar.MONTH); System.out.println("roll----year="+year+","+month); //得到的结果:2021,0 gc.set(2021,12,8); gc.add(Calendar.DAY_OF_MONTH,-8); int year1=gc.get(Calendar.YEAR); int month1=gc.get(Calendar.MONTH); System.out.println("add----year="+year1+","+month1); //得到的结果:2021,11 } }
9:Java8推出的新的时间API
-
LocalDate:日期
-
LocalTime:时间类(时分秒-纳秒)
-
LocalDateTime:LocalDate + LocalTime
-
Instant:时间戳
-
import java.time.LocalDate; import java.time.LocalTime; import java.time.LocalDateTime; import java.time.Month; import java.time.ZoneId; public class LocalTest { public static void main(String[] args) { //当前时间 LocalDate today = LocalDate.now(); System.out.println(today); //根据指定时间创建LocalDate LocalDate firstDay_2021 = LocalDate.of(2021, Month.JANUARY, 1); System.out.println(firstDay_2021); // 2021-01-01 //2021年的第100天 LocalDate day = LocalDate.ofYearDay(2021, 100); System.out.println(day); //2021-0410 //更改时区 LocalDate area = LocalDate.now(ZoneId.of("Asia/Shanghai")); System.out.println(area); //从纪元日1970.1.1,开始365天 LocalDate year = LocalDate.ofEpochDay(365); System.out.println(year); //1971-01-01 //判断是否时闰年 LocalDate leap=LocalDate.now(); System.out.println(leap.getYear()+"is Leap Year:"+leap.isLeapYear()); ----------------------------------------------------------------------------------------------------- //获取当前时间 LocalTime time = LocalTime.now(); System.out.println(time); //根据时分秒 LocalTime time1 = LocalTime.of(12, 20, 25, 90); System.out.println(time1); //一天当中的第几秒 LocalTime time3 = LocalTime.ofSecondOfDay(70000); System.out.println(time3); //上海时间 LocalTime time4 = LocalTime.now(ZoneId.of("Asia/Shanghai")); System.out.println(time4); ----------------------------------------------------------------------------------------------------- //当前日期时间 LocalDateTime today1= LocalDateTime.now(); System.out.println(today1); //根据时间日期 LocalDateTime today2=LocalDateTime.of(LocalDate.now(), LocalTime.now()); System.out.println(today2); //根据具体时间 LocalDateTime today3=LocalDateTime.of(2021, Month.JANUARY,12,18,54,23, 940000000); System.out.println(today3); //上海时区 LocalDateTime today4=LocalDateTime.now(ZoneId.of("Asia/Shanghai")); System.out.println(today4); //从19701.1 10000秒 LocalDateTime today5=LocalDateTime.ofEpochSecond(10000,0,ZoneOffset.UTC); System.out.println(today5); ----------------------------------------------------------------------------------------------------- //当前时间戳 Instant t1=Instant.now(); System.out.println(t1); //从毫秒数来创建时间戳 Instant t2=Instant.ofEpochMilli(t1.toEpochMilli()); System.out.println(t2); } }
10:格式化类
-
NumberFormat:数字格式化,抽象类 DecimalFormat 工厂模式
-
MessageFormat:字符串格式化
-
DateFormate:时间格式化,抽象类 SimpleDateFormat 工厂模式(线程不安全)
-
parse:将字符串格式化为时间对象
-
format:将时间对象转为字符串 例如:YYYY-MM-DD HH:MI-SS 输出
-
java.time.format.DateFormatter:时间格式化 (线程安全)
-
ofPattern:设定时间格式
-
parse:将字符串格式化为时间对象
-
format:将时间对象转为字符串 例如:YYYY-MM-DD HH:MI-SS 输出
-
DecimalFormat df1,df2; //整数部分为0时,#认为整数不存在,0认为为0 df1 = new DecimalFormat("#.00"); df2 = new DecimalFormat("0.00"); System.out.println(df1.format(0.1)); // .10 System.out.println(df2.format(0.1)); // 0.10 //小数部分,#代表最多几位,0代表必须有这几位 df1 = new DecimalFormat("0.00"); df2 = new DecimalFormat("0.##"); System.out.println(df1.format(0.1)); // 0.10 System.out.println(df2.format(0.1)); // 0.1 //对整数部分处理都一样,有几位就写几位 df1 = new DecimalFormat("0.00"); df2 = new DecimalFormat("#.00"); System.out.println(df1.format(2)); // 2.00 System.out.println(df2.format(2)); // 2.00 System.out.println(df1.format(20)); // 20.00 System.out.println(df2.format(20)); // 20.00 ----------------------------------------------------------------------------------------------------- double f = 111231.5585; BigDecimal b = new BigDecimal(f); double f1 = b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue(); System.out.println(f1); //111231.56 DecimalFormat df =new DecimalFormat("#.00"); String f2 = df.format(f); System.out.println(f2); //111231.56 String f3 = String.format("%.2f",f); System.out.println(f3); //111231.56 NumberFormat ddf1=NumberFormat.getInstance() ; System.out.println(ddf1.getClass().getName()); ddf1.setMaximumFractionDigits(2); String f4= ddf1.format(f) ; System.out.println(f4); //111,231.56 ----------------------------------------------------------------------------------------------------- String message = "{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}{16}"; Object[] array = new Object[]{"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q"}; String value = MessageFormat.format(message, array); System.out.println(value);//ABCDEFGHIJKLMNOPQ message = "oh, {0,number,#.##} is a good number"; array = new Object[]{new Double(3.1415)}; value = MessageFormat.format(message, array); System.out.println(value);//oh, 3.14 is a good number ----------------------------------------------------------------------------------------------------- //将字符串转换为时间 String dateStr = "2016年10月25日"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日"); LocalDate date = LocalDate.parse(dateStr, formatter); System.out.println(date.getYear() + "-" + date.getMonthValue() + "-" + date.getDayOfMonth()); //2016-10-25 //将日期转换为字符串 LocalDateTime now = LocalDateTime.now(); DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy年MM月dd日 hh:mm:ss"); String nowStr = now.format(format); System.out.println(nowStr); //2021年05月19日 08:00:02
11:作业
-
题目内容:
-
输入一个字符串,请判断是否满足身份证基本要求,并返回具体的生日yyyy-mm-dd。如果输入数据有误,请输出0000-00-00。基本要求是:a)必须是18位;b) 前面位数必须是数字,最后一位可以是数字或小写字母;c) 日期是存在的。
import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Scanner; public class A { public static void main(String[] args) { Scanner in = new Scanner(System.in); String str = in.next(); if (str.length() != 18) System.out.println("0000-00-00"); String str1 = str.substring(6, 14); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); LocalDate date = LocalDate.parse(str1, formatter); DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String st2=date.format(formatter1); System.out.println(st2); } } //输入500112200012136712 输出2000-12-13
第九章 Java异常类和异常处理
1:异常分类
-
Throwable:所有错误的祖先
-
Error:系统内部错误或者资源耗尽
-
Exception:程序有关的异常
-
RuntimeException:运行时一号仓,编译时不会报错
2:异常处理
-
try-catch-finally
-
try必须有,catch和finally至少要有一个
-
当try发生异常时,将执行catch代码。若无则绕开
-
finally:try或catch执行结束后,必须执行finally,finally一定会被执行
-
当方法存在可能异常的语句,但不处理时,可以使用thows来声明异常
-
一个方法被覆盖时,覆盖他的方法必须抛出相同的异常,或者异常的子类
-
如果父类的方法抛出异常,重写的子类的方法也必须抛出那些异常的子集,也就是不能抛出新的异常
-
public class TryDemo { public static void main(String[] args) { try { int a = 5/2; //无异常 System.out.println("a is " + a); } catch(Exception ex) { ex.printStackTrace(); } finally { System.out.println("Phrase 1 is over"); } try { int a = 5/0; //ArithmeticException System.out.println("a is " + a); } catch(Exception ex) { ex.printStackTrace(); } finally { System.out.println("Phrase 2 is over"); } try { int a = 5/0; //ArithmeticException System.out.println("a is " + a); } catch(Exception ex) { ex.printStackTrace(); int a = 5/0; //ArithmeticException } finally { System.out.println("Phrase 3 is over"); } } } ----------------------------------------------------------------------------------------------------- public class ThrowsDemo { public static void main(String [] args) { try { int result = new Test().divide( 3, 1 ); System.out.println("the 1st result is" + result ); } catch(ArithmeticException ex) { ex.printStackTrace(); } int result = new Test().divide( 3, 0 ); System.out.println("the 2nd result is" + result ); } } class Test { //ArithmeticException is a RuntimeException, not checked exception public int divide(int x, int y) throws ArithmeticException { int result = x/y; return x/y; } } ----------------------------------------------------------------------------------------------------- public class Father { public void f1() throws ArithmeticException { } } public class Son extends Father { public void f1() throws IOException { //子类重写方法, //所抛出的异常不能超出父类规定的范围 } }
3:自定义异常
-
Exception类是所有异常的父类
-
Exception继承自Java.lang.Throwable
-
自定义异常需要继承Exception类或其子类
-
自定义重点在构造函数,调用父类的Exception的message构造函数
-
在程序中采取throw主动抛出异常
-
public class MyException extends Exception { private String returnCode ; //异常对应的返回码 private String returnMsg; //异常对应的描述信息 public MyException() { super(); } public MyException(String returnMsg) { super(returnMsg); this.returnMsg = returnMsg; } public MyException(String returnCode, String returnMsg) { super(); this.returnCode = returnCode; this.returnMsg = returnMsg; } public String getReturnCode() { return returnCode; } public String getreturnMsg() { return returnMsg; } }
4:throws和throw的区别
-
throw:异常的生成阶段:手动抛出异常对象
-
throws:异常的处理方式:声明方法可能要抛出的各种异常类
5:作业
第十章 Java数据结构
1:数组
-
数组的定义和初始化:静态初始化、动态初始化
-
静态:int []arr=new int[]{1,2,3}; / int[] arr={1,2,3};
-
动态:int []arr=new int[3];
-
内存解析:arr存储在栈中存储一个指向地址,该地址指向堆空间的数组
-
数组的遍历:普通for循环遍历,foreach遍历
-
多维数组:数组的数组,存储是按照行存储原则
2:JCF(Java Collection FrameWork)Java集合框架
-
JCF的集合接口是Collection
-
JCF的迭代器接口Iterator(hasNext、next、remove)
-
JCF:列表(List、ArrayList、LinkedList) 集合(Set、HashSet、LinkedHashSet) 映射(Map、HashMap、TreeMap、LinkedHashMap)
-
JCF主要算法类:Arrays:对数组进行查找和排序等操作 Collections:对Collection及其子类进行排序和查找操作
3:List接口
-
有序的Collection,允许重复元素
-
主要实现:ArrayList、LinkedList、Vector4
-
ArrayList源码分析:ArrayList list=new ArrayList();
-
JDK7:底层创建长度为10的数组,扩容是为原来的1.5倍(类似于单例模式中的饿汉式) JDK8:初始并未创建数组,在第一次调用add方法时创建,扩容与JDK7一致(类似于懒汉式)
-
LinkedList:底层采用双向链表结构方便插、删操作
-
vector:底层创建了长度为10的数组,扩容时为原来的两倍
4:Set接口
-
无序,不可重复
-
HashSet、LinedList、TreeSet
-
如何理解无序性?
-
以HashSet说明:存储数据在底层数组中并非按照数组索引添加而是根据哈希值
-
如何理解不可重复性?
-
保证添加的元素按照equals方法判断的,不能返回true,即:相同的元素只能添加一个
-
添加元素的过程?
-
以HashSet为例:向HashSet中添加元素A,首先调用A所在类的hashcode(),计算A的哈希值,哈希值通过某种算法算出在HashSet数组中的存放位置。若此位置元素无其他元素,则添加成功。若该位置已经存在其他元素,则比较两者的hash值,若两者的hash值不同,则添加成功,若hash值相同,调用equals方法,true则失败,false则成功
-
JDK7中:添加元素存入数据指向原有元素
-
JKD8:原有元素指向新添加元素
-
要求?
-
向set中添加的数据,其所在的类一定要重写equals和hashcode,且两方法尽可能保持一致性,相等的对象且具有相等的散列码
-
LinkedHashSet:作为HashSet的子类,再添加数据时还维护了两个引用,记录前一个数据和后一个数据,双向链表结构,对于频繁遍历LinkedList效率高于HashSet
-
TreeSet:红黑树,向TreeSet中添加的数据,要求是相同的对象
-
两种排序方式:自然排序(Comparable接口)、定制排序(Comparator接口)
5:Map接口
-
HashMap、LinkedHashMap、TreeMap、HashTable、Properties
-
HashMap:Map的主要实现类,线程不安全,效率高,可以存储null的key和value
-
LinkedHashMap:双向链表、便于遍历
-
TreeMap:按添加顺序实现遍历,考虑自然、定制排序,底层使用红黑树
-
HashTable:作为古老的实现类,线程安全,效率低,不能存储null
-
Properties:HashTable的子类,常用来处理配置文件,key-value都为String类型
-
HashMap的底层原理?
-
结构:key-value中key相当于Set接口(无序且不可重复),value相当于Collection接口(可重复,无序),key-value这一整体看作Set(无序且不可重复)
-
HashMap底层:HashMap map=new HashMap();
-
JDK7:实例化后底层创建了长度为16的一维数组,扩容时为原来的2倍,并将原有数据复制,当数组长度为12时就开始扩容
-
JDK8:初始并未创建长度为16的数组,当首次调用put方法时创建长度为16的数组
-
JDK7底层结构为:数组+链表 JDK8底层结构为:数组+链表+红黑树
-
当数组某一索引位置上的元素以链表形式存在的数据个数大于8时,且当前数组的长度大于64时,此时索引位置上的所有数据改为红黑树存储
-
map.put(key1,value1);
-
添加过程:
-
首先调用key1所在类的hashcode计算哈希值,经过算法得到数组中存放的位置,此位置为空,则添加成功,此位置不为空,则比较key1与当前数据的哈希值,若不同,则添加成功,若相同,则调用key1所在类的equals方法比较,若为false则添加成功,若为true则使用value1替换掉原有value
6:Collection接口中的常用方法
-
add(Object e):增加元素到集合中
-
size():获取添加的元素个数
-
addAll(Collection c):将c集合元素添加到当前集合
-
isEmpty():判断当前集合是否为空
-
clear():清空集合元素
-
contains(Object obj):当前集合是否包含obj,调用的是obj所在类的equals方法
-
remove(Object obj):返回值为boolean,表示是否删除成功
-
retainAll(Collection c):获取当前集合与c的交集
-
equals、hashcode
-
toArray():将集合转为数组 将数组转为集合:Arrays.asList();
-
iterator:返回Iterator接口的实例,用于集合的遍历
7:List的常用方法
-
add(int index,Object obj):在index位置插入obj
-
addAll(int index,Collection ele):从index开始添加eld所有元素
-
get(int index):获取指定位置的元素
-
indexof(Object obj):返回obj在集合首次出现的位置
-
lastIndexof(Object obj):返回obj在集合最后出现的位置
-
remove(int index):删除指定位置的元素,并返回此值 该方法与Collection中的删除方法有所不同
-
set(int index,Object obj):设置指定位置元素为obj
-
subList(int index1,int index2):返回index1到index2的子集合
8:Set接口无新定义方法,都为Collection中的方法
9:Map的常用方法
-
put(Object key,Object value):将指定的key-value添加(修改)到当前map对象
-
putAll(Map m):将m中的所有键值对存到当前map中
-
remove(Object key):移除指定key的键值对,并返回value 三个接口中的该方法各有差异
-
get(Object key):获取指定key多对应的value
-
containsKey(Object key):是否包含指定的key
-
cotainsValue(Object obj):是否包含指定的value
-
size():返回键值对的对数
-
Set keySet():返回所有的key构成的Set集合
-
Collection values():返回左右value构成的Collection集合
-
Set entrySet():返回所有键值对构成的Set集合
10:集合元素的遍历
-
使用Iteraor接口,迭代器
-
List list=new ArrayList; Iteraor i=list.iterator();//返回Iterator接口实例 while(i.hasNext()){ sout(i.next()); }
-
foreach遍历:实际内部依然调用了迭代器,不会改变原有元素
-
for(Object obj:list) sout(obj);
11:工具类
-
操作Collection和Map的工具类
-
Collection和Collections的区别?
-
Collection是创建集合的接口,Collections是操作Collection和Map的工具类
-
reverse(List):反转List中的元素的顺序
-
shuffle(List):对List集合元素进行随机排序
-
sort(List):根据元素的自然排序对List集合元素按升序排序
-
sort(List,Comparator):根据指定的Comparator顺序对List排序
-
swap(List,int,int):将指定的List集合中两位置元素替换
-
Collections类中提供了多个synchronized方法,可将指定集合包装成线程同步的集合,解决线程安全问题
-
例如:List l=Collections.synchronizedList(list);返回的 l 即为线程安全的List
12:作业
-
题目内容:
在国际机场,我们会发现有多个货币兑换的窗口,这是由于各国货币的单位价值是不一样的。下面列出了某日国际货币的汇率表(相对于100人民币的各国货币值)。
货币 CNY HKD USD EUR 汇率 100 118 15 13 例如,100元人民币可以兑换118香港币。请利用继承机制与Comparable接口实现不同数目货币对象价值的排序。下面给出了程序的基本框架,请给出相关的函数实现。(假设所有的输入数值和比较都是用整数)
import java.util.Arrays; import java.util.Scanner; class Currency { private String name; //货币名称 private int originalValue; //原始值 private int value; //转换为人民币后的值 public static String[] CURRENCY_NAME = { "CNY", "HKD", "USD", "EUR" }; public static int[] CURRENCY_RATIO = { 100, 118, 15, 13 }; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getOriginalValue() { return originalValue; } public void setOriginalValue(int originalValue) { this.originalValue = originalValue; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } } class HKD extends Currency implements Comparable<Currency> { double a; @Override public int compareTo(Currency e) { if (e.getValue()>a) return 1; if (e.getValue()<a) return -1; else return 0; } HKD(int a){ this.a=a*1.18; this.setValue((int)this.a); this.setName("HKD"); this.setOriginalValue(a); } } // 实现你的构造函数与Comparable中的接口 class USD extends Currency implements Comparable<Currency> { double a; @Override public int compareTo(Currency e) { if (e.getValue()>a) return 1; if (e.getValue()<a) return -1; else return 0; } USD(int a){ this.a=a*0.15; this.setValue((int)this.a); this.setName("USD"); this.setOriginalValue(a); } // 实现你的构造函数与Comparable中的接口 } class EUR extends Currency implements Comparable<Currency> { double a; @Override public int compareTo(Currency e) { if (e.getValue()>a) return 1; if (e.getValue()<a) return -1; else return 0; } EUR(int a){ this.a=a*0.13; this.setValue((int)this.a); this.setName("EUR"); this.setOriginalValue(a); } } public class Main { public static void main(String[] args) { Currency[] cs = new Currency[3]; //初始化 Scanner sc = new Scanner(System.in); //利用hasNextXXX()判断是否还有下一输入项 int a = 0; int b = 0; int c = 0; if (sc.hasNext()) { a = sc.nextInt(); cs[0] = new HKD(a); } if (sc.hasNext()) { b = sc.nextInt(); cs[1] = new USD(b); } if (sc.hasNext()) { c = sc.nextInt(); cs[2] = new EUR(c); } //初始化结束 //请补充排序 Arrays.sort(cs); for (Currency obj:cs ) { System.out.println(obj.getName()+" "+obj.getOriginalValue()); } } } //输入:100 100 100 //输出:HKD 100 // USD 100 // EUR 100
第十一章 Java文件读写
1:Java IO 包
-
文件系统和Java是两套系统
-
Java读写文件,只能以数据流的形式进行读写
-
Java.io包中分为节点类和包装类(转化类、装饰类)
-
节点类:直接操作文件类
-
转换类:字符到字节之间的转化
-
装饰类:装饰节点类
2:File类的使用
-
java.io.File:文件和文件目录路径的抽象表示形式,与平台无关
-
想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录
-
常用构造器
-
pubic File(String pathname):以pathname为路径创建File对象,可以是绝对路径(是一个固定的路径,从盘符开始)也可以是相对路径(十点过对于某个位置的开始),如果pathname是相对路径,则默认的当前路径在系统属性user.dir中
-
public File(String parent ,String child):以parent为父路径,child为子路径创建File对象
-
public File(File parent , String child):根据一个父File对象爱国和子文件路径创建File对象
-
路径分隔符
-
路径中的每级目录之间使用一个路径分隔符,路径分隔符与系统有关(Windows和DOS系统使用“\”,UNIX和URL使用“/”)
-
File类中提供了一个常量: public static final String separator
-
File file=new File("d:\\qhd\\xxx.txt"); File file1=new File("d:"+File.separator+"qhd"+File.separator+"xxx.txt")
-
File类的常用方法
-
public Sring getAbsolutePath():获取绝对路径
-
public String getParent():获取上层文件目录路径,若无,则返回null
-
public boolean isDirectory():判断是否是文件目录
-
public boolean isFile():判断是否是文件
-
public boolean exisits():判断是否存在
-
public boolean createNewFile():创建文件,若文件存在则不创建,返回false
-
public boolean mkdirs():创建文件目录,如果上层文件目录不存在,一并创建
-
public boolean delete():删除文件或者文件夹
-
File dir1=new File("D:/夏雪星/qhd"); if (!dir1.exists()){ dir1.mkdir(); } //创建dir1为父目录,名为“xxx”的File对象 File dir2=new File(dir1,"xxx"); if (!dir2.exists()){ dir2.mkdir();//如果不存在就创建为目录 } //创建dir2为父目录,名为"xxx.txt"的File对象 File dir3=new File(dir2,"xxx.txt"); if (!dir3.exists()) { dir3.createNewFile();
3:IO流原理及流 的分类
-
I/O是input和output的缩写,该技术用于处理设备之间的数据传输
-
Java程序中对于数据输入输出操作以“流(stream)”的方式进行
-
java.io包下提供了各种流类和接口,用以获取同种类的数据,并通过标准的方法输入或输出数据
-
input:读取外部数据(磁盘、光盘等)到程序(内存)中
-
output:将程序(内存)数据输出到磁盘、光盘等存储设备
-
流的分类
-
按操作数据单位:字节流(8bit)、字符流(16bit)
-
按数据的流向:输入流、输出流
-
按流的角色不同:节点流、处理流
-
抽象基类
-
抽象基类 字节流 字符流 输入流 InputStream Reader 输出流 OutputStream Writer
4:节点流(文件流)
-
读取文件
-
步骤: 1.创建一个流对象,将已存在的一个文件加载进流 FileReader fr=new FileReader(new File("Test.txt")); 2.创建一个临时存放数据的数组 char[] ch=new char[1024]; 3.调用流对象的读取方法将流中的数据读入到数组中 fr.read(ch); 4.关闭资源 fr.close(); ----------------------------------------------------------------------------------------------------- FileReader fr= null; try { fr = new FileReader(new File("D:\\夏雪星\\qhd\\xxx\\xxx.txt")); char[] buf=new char[1024]; int len; while((len=fr.read(buf))!=-1){ System.out.println(new String(buf,0,len)); } } catch (IOException e) { e.printStackTrace(); } finally { if (fr!=null) try { fr.close(); } catch (IOException e) { e.printStackTrace(); } }
-
写入文件
-
步骤: 1.创建流对象,建立数据存放文件 FileWriter fw=new FileWriter(new File("xxx.txt")); 2.调用流对象的写入方法,将数据写入流 fw.write("xxx是🐖"); 3.关闭流资源,并将流中的数据清空到文件中 fw.close(); ----------------------------------------------------------------------------------------------------- FileWriter fw= null; try { fw = new FileWriter(new File("D:\\夏雪星\\qhd\\xxx\\xxx.txt")); fw.write("xxx是🐖"); } catch (IOException e) { e.printStackTrace(); } finally { if (fw!=null) { try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } //Java中的三个常用快捷键:选中代码后按住Ctrl和Alt加T 快捷添加try-catch方法 // 选中代码Shift加Ctrl加上下键 将选中代码上下移动 // Ctrl加D 复制当行代码并自动粘贴到下一行
-
字节流操作字节,例如:.mp3,.avi,.mp4,.jpg,.doc,.ppt等
-
字符流操作字符,只能操作普通文本文件例如:.txt,.java,.c,.cpp等语言的源代码。尤其注意.doc,.excel,ppt这些不是文本文件
5:缓冲流
-
为了提高数据读写的速度
-
缓冲流要嵌套在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
-
BufferedInputStream 和 BufferedOutputStream
-
BufferedReader 和 BufferedWriter
-
关闭流的顺序和打开流的顺序相反,并且只需要关闭最外层的流即可,会自动关闭相对应的内层流
-
flush()方法的使用
-
flush()方法是清空,即清空缓冲区数据,也就是说在使用读写流的时候,先将数据读到缓冲区,再由缓冲区写入文件,当数据读完的时候,并不代表数据已经写完,因为有一部分有可能留在缓冲区,这时如果直接调用close()方法,那么这部分数据就会丢失,因此要在close()之前先调用flush方法,保证缓冲区的数据已经清空
-
BufferedReader br= null; BufferedWriter bw= null; try { //创建缓冲流对象:它是处理流,是对节点流的包装 br = new BufferedReader(new FileReader("D:\\夏雪星\\qhd\\xxx\\xxx.txt")); bw = new BufferedWriter(new FileWriter("D:\\夏雪星\\qhd\\xxx\\qhd.xtx")); String str; while ((str=br.readLine())!=null){//一次读取字符文本文件的一行字符 bw.write(str);//一次写入一行字符 bw.newLine();//写入行分隔符 } bw.flush();//刷新缓冲区 } catch (IOException e) { e.printStackTrace(); } finally { //关闭IO流对象 if (bw!=null) { try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } if (br!=null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } }
6:转换流
-
转换流提供了在在字节流和字符流之间的转换
-
Java API提供了两个转换流:
-
InputStreamReader:将InputStream转换为Reader
-
OutputStreamWriter:将Writer转换为OutputStream
-
字节流中的数据都是字符时,转成字符流操作更高效
-
InputStreamReader:实现将字节的输入流按指定字符集转换为字符的输入流
-
OutputStreamWriter:实现将字符的输出流按指定字符集转换为字节的输出流
-
BufferedReader br= null; BufferedWriter bw= null; try { FileInputStream fis=new FileInputStream("D:\\夏雪星\\qhd\\xxx\\xxx.txt"); FileOutputStream fos=new FileOutputStream("D:\\夏雪星\\qhd\\xxx\\qhd.txt"); InputStreamReader isr=new InputStreamReader(fis,"UTF-8"); OutputStreamWriter osw=new OutputStreamWriter(fos,"UTF-8"); br = new BufferedReader(isr); bw = new BufferedWriter(osw); String str=null; while ((str=br.readLine())!=null){ bw.write(str); bw.newLine(); bw.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { try { bw.close(); } catch (IOException e) { e.printStackTrace(); } try { br.close(); } catch (IOException e) { e.printStackTrace(); } }
7:数据流
-
为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流
-
数据流有两个类:(用于读取和写出基本数据类型、String类的数据)
-
DataInputStream、DataOutputStream
-
分别嵌套在InputStream、OutputStream子类的流上
-
DataInputStream中的方法
-
boolean readBoolean()
-
byte readByte()
-
char readChar()
-
········等等基本数据类型
-
DataOutputStream中的方法,将上诉方法中的read改为write即可
-
DataOutputStream dos= null; try { dos = new DataOutputStream(new FileOutputStream("D:\\夏雪星\\qhd\\xxx\\qhd.txt")); dos.writeBytes("xxx是猪"); dos.writeBoolean(false); dos.writeLong(12345543234567L); System.out.println("写入文件成功!"); } catch (IOException e) { e.printStackTrace(); } finally { if (dos!=null) { try { dos.close(); } catch (IOException e) { e.printStackTrace(); } } }
8:Java zip包
-
压缩包:zip、rar、gz
-
java zip包支持zip和Gzip包的压缩和解压
-
zip文件操作类:java.util.zip包
-
ZipInputStream、ZipOutputStream压缩文件输入/输出流
-
单个/多个压缩(重点在Entry和输入输出流向,算法不需要关心)
-
File file = new File("c:/temp/abc.txt") ; // File zipFile = new File("c:/temp/single2.zip") ; // InputStream input = new FileInputStream(file) ; // ZipOutputStream zipOut = null ; // zipOut = new ZipOutputStream(new FileOutputStream(zipFile)) ; zipOut.putNextEntry(new ZipEntry(file.getName())) ; // zipOut.setComment("single file zip") ; // // int temp = 0 ; while((temp=input.read())!=-1){ // zipOut.write(temp) ; // } input.close() ; // zipOut.close() ; // System.out.println("single file zip done."); } ----------------------------------------------------------------------------------------------------- File file = new File("c:/temp/multiple") ; // File zipFile = new File("c:/temp/multiple2.zip") ; // InputStream input = null ; // ZipOutputStream zipOut = null ; // zipOut = new ZipOutputStream(new FileOutputStream(zipFile)) ; zipOut.setComment("multiple file zip") ; // // int temp = 0 ; if(file.isDirectory()){ // File lists[] = file.listFiles() ; // for(int i=0;i<lists.length;i++){ input = new FileInputStream(lists[i]) ; // zipOut.putNextEntry(new ZipEntry(file.getName() +File.separator+lists[i].getName())) ; // System.out.println("" + lists[i].getName()); while((temp=input.read())!=-1){ // zipOut.write(temp) ; // } input.close() ; // } } zipOut.close() ; // System.out.println("multiple file zip done.");
-
单个多个解压
-
// File zipFile = new File("c:/temp/single.zip") ; // ZipInputStream input = null ; // input = new ZipInputStream(new FileInputStream(zipFile)) ; // ZipEntry entry = input.getNextEntry() ; // System.out.println("" + entry.getName()) ; // // File outFile = new File("c:/temp/" + entry.getName()); OutputStream out = new FileOutputStream(outFile) ; // int temp = 0 ; while((temp=input.read())!=-1){ out.write(temp) ; } input.close() ; // out.close() ; // System.out.println("unzip done.") ; ----------------------------------------------------------------------------------------------------- // File file = new File("c:/temp/multiple.zip") ; // File outFile = null ; // ZipFile zipFile = new ZipFile(file) ; // ZipInputStream zipInput = null ; // // OutputStream out = null ; // InputStream input = null ; // ZipEntry entry = null ; // zipInput = new ZipInputStream(new FileInputStream(file)) ; // // while((entry = zipInput.getNextEntry())!=null){ // System.out.println("" + entry.getName() + "") ; outFile = new File("c:/temp/" + entry.getName()) ; // if(!outFile.getParentFile().exists()){ // outFile.getParentFile().mkdirs() ; } if(!outFile.exists()){ if(entry.isDirectory()) { outFile.mkdirs(); System.out.println("create directory..."); } else { outFile.createNewFile() ; System.out.println("create file..."); } } if(!entry.isDirectory()) { input = zipFile.getInputStream(entry) ; out = new FileOutputStream(outFile) ; int temp = 0 ; while((temp=input.read())!=-1){ out.write(temp) ; } input.close() ; // out.close() ; // } } input.close() ;
9:作业
-
读取以下的a.txt,统计相同单词的次数,最后按照次数的大小降序排列,输出到b.txt中。
a.txt (===算分隔符,不算单词,不考虑单词大小写)
hello world
hello
java world hello
b.txt
hello,3
world,2
java,1
提示:需要用到的内容有文本文件读和写操作。还要加上数据结构,有ArrayList, HashMap,Comparable等。
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; class MyComparator implements Comparator<Map.Entry<String,Integer>>{ public int compare(HashMap.Entry<String,Integer> he1,HashMap.Entry<String,Integer> he2) { return he2.getValue()-he1.getValue(); } } public class A { public static void main(String[] args) { // TODO Auto-generated method stub HashMap<String, Integer> hm = new HashMap<String,Integer>(); //文件读取 try(BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("D:\\夏雪星\\qhd\\xxx\\QHD.txt")))){ String line; while((line = br.readLine())!=null) { Pattern p = Pattern.compile("\\s+");//正则匹配空格 String words[]= p.split(line);//获取的字符串进行分割单词 for(String item : words) { if(item.length()!=0) { if(hm.get(item)==null) hm.put(item, 1);//将数据放入map中 else hm.put(item, hm.get(item)+1); } } } }catch(Exception e) { System.err.println(e.getMessage()); } //HashMap转换为list,进行排序 List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(hm.entrySet()); Collections.sort(list,new MyComparator()); //将数据写入文件 try(BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\夏雪星\\qhd\\xxx\\QHD1.txt")))){ for(Map.Entry<String, Integer> item: list) { bw.write(item.getKey()+","+item.getValue()); bw.newLine(); } }catch(Exception e) { System.err.println(e.getMessage()); } } }
第十二章 Java案例实践
package com.MOOC; public class ComputerStore { public static void main(String[] args) { //定义第一台机器的部件 CPU intel = new Intel(2, "intel cpu", 1000); Disk seagate = new Seagate(1000, "Seagate disk", 40960); //组装第一台机器并工作 Computer computer1 = new Computer("computer 1", intel, seagate); System.out.println("computer 1 description: " + computer1.description()); System.out.println("Computer 1 work: "); computer1.work(); //定义第二台机器的部件 CPU amd = new AMD(800, "AMD cpu", 2); Disk westdigital = new Seagate(2000, "West Digital disk", 81920); //组装第二台机器并工作 Computer computer2 = new Computer("computer 2", amd,westdigital); System.out.println("computer 2 description: " + computer2.description()); System.out.println("Computer 2 work: "); computer2.work(); } } package com.MOOC; public class AMD extends CPU{ public AMD(double price, String name, int coreNum) { super(price, name, coreNum); } public void work(){ System.out.println("This is AMD's cpu working"); } } package com.MOOC; public class Componnent { private double price; private String name; public Componnent(double price, String name) { this.price = price; this.name = name; } public String description(){ StringBuilder str=new StringBuilder(); str.append("Name:{") .append(name) .append("}; Price:{") .append(price) .append("};"); return str.toString(); } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } } package com.MOOC; public class Computer extends Componnent{ private CPU cpu; private Disk disk; public Computer( String name,CPU cpu,Disk disk) { super(-1,name); this.cpu=cpu; this.disk=disk; super.setPrice(cpu.getPrice()+disk.getPrice()); } public String description() { StringBuilder cmputerDescBuilder = new StringBuilder(); cmputerDescBuilder.append(super.description()) .append("CPU description: {") .append(cpu.description()) .append("}") .append("; Disk descripton: {") .append(disk.description()) .append("}"); return cmputerDescBuilder.toString(); } public void work() { cpu.work(); disk.work(); } } package com.MOOC; public class CPU extends Componnent implements Workable{ protected int coreNum; public CPU(double price, String name,int coreNum) { super(price, name); this.coreNum=coreNum; } @Override public void work() { } @Override public String description() { StringBuilder cpuDescBuilder = new StringBuilder(); cpuDescBuilder.append(super.description()) .append(" Core Num:{") .append(coreNum) .append("}"); return cpuDescBuilder.toString(); } } package com.MOOC; public class Disk extends Componnent implements Workable{ public int getVolume() { return volume; } public void setVolume(int volume) { this.volume = volume; } protected int volume; public Disk(double price, String name,int volume) { super(price, name); this.volume=volume; } @Override public void work() { } @Override public String description() { StringBuilder cpuDescBuilder = new StringBuilder(); cpuDescBuilder.append(super.description()) .append(" size(MB):{") .append(volume) .append(" MB}"); return cpuDescBuilder.toString(); } } package com.MOOC; public class Intel extends CPU{ public Intel(double price, String name, int coreNum) { super(price, name, coreNum); } public void work(){ System.out.println("This is Intel's CPU working"); } } package com.MOOC; public class Seagate extends Disk{ public Seagate(double price, String name, int volume) { super(price, name, volume); } public void work(){ System.out.println("This is seagate disk working"); } } package com.MOOC; public interface Workable { void work(); }
-
输出结果: