目录
三、Java API
1.Object:
1.1概念:
1.2常用方法:
2.String
2.1概述:
2.2特点:
2.3常用方法:
3.StringBuilder和StringBuffer
3.1特点
3.2常用方法
4.包装类 Number
4.1创建对象
4.2常用方法
5.日期类Date
5.1概述
5.2创建对象
5.3常用方法
5.4日期和时间的格式化编码
5.5日期工具SimpleDateFormat
6.BigDecimal和BigInteger
6.1概述
6.2创建对象
6.3常用方法
7.IO
7.1继承结构
7.2流的概念
7.3File文件流
7.4字节流读取
关闭流工具类:
7.5字节流写出
7.6 字符流读取
7.7字符流写出
7.8 扩展
8.泛型
8.1概念
8.2作用
8.3泛型声明
8.4常用名称
9.集合
9.1Collection接口
9.2List接口
9.3ArrayList
9.4LinkList
9.5set接口
9.6HashSet
10.Map接口
10.1概述
类型参数: K - 此映射所维护的键的类型V - 映射值的类型。
10.2特点
10.3继承结构
10.4常用方法
10.5HashMap
11Collections工具类
11.1常用方法
API:Application Programming Interface应用编程接口,一切可以调用的东西都是API。
java.lang包,这个包会自动导入。
java.lang.Object
java.lang.String
java.lang.StringBuilder/StringBuffer
正则表达式
包装类等
所有对象的顶级父类
存在于java.lang包中,这个包不需要我们手动导包
String toString() 返回该对象的地址值 int hashCode() 返回该对象的哈希码值。 boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”。
import java.util.Objects;
//测试 Object
//总结:
//1,重写toString()--默认是使用Object的toString()展示的就是地址值.因为现在想看属性值
//2,重写equals()--默认是使用Object的equals()展示的是地址值间的比较,
// 现在不想比较地址值,想比较对象间的属性值
//3,怎么自动生成--右键-generate...ok
//4,instanceof是java里的关键字,通常用来判断 obj instanceof Student ,判断obj 484 Student类型
public class Test2_Object {
public static void main(String[] args) {
//1,创建Student对象,并使用父类Object的方法
Student s = new Student("张三",46);
System.out.println( s.hashCode() );//返回哈希码值-460141958
//2,新需求:打印的不要地址值,而是想要对象的属性值--继承Object,重写toString()
System.out.println( s.toString() );//用的Object的,返回地址值-cn.tedu.api.Student@1b6d3586
System.out.println( s );
//2.2,toString()没重写,默认返回地址值,但是如果重写了会返回对象的属性值
//cn.tedu.api.Student@1b6d3586 -> Student{name='张三', age=46}
System.out.println( s.equals("abc") );//用的Object的,判断是否和abc相等-false
//3,新需求:当执行equals()进行对象间比较时,现在不想比较地址值,而想要根据属性值来比较
//默认使用的是Object提供的this == obj,
//==比较基本类型的值时,比的是数值本身.比较引用类型的值时,比的是地址值
Student s2 = new Student("张三",46);
System.out.println( s == s2);//在比地址值 false
System.out.println( s.equals(s2) );//默认使用的是Object提供的this == obj,比地址值就是false
}
}
class Student{
//3.1,提供重写的equals()--是要比较对象间的属性值,而不是地址值
// public boolean equals(Object obj) {
// //java.lang.ClassCastException: java.lang.String cannot be cast to cn.tedu.api.Student
// //加一个判断,如果obj也是Student类型,才参与比较--instanceof
// if(obj instanceof Student){
// //向下转型--转成Student类型,来使用Student特有的功能
// Student s = (Student)obj ;
//
// //根据两个对象的属性值判断.
// // 如果name和age的属性值都一样,就认为两个对象是相等的返回true
// if(name==s.name && age==s.age){
// return true;
// }
// }
// return false ;
// }
//generate...--equals() and hashCode()--ok
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
//2.1,提供重写的toString()--方便查看属性值,而不是地址值--generate..toString()..ok
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//提供丰富的构造方法--generate...constructor-看需求-ok
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
private String name;
private int age;
//提供set()/get() --generate...-getter and setter-按着ctrl全选-ok
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的 实例实现。
字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。
--源码摘抄:public final class String{//String是一个最终的类,不能被继承 //数组一旦创建,长度就不能改变了.而且数组被final了,值不能改,是一个常量 private final char value[]; } --字符串底层会创建一个char[]来存放字符数据 --字符串的本质上 是一个char[]
//char charAt(int index)返回指定索引处的 char 值。
System.out.println(s.charAt(2));
//String concat(String str)将指定字符串连接到此字符串的结尾。
System.out.println(s.concat("张三"));
// boolean contains(CharSequence s)当且仅当此字符串包含指定的 char 值序列时,返回 true。
System.out.println(s.contains("d"));
// boolean endsWith(String suffix)测试此字符串是否以指定的后缀结束。
System.out.println(s.endsWith("apple"));
//boolean equals(Object anObject)将此字符串与指定的对象比较。
System.out.println(s.equals("banana"));
// int hashCode()返回此字符串的哈希码。
System.out.println(s.hashCode());
//int indexOf(String str)返回指定子字符串在此字符串中第一次出现处的索引。
System.out.println(s.indexOf("cd"));
//boolean isEmpty()当且仅当 length() 为 0 时返回 true。
System.out.println(s.isEmpty());
// int length()返回此字符串的长度
System.out.println(s.length());
//int lastIndexOf(String str)返回指定子字符串在此字符串中最右边出现处的索引。
System.out.println(s.lastIndexOf("e"));
//boolean startsWith(String prefix)测试此字符串是否以指定的前缀开始。
System.out.println(s.startsWith("l"));
// String toLowerCase()使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
System.out.println(s.toLowerCase());
// String toUpperCase()使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
System.out.println(s.toUpperCase());
// String substring(int beginIndex)返回一个新的字符串,它是此字符串的一个子字符串。
System.out.println(s.substring(2));
// String substring(int beginIndex, int endIndex)返回一个新字符串,它是此字符串的一个子字符串。
System.out.println(s.substring(1, 5));//从1开始到5结束
//String trim()返回字符串的副本,忽略前导空白和尾部空白。
System.out.println(s.trim());//去除空格
//static String valueOf(int i)返回 int 参数的字符串表示形式。
// System.out.println(String.valueOf(100));
String st = String.valueOf(10);
System.out.println(st + 1);
// char[] toCharArray()将此字符串转换为一个新的字符数组。
char c[] = s.toCharArray();
System.out.println(c);
//byte[] getBytes()使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
byte by[] = s.getBytes();
System.out.println(Arrays.toString(by));
//String[] split(String regex)根据给定正则表达式的匹配拆分此字符串。
String[] ss = s.split("1");//按照制定规则切割字符串,并存入字符串
System.out.println(Arrays.toString(ss));
1、 封装了char[]数组
2、 是可变的字符序列
3、 提供了一组可以对字符内容修改的方法
4、 常用append()来代替字符串做字符串连接
5、 内部字符数组默认初始容量是16:initial capacity of 16 characters
6、 如果大于16会尝试将扩容,新数组大小原来的变成2倍+2,容量如果还不够,直接扩充到需要的容量大小。int newCapacity = value.length * 2 + 2;
7、 StringBuffer 1.0出道线程安全,StringBuilder1.5出道线程不安全
StringBuilder append(String str) 将指定的字符串追加到此字符序列。
public class Test02_StringBuffer {
public static void main(String[] args) {
method();
method2();//StringBuilder优化--可以拼接任意类型数据
method3();//concat拼接字符串--只能凭借字符串类型
}
public static void method() {
String s = "wsgdsdsjajdsosw";
String s1 = "";
//计时器
long start = System.currentTimeMillis();//计时开始ms
for (int i = 0; i <= 10000; i++) {
s1 += s;
}
long end = System.currentTimeMillis();//计时结束ms
System.out.println(s1);
System.out.println(end - start); //计算时间差ms
}
//StringBuilder优化
public static void method2() {
String s = "wsgdsdsjajdsosw";
StringBuilder sb = new StringBuilder();//创建对象
//计时器
long start = System.currentTimeMillis();//计时开始ms
for (int i = 0; i <= 10000; i++) {
sb.append(s);
}
long end = System.currentTimeMillis();//计时结束ms
System.out.println(end - start); //计算时间差ms
}
//concat拼接字符串
public static void method3() {
String s = "wsgdsdsjajdsosw";
String st = new String();//创建对象
//计时器
long start = System.currentTimeMillis();//计时开始ms
for (int i = 0; i <= 10000; i++) {
st.concat(s);
}
long end = System.currentTimeMillis();//计时结束ms
System.out.println(end - start); //计算时间差ms
}
}
【Number:数字包装类的抽象父类】
Integer(int value)
int intValue() 以 int 类型返回该 Integer 的值。 static int parseInt(String s) 将字符串参数作为有符号的十进制整数进行解析。 static Integer valueOf(int i) 返回一个表示指定的 int 值的 Integer 实例。
public class Test03_Number {
public static void main(String[] args) {
//创建Integer对象
Integer iny = 5;
Integer i = new Integer(5);//自动装箱(将int类型装换为包装类型)
//高效的缓存,如果数据的范围在-128~127之间,相同数据只存一次--类似于常量池!!
Integer in = Integer.valueOf(5);//自动装箱(更高效)
//高效只存在于:byte、short、int、long,其他类型都不高效
int a = i.intValue();//自动拆箱(将包装类型装换为int类型)
System.out.println(a);
//Double
Double d = new Double(5.2);
Double d2 = Double.valueOf(5.2);//不高效和new一样
double dou = d.doubleValue();//将包装类型装换为基本类型
}
}
存在于java.util.Date包。
用来封装一个毫秒值表示一个精确的时间点。
从1970-1-1 0点开始的毫秒值。
new Date():封装的是系统当前时间的毫秒值
new Date(900000000000L):封装指定的时间点
getTime():取内部毫秒值
setTime():存取内部毫秒值
getMonth():获取当前月份
getHours():获取当前小时
compareTo(Date):当前对象与参数对象比较。当前对象大返回正数,小返回负数,相同0。
import java.util.Date;
//Date:时间工具类
public class Test04_Date {
public static void main(String[] args) {
Date d = new Date();
System.out.println( d.getTime());//以表示 1970 年 1 月 1 日 00:00:00 GMT 以后 time 毫秒的时间点。
System.out.println(d.getClass());//返回此Object的运行时类
System.out.println(d.getDate());//获取今天是一个月内的第几天
System.out.println(d.getDay());//获取今天星期几
System.out.println(d.getHours());//获取现在是几点
System.out.println(d.getMinutes());//获取一个小时里的第几分钟
System.out.println(d.getMonth());//获取自然月份(从0开始,自然月-1)
System.out.println(d.getSeconds());//获取现在是第几秒
System.out.println(d.getTimezoneOffset());//返回相对于UTC(相应于此Date对象表示的时间)的本地时区的偏移量(以分钟为单位)。
System.out.println(d.getYear());//获取从1990年到现在一共多少年
}
}
时间模式字符串用来指定时间格式。在此模式中,所有的 ASCII 字母被保留为模式字母,定义如下:
5.5.1概述:
日期格式化工具,可以把Date对象格式化成字符串,也可以日期字符串解析成Date对象。
5.5.2创建对象:
new SimpleDateFormat(格式)
格式:yyyy-MM-dd HH:mm:ss
5.5.3常用方法:
format(Date):把Date格式化成字符串
parse(String):把String解析成Date
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
//StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos)将给定的 Date 格式化为日期/时间字符串,并将结果添加到
// Date parse(String text, ParsePosition pos)解析字符串的文本,生成 Date。
public class Test05_SimpleDateFormat {
public static void main(String[] args) throws ParseException {
//接收用户输入出生日期
String date = new Scanner(System.in).nextLine();
//将string类型日期转换为Date类型
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(date);
//计算存活日期
long start = d.getTime();
long now = System.currentTimeMillis();
System.out.println((now-start)/1000/60/60/24); //ms换算天
}
}
面试题1:
StringBuilder和StringBuffer的区别:
1、 在线程安全上,
--StringBuffer是旧版本就提供的,线程安全的。@since JDK1.0
--StringBuilder是jdk1.5后产生,线程不安全的。@since 1.5
2、 在执行效率上,StringBuilder > StringBuffer > String
3、 源码体现:本质上都是在调用父类抽象类AbstractStringBuilder来干活,只不过Buffer把代码加了同步关键字,使得程序可以保证线程安全问题。
abstract class AbstractStringBuilder implements Appendable, CharSequence {
面试题2:
什么是自动装箱和自动拆箱?
自动装箱:把基本类型包装成一包装类的对象
Integer a = 5;//a是引用类型,引用了包装对象的地址。
编译器会完成对象的自动装箱:Integer a = Integer.valueOf(5);
自动拆箱:从包装对象中,自动取出基本类型值
int i = a;//a现在是包装类型,没法给变量赋值,需要把5取出来。
编译器会完成自动拆箱:int i = a.intValue();
BigDecimal:常用来解决精确的浮点数运算。
BigInteger:常用来解决超大的整数运算。
BigDecimal.valueOf(2);
add(BigDecimal bd): 做加法运算
substract(BigDecimal bd) : 做减法运算
multiply(BigDecimal bd) : 做乘法运算
divide(BigDecimal bd) : 做除法运算
divide(BigDecimal bd,保留位数,舍入方式):除不尽时使用
setScale(保留位数,舍入方式):同上
pow(int n):求数据的几次幂
import java.math.BigDecimal;
import java.util.Scanner;
//BigDecimal:解决小数运算不精确
public class Test06_BigDecimal {
public static void main(String[] args) {
method();
method2();//BigDecimal
}
public static void method() {
double a = new Scanner(System.in).nextDouble();
double b = new Scanner(System.in).nextDouble();
System.out.println(a + b);
System.out.println(a - b);
System.out.println(a * b);
System.out.println(a / b);
}
//BigDecimal
//BigDecimal(double val)将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。
public static void method2() {
double a = new Scanner(System.in).nextDouble();
double b = new Scanner(System.in).nextDouble();
//创建对象
//double
BigDecimal bd1 = new BigDecimal(a);//有坑(不建议用)
BigDecimal bd2 = new BigDecimal(b);
BigDecimal bd3 = bd1.add(bd2);
System.out.println(bd3);
//string类型(推荐)
BigDecimal bd5 = new BigDecimal(a + "");
BigDecimal bd4 = new BigDecimal(String.valueOf(b));
BigDecimal bd6 = bd5.add(bd4);
System.out.println(bd6);
bd6 = bd5.subtract(bd4);
System.out.println(bd6);
bd6 = bd5.multiply(bd4);
System.out.println(bd6);
//divide(x,y,z)--x是要做除法运算的对象,y是保留的小数位数,z是舍入模式
bd6 = bd5.divide(bd4,5,BigDecimal.ROUND_HALF_UP);//四舍五入
System.out.println(bd6);
}
}
n/out相对于程序而言的输入(读取)和输出(写出)的过程。
在Java中,根据处理的数据单位不同,分为字节流和字符流
java.io包:
File
字节流:针对二进制文件
InputStream
--FileInputStream
--BufferedInputStream
--ObjectInputStream
OutputStream
--FileOutputStream
--BufferedOutputStream
--ObjectOutputStream
字符流:针对文本文件。读写容易发生乱码现象,在读写时最好指定编码集为utf-8
Writer
--BufferedWriter
--OutputStreamWriter
Reader
--BufferedReader
--InputStreamReader
--PrintWriter/PrintStream
数据的读写抽象成数据,在管道中流动。
Ø 流只能单方向流动
Ø 输入流用来读取in
Ø 输出流用来写出Out
Ø 数据只能从头到尾顺序的读写一次
7.3.1概述
封装一个磁盘路径字符串,对这个路径可以执行一次操作。
可以用来封装文件路径、文件夹路径、不存在的路径。
7.3.2创建对象
File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
7.3.3常用方法
文件、文件夹属性
length():文件的字节量
exists():是否存在,存在返回true
isFile():是否为文件,是文件返回true
isDirectory():是否为文件夹,是文件夹返回true
getName():获取文件/文件夹名
getParent():获取父文件夹的路径
getAbsolutePath():获取文件的完整路径
创建、删除
createNewFile():新建文件,文件夹不存在会异常,文件已经存在返回false
mkdirs():新建多层不存在的文件夹\a\b\c
mkdir():新建单层不存在的文件夹\a
delete():删除文件,删除空文件夹
文件夹列表
list():返回String[],包含文件名
listFiles():返回File[],包含文件对象
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;
public class Test01_File {
public static void main(String[] args) throws IOException {
File f = new File("D:\\1.txt");
System.out.println(f.length()); //获取文件大小
System.out.println(f.exists()); //判断文件是否存在
System.out.println(f.isFile());// 判断是否为文件
System.out.println(f.isDirectory()); //判断是否为文件夹
System.out.println(f.getName());// 获取文件名
System.out.println(f.getParent());// 获取文件父路径
System.out.println(f.getAbsolutePath());// 获取完整路径
f = new File("D:\\2.txt");
System.out.println(f.createNewFile());//创建不存在的文件
f = new File("D:\\abc");
System.out.println(f.mkdir());//创建文件夹
f = new File("D:\\abc\\a\\b");
System.out.println(f.mkdirs());//创建多个文件夹
System.out.println(f.delete());//删除文件或空文件夹
//列出文件夹的资源
f = new File("D:\\eclipse");
String[] s = f.list();//获取所有资源的名字存入String[]
System.out.println(Arrays.toString(s));
File[] f1=f.listFiles();//获取所有资源并封装成file对象,存入 File[]
System.out.println(Arrays.toString(f1));
//创建3个file对象存入容器里
File file1 = new File("D:\\1.txt");
File file2 = new File("D:\\2.txt");
File file3 = new File("D:\\3.txt");
File[] ff = new File[]{file1,file2,file3};
System.out.println(Arrays.toString(ff));
//TODo统计文件夹里所有文件的大小
// 1,接收用户输入文件夹路径
// 2,列出文件夹里的所有资源
// 3,判断资源是文件夹还是文件
// 4,如果是文件求和.如果是文件夹,输出文件夹名称
String s1 = new Scanner(System.in).nextLine();
File fi= new File(s1);
File fff[]=fi.listFiles();
long sun=0;
// System.out.println(Arrays.toString(fff));
for (int i = 0; i < fff.length; i++) {
if (fff[i].isFile()) {
sun+=fi.length();
}else{
System.out.println(fff[i].getName());
}
}
System.out.println("文件总大小:"+sun);
}
}
7.3.4递归: 自己调用自己
递归:统计文件大小,删除文件
求目录的总大小:
1、把指定目录封装成File对象
2、把文件夹列表列出来
3、判断,如果是文件,直接把f.length()相加
4、判断,如果是文件夹,继续列表,继续判断,如果是文件相加,如果又是文件夹,继续列表,继续判断,如果是文件相加......
5、如果是文件夹,递归调用方法本身的业务逻辑
package cn.tedu.io;
import java.io.File;
import org.junit.Test;
//递归求目录总大小
public class Test2_File2 {
public static void main(String[] args) {
// 1、把指定目录封装成File对象
File file = new File("D:\\teach\\a");
int size =count(file);
System.out.println(size);
}
private static int count(File file) {
// 2、把文件夹列表列出来
File[] files = file.listFiles();
//2.1 遍历数组里的每个资源
int sum = 0;//记录文件的大小
for (int i = 0; i < files.length; i++) {
// 3、判断,如果是文件,直接把f.length()相加
// files[i]表示每次遍历到的资源
if(files[i].isFile()) {
sum += files[i].length();//求文件的和
}else if(files[i].isDirectory()){
// 4、判断,如果是文件夹,继续列表,继续判断,如果是文件相加,如果又是文件夹,继续列表,继续判断,如果是文件相加......
// 5、如果是文件夹,递归调用方法本身的业务逻辑
sum += count(file[i]);//把当前遍历到的文件夹继续循环判断求和
}
}
return sum ;
}
}
字节流是由字节组成的,字符流是由字符组成的. Java里字符由两个字节组成.字节流是最基本的,所有的InputStream和OutputStream的子类都是,主要用在处理二进制数据。
流式传输主要指将整个音频和视频及三维媒体等多媒体文件经过特定的压缩方式解析成一个个压缩包,由视频服务器向用户计算机顺序或实时传送。在采用流式传输方式的系统中,用户不必像采用下载方式那样等到整个文件全部下载完毕,而是只需经过几秒或几十秒的启动延时即可在用户的计算机上利用解压设备对压缩的A/V、3D等多媒体文件解压后进行播放和观看。此时多媒体文件的剩余部分将在后台的服务器内继续下载。
7.4.1InputStream抽象类
此抽象类是表示字节输入流的所有类的超类/抽象类。
常用方法:
abstract int read() 从输入流中读取数据的下一个字节。
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。
void close() 关闭此输入流并释放与该流关联的所有系统资源。
7.4.2FileInputStream子类
直接插在文件上,直接读取文件数据。
创建方法:
FileInputStream(File file)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream(String pathname)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
7.4.2BufferedInputStream子类
BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组(默认8M大小)。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。
创建对象:
BufferedInputStream(InputStream in)
创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用
import java.io.*;
//测试字节流读写
public class Test04_InputStream {
public static void main(String[] args) throws IOException {
method();
method2();//BufferedInputStream
}
public static void method() throws IOException {
InputStream ins = new FileInputStream("D:\\demo\\1.txt");//指定要读取的哪儿的文件
InputStream ins2 = new FileInputStream(new File("D:\\demo\\1.txt"));//指定要读取文件的路径
//read()一个一个读,没有数据可读时永远返回-1
// int data = ins.read();
// System.out.println(data);
// int data2 = ins.read();
// System.out.println(data2);
// int data3 = ins.read();
// System.out.println(data3);
// int data4 = ins.read();
// System.out.println(data4);
//循环优化
int b;//定义变量,记录读取数据
while ((b = ins.read()) != -1) {b只要读到的不是-1就行
System.out.println(b);
}
ins.close();//关闭资源
}
public static void method2() {
InputStream ins = null;
try {
ins = new BufferedInputStream(new
FileInputStream("D:\\demo\\1.txt"));
// int a= ins.read();
// System.out.println(a);
// ins.close();
int b;//定义变量,记录读取数据
while ((b = ins.read()) != -1) {b只要读到的不是-1就行
System.out.println(b);
}
} catch (IOException e) {
System.out.println("读取失败");
} finally {
//释放资源
try {
ins.close();//关闭资源
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.Closeable;
import java.io.IOException;
/*
IO关闭资源工具类
*/
/**
* IO关闭资源工具类
*/
public class IO_Utils {
//Closeable:体现了多态
public static void close(Closeable c) {
if (c != null) {//防止空指针异常
try {
c.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
7.5.1OutputStream抽象类
此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。
void close()
关闭此输出流并释放与此流有关的所有系统资源。
void flush()
刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b)
将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b)
将指定的字节写入此输出流。
7.5.2FileOutputStream子类
直接插在文件上,直接写出文件数据
创建对象:
FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。FileOutputStream(File file)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append) –追加
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
7.5.2BufferedOutputStream子类
该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
import cn.tedu.utils.IO_Utils;
import java.io.*;
public class Test01_OutputStream {
public static void main(String[] args) throws IOException {
method();
method2();
}
public static void method() {
// OutputStream out1 = new FileOutputStream("D:\\1.txt");//数据覆盖
OutputStream out = null;
try {
out = new FileOutputStream("D:\\1.txt", true);//数据追加
out.write(123);
out.write(456);
} catch (IOException e) {
// TODO: handle exception
} finally {
// if (out != null) {//加判断防止空指针异常
//
// try {
// out.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
IO_Utils.close(out);//关闭流工具类提供
}
}
public static void method2() throws IOException {
OutputStream out = new BufferedOutputStream(new
FileOutputStream("D:\\2.txt",true));//追加
out.write(987);
out.write(897);
out.flush();//刷出数据
// out.close();//刷出数据并关闭资源
}
}
7.5.3文件拷贝练习
import java.io.*;
import java.util.Scanner;
//文件复制
public class Test02_Copy {
public static void main(String[] args) {
System.out.println("请输入源文件路径:");
String from = new Scanner(System.in).nextLine();
System.out.println("请输入目标文件路径:");
String to = new Scanner(System.in).nextLine();
copy(from, to);
System.out.println("复制完成");
}
public static void copy(String from, String to) {
InputStream in = null;
OutputStream out = null;
try {
//创建读写对象
in = new BufferedInputStream(new FileInputStream(from));
out = new BufferedOutputStream(new FileOutputStream(to));
//边读边写
int d;//定义变量记录read()读到的数据
while ((d = in.read()) != -1) {
out.write(d);//把读到的文件写道指定文件
}
} catch (IOException e) {
System.out.println("文件复制失败");
} finally {
//释放资源
IO_Utils.close(in);
IO_Utils.close(out);
}
}
}
常用于处理纯文本数据。
7.6.1Reader抽象类
用于读取字符流的抽象类。
常用方法:
int read()
读取单个字符。
int read(char[] cbuf)
将字符读入数组。
abstract int read(char[] cbuf, int off, int len)
将字符读入数组的某一部分。
int read(CharBuffer target)
试图将字符读入指定的字符缓冲区。
abstract void close()
关闭该流并释放与之关联的所有资源。
7.6.2 FileReader子类
用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。
创建对象
FileReader
(
StringfileName)
在给定从中读取数据的文件名的情况下创建一个新 FileReader。FileReader
(
Filefile)
在给定从中读取数据的 File 的情况下创建一个新 FileReader。
7.6.3 InputStreamReader子类
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
创建对象
InputStreamReader(InputStream in, String charsetName)
创建使用指定字符集的 InputStreamReader。
InputStreamReader(InputStream in)
创建一个使用默认字符集的 InputStreamReader。
7.6.4 BufferedReader子类
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
创建对象
BufferedReader(Reader in)
创建一个使用默认大小输入缓冲区的缓冲字符输入流。
7.7.1 Writer抽象类
写入字符流的抽象类。
常用方法:
void write(char[] cbuf)
写入字符数组。
abstract void write(char[] cbuf, int off, int len)
写入字符数组的某一部分。
void write(int c)
写入单个字符。
void write(String str)
写入字符串。
void write(String str, int off, int len)
写入字符串的某一部分。
abstract void close()
关闭此流,但要先刷新它。
7.7.2 FileWriter子类
用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。
创建对象
FileWriter
(
StringfileName)
根据给定的文件名构造一个 FileWriter 对象。FileWriter
(
StringfileName, boolean append)
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
7.7.3 OutputStreamWriter子类
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
创建对象
OutputStreamWriter(OutputStream out, String charsetName)
创建使用指定字符集的 OutputStreamWriter。
OutputStreamWriter(OutputStream out)
创建使用默认字符编码的 OutputStreamWriter。
7.7.4 BufferedWriter子类
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
创建对象
BufferedWriter(Writer out)
创建一个使用默认大小输出缓冲区的缓冲字符输出流。
7.7.5 练习:字符流读写
把数据写出到指定文件中。如果文件不存在会自动创建,文件夹不存在会报错。
package cn.tedu.hello;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class rr {
public static void main(String[] args) throws Exception {
// method1();//字符读取
method2();//字符写出
}
private static void method2() throws Exception {
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("D:\\\\teach\\\\a.txt"))
, "utf-8"));
long s = System.currentTimeMillis();
for(int i = 48 ; i < 1000000; i++) {
out.write(i);
}
s = System.currentTimeMillis() - s;
System.out.println(s + "--");//266
out.close();
}
private static void method1() throws Exception {
//字符流读图片乱码
// BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(new File("D:\\teach\\1.jpg"))));
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(new File("D:\\teach\\a\\1.txt"))));
// System.out.println(in.readLine());
// System.out.println(in.readLine());//null读到/n/r
String line = "";
while((line = in.readLine())!=null) {//一行一行读
System.out.println(line);
}
in.close();
}
}
7.8.1 序列化 / 反序列化
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
1、序列化:利用ObjectOutputStream,对象的信息,按固定格式转成一串字节值输出并持久保存到磁盘化。
2、反序列化:利用ObjectInputStream,读取磁盘中序列化数据,重新恢复对象。
注意:
1、 需要序列化的文件必须实现Serializable接口以启用其序列化功能。
2、 每个被序列化的文件都有一个唯一id,如果没有添加编译器会根据类的定义信息计算产生一个版本号。
package cn.tedu.serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Test5_Seri {
public static void main(String[] args) throws Exception, IOException {
//序列化:就是把java对象保存在磁盘中
ObjectOutputStream os =
new ObjectOutputStream(
new FileOutputStream(
"D:\\teach\\a\\student.txt"));
Student s = new Student("张三",20,"成都");
os.writeObject(s);//序列化,把Student对象信息保存到指定文件中
os.close();//关闭输出资源
//反序列化:从磁盘读到程序里
ObjectInputStream in =
new ObjectInputStream(
new FileInputStream(
"D:\\teach\\a\\student.txt"));
//反序列化,把文件里的数据读到程序中,封装成对象,默认是Object
Object obj =in.readObject();
System.out.println(obj);
}
}
//1,如果想完成序列化,类必须实现Serializable接口
//只是用来做标记,需要序列化
class Student implements Serializable{
//创建对象用
public Student(String name, int age, String addr) {
this.name = name;
this.age = age;
this.addr = addr;
}
//一般序列化的都是属性
String name = "张三";
int age = 20;
String addr = "成都";
//为了看属性值
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", addr=" + addr + "]";
}
}
7.8.2 BIO、NIO、AIO的区别
阻塞IO,BIO 就是传统的 java.io 包,它是基于流模型实现的,交互的方式是同步、阻塞方式,也就是说在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调用时可靠的线性顺序。它的有点就是代码比较简单、直观;缺点就是 IO 的效率和扩展性很低,容易成为应用性能瓶颈。
非阻塞IO,NIO 是 Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层高性能的数据操作方式。
异步IO,AIO 是 Java 1.7 之后引入的包,是 NIO 的升级版本,提供了异步非堵塞的 IO 操作方式,所以人们叫它 AIO(Asynchronous IO),异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。但目前还不够成熟,应用不多。
泛型是(Generics)是JDK1.5 的一个新特性,其实就是一个『语法糖』,本质上就是编译器为了提供更好的可读性而提供的一种小手段,小技巧,虚拟机层面是不存在所谓『泛型』的概念的。
通过泛型的语法定义,约束集合元素的类型,进行安全检查,把错误显示在编译期
代码通用性更强
泛型可以提升程序代码的可读性,但它只是一个语法糖(编译后这样的东西就被删除,不出现在最终的源代码中),对于JVM运行时的性能是没有任何影响的
泛型可以在接口、方法、返回值上使用:
java.util.List泛型接口/类:
public interface Collection
{} 泛型方法的声明:
public
void print(E e) {} 在方法返回值前声明了一个
表示后面出现的E是泛型,而不是普通的java变量。
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型
9.1.1概述
英文名称Collection,是用来存放对象的数据结构。其中长度可变,而且集合中可以存放不同类型的对象。并提供了一组操作成批对象的方法。
数组的缺点:长度是固定不可变的,访问方式单一,插入、删除等操作繁琐。
9.1.2集合的继承结构
9.1.3常用方法
boolean add(E e):添加元素。
boolean addAll(Collection c):把小集合添加到大集合中 。
boolean contains(Object o) : 如果此 collection 包含指定的元素,则返回 true。
boolean isEmpty() :如果此 collection 没有元素,则返回 true。
Iterator
iterator():返回在此 collection 的元素上进行迭代的迭代器。 boolean remove(Object o) :从此 collection 中移除指定元素的单个实例。
int size() :返回此 collection 中的元素数。
Objec[] toArray():返回对象数组
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
public class Test01_Collection {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add(1);//添加元素
c.add(2);//添加元素
c.add(3);//添加元素
// c.clear();//清空集合
System.out.println(c.contains(2)); //判断是否包含元素
System.out.println(c.equals(2));//判断相等
System.out.println(c.hashCode());//打印哈希码
System.out.println(c.isEmpty());//判断是否为空
System.out.println(c.remove(3));//移除指定数据
System.out.println(c.size());//集合长度
Object[] o = c.toArray();//将集合存入数组
System.out.println(Arrays.toString(o));
//集合间的操作
Collection c2 = new ArrayList();
c2.add(1);
c2.add(2);
c2.add(3);
c2.add(4);
System.out.println(c2.addAll(c)); //把c的数据加入到c2中
System.out.println(c2.containsAll(c));//判断c2里是否包含c
System.out.println(c2.removeAll(c)); //移除交集
System.out.println(c2.retainAll(c)); //移除差集(保留交集)
//Iterator:迭代器(遍历集合)
/*
boolean hasNext()
如果仍有元素可以迭代,则返回 true。
E next()
返回迭代的下一个元素。
void remove()
从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
*/
Iterator it = c.iterator();
//hdsNext()-判断集合里有元素吗,有元素就获取,没有就不取.
/*
hasNext()
如果仍有元素可以迭代,则返回 true。
next()
返回迭代的下一个元素。
*/
while (it.hasNext()) {
Integer in = it.next();//获取元素
System.out.println(in);
}
}
}
9.2.1概述
有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
9.2.2特点
1、 数据有序
2、 允许存放重复元素
3、 元素都有索引
9.2.3常用方法
ListIterator
listIterator() 返回此列表元素的列表迭代器(按适当顺序)。
ListIterator
listIterator(int index) 返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
void add(int index, E element)
在列表的指定位置插入指定元素(可选操作)。
boolean addAll(int index, Collection extends E> c)
将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
List
subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
E get(int index)
返回列表中指定位置的元素。
int indexOf(Object o)
返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
import java.util.*;
//List集合
public class Test02_List {
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(1);
list.add(3);
list.add(4);
System.out.println(list.contains(3));//判断是否包含
System.out.println(list.hashCode());//打印哈希码
System.out.println(list.isEmpty());//判断是否为空
System.out.println(list.remove(2));//移除指定元素
System.out.println(list.size());//集合大小
System.out.println(list.equals(12));//判断是否相等
Object[] o = list.toArray();//将集合存入数组
System.out.println(Arrays.toString(o));
//List扩展方法
list.add(4, 56);//在4索引处插入新的值56
System.out.println(list.get(4));//获取下标为4的元素
System.out.println(list.indexOf(1));//获取第一次出现元素为1的索引值
System.out.println(list.lastIndexOf(1));//获取最后出现元素为1的索引值
System.out.println(list.remove(4));//移除索引为4的元素(返回移除的元素)
//System.out.println(list.remove(3));
//问题:拿着3当下标来看的.怎么把基本类型的3变成 object类型呢?--Integer
//需要把3从字面值int类型变成Integer类型--自己完成装箱Integer.valueOf(3);
System.out.println(list.remove(Integer.valueOf(3)));移除第一次出现值为3的元素
System.out.println(list.set(2, 5));//设置索引为2的元素值为5(打印被替换的值)
List list2 = list.subList(2, 3);//截取索引为2-3(含头不含尾)的元素
System.out.println(list2);
//TODO 迭代list集合
//Iterator iterator() 和ListIterator listIterator() 的区别
//Iterator.是父接口, ListIterator是子接口除了能用父接口的方法还拓展了逆向遍历(不用!)
//TODO 方式1:继承自父接口Collection-----Iterator iterator()
Iterator it = list.iterator();
while (it.hasNext()) {//判断后面有没有元素
// Integer next = it.next();
// System.out.println(next);
System.out.println(it.next()); //打印元素
}
//TODO 方式2:List特有的-----ListIterator listIterator()
ListIterator integerListIterator = list.listIterator();
while (integerListIterator.hasNext()){
System.out.println(integerListIterator.next());
}
//TODO 方式3:普通for
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i)); //根据索引获取元素
}
//TODO 方式4:增强for
for (Integer i : list ) {
System.out.println(i);
}
}
}
9.3.1概述
1) 存在于java.util包中。
2) 内部用数组存放数据,封装了数组的操作,每个对象都有下标。
3) 内部数组默认初始容量是10。如果不够会以1.5倍容量增长。
4) 查询快,增删数据效率会降低。
9.3.2创建对象
new ArrayList():初始容量是10
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/*
ArrayList集合
*/
public class Test03_ArrayList {
public static void main(String[] args) {
ArrayList a = new ArrayList();
a.add(100);
//当向集合中添加元素时,才开始分配内存,本质上是在不断的给必层维护的数组扩容,默认容量是10
//如果不够,自动扩容,按照1.5倍的速度扩容。
System.out.println(a.isEmpty());
// System.out.println(a.iterator());
System.out.println(a.remove(2));
System.out.println(a.size());
System.out.println(a.get(1));
System.out.println(a.contains(200));
System.out.println(a.hashCode());
System.out.println(a.equals(100));
Object[] objects = a.toArray();
System.out.println(Arrays.toString(objects));
a.add(1,200);
System.out.println(a.indexOf(500));
System.out.println(a.lastIndexOf(200));
System.out.println(a.remove(Integer.valueOf(600)));
System.out.println(a.set(2,500));
List list = a.subList(1, 3);
System.out.println(list);
}
}
9.4.1概述
双向链表,两端效率高。底层就是数组和链表实现的。
9.4.2常用方法
add()
get()
size()
remove(i)
remove(数据)
iterator()
addFirst() addLast()
getFirst() getLast()
removeFirst() removeLast()
import java.util.LinkedList;
//LinkedList
public class Test04_LinkedList {
public static void main(String[] args) {
LinkedList l = new LinkedList();
l.add("张三");
l.add("李四");
l.add("王五");
System.out.println(l);
l.addFirst("钢铁侠");//添加首元素
l.addLast("灭霸");//添加尾元素
System.out.println(l.getFirst());//获取首元素
System.out.println(l.getLast());//获取尾元素
System.out.println(l.removeFirst());//移除首元素
System.out.println(l.removeLast());//移除尾元素
System.out.println(l);
System.out.println(l.pollFirst());//获取并移除首元素
System.out.println(l.pollLast());//获取并移除尾元素
System.out.println(l.offerFirst("孙悟空"));//插入首元素
System.out.println(l.offerLast("猪八戒"));//插入尾元素
System.out.println(l.peekFirst());//获取不移除首元素
System.out.println(l.peekLast());//获取不移除尾元素
System.out.println(l);
}
}
9.5.1概述
一个不包含重复元素的 collection。
数据无序(因为set集合没有下标)。
由于集合中的元素不可以重复。常用于给数据去重。
9.5.2特点
HashSet:底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。当然K仍然不许重复。
TreeSet:底层就是TreeMap,也是红黑树的形式,便于查找数据。
HashMap实现中,当哈希值相同的对象,会在同一个hash值的位置存储不同属性的数据。
9.5.3常用方法
boolean add(E e):添加元素。
boolean addAll(Collection c):把小集合添加到大集合中 。
boolean contains(Object o) : 如果此 collection 包含指定的元素,则返回 true。
boolean isEmpty() :如果此 collection 没有元素,则返回 true。
Iterator
iterator():返回在此 collection 的元素上进行迭代的迭代器。 boolean remove(Object o) :从此 collection 中移除指定元素的单个实例。
int size() :返回此 collection 中的元素数。
Objec[] toArray():返回对象数组
9.6.1概述
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
java.util接口 Map
也叫哈希表、散列表。常用于存 键值对 结构的数据。其中的键不能重复,值可以重复
可以根据键 提取对应的值
键不允许重复,如果重复值会被覆盖
存放的都是无序数据
初始容量是16,默认的加载因子是0.75
void clear()
从此映射中移除所有映射关系(可选操作)。
boolean containsKey(Object key)
如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true。
V get(Object key)
返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
boolean isEmpty()
如果此映射未包含键-值映射关系,则返回 true。
V put(K key, V value)
将指定的值与此映射中的指定键关联(可选操作)。
void putAll(Map extends K,? extends V> m)
从指定映射中将所有映射关系复制到此映射中(可选操作)。
V remove(Object key)
如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
int size()
返回此映射中的键-值映射关系数。
Set
> entrySet() 返回此映射所包含的映射关系的 Set 视图。
HashMap的键要同时重写hashCode()和equals()
hashCode()用来判断确定hash值是否相同
equals()用来判断属性的值是否相同
-- equals()判断数据如果相等,hashCode()必须相同
-- equals()判断数据如果不等,hashCode()尽量不同
10.5.1概述
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。
HashMap底层是一个Entry数组,当存放数据时会根据hash算法计算数据的存放位置。算法:hash(key)%n,n就是数组的长度。
当计算的位置没有数据时,就直接存放,当计算的位置有数据时也就是发生hash冲突的时候/hash碰撞时,采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。
Collections.sort(List<> list):根据元素的自然顺序 对指定列表按升序进行排序。
Collections.max():根据元素的自然顺序,返回给定 collection 的最大元素。
Collections.min():根据元素的自然顺序 返回给定 collection 的最小元素。
Collections.swap(List,i,j):在指定列表的指定位置处交换元素。
Collections.addAll():