黑马程序员技术交流社区

标题: 最新笔记 [打印本页]

作者: 黑马★涛仔    时间: 2018-11-26 15:06
标题: 最新笔记
7-10天的笔记

Day - 07
线程间通信 线程池 Lambda表达式

1. 线程间通信
线程间通信:     
多个线程在处理同一个资源, 但是多个线程的处理动作却不相同(线程的任务不同, 需要协调合作)

2. 线程池
普通创建线程方式的缺点:
"创建"线程和"销毁"线程都是比较占用内存和CPU的操作.
对于一些数量多, 执行时间短的任务, 频繁的创建和销毁线程来执行, 会降低程序运行效率.

线程池:
一个容纳多个线程的容器(集合)

线程池可以解决的问题:
  其中的线程可以反复使用, 省去了频繁创建线程对象的操作, 无需反复创建线程而消耗过多资源

2.1 线程池的代码实现
线程池的创建和使用步骤:
1. 使用Executors的静态方法 newFixedThreadPool(int nThreads) 创建线
程池ExecutorService   
2. 创建一个任务类, 实现Runnable接口, 重写run()方法   
3. 调用ExecutorService对象的 submit(Runnable task) 方法, 传递任务给
  线程池, 执行任务  
4. 调用ExecutorService对象的 shutdown() 方法, 销毁线程池 (不建议执行)
3. 函数式编程思想: Lambda表达式
函数式编程的好处:
简化代码编写 (使用 λ Lambda表达式, 简化匿名内部类的代码)

3.1 Lambda标准格式
Lambda表达式的3个部分:
1. 一些参数 ()        
接口中抽象方法的参数列表. 没参数就空着; 有参数就写, 多个参数用逗号分隔   
2. 一个箭头 ->        
将参数传递给方法体   
3. 一段代码 {}        
重写接口抽象方法的方法体
(参数列表) -> {一些重写方法的代码}
(数据类型 变量名, 数据类型 变量名) -> {  一些重写方法的代码 }

4. Lambda省略格式和使用前提
可以省略的部分:
1. (参数列表): 参数"类型"可以省略 (a, b) -> {}        
2. (参数列表): 如果参数只有1个, 则"类型"和"小括号"都可以省略  a -> sout(a)                     3. {一些代码}: 如果只有一条代码, 则"大括号", "return", "分号"都可以"一起省
略"

*函数式接口:
函数式接口: "有且仅有一个抽象方法的接口"

Lambda表达式的使用前提:
1. Lambda只能用于接口, 且"接口中有且仅有一个抽象方法"(也称为"函数式接
口")        普通类, 抽象类不能用   
2. 使用Lambda必须具有上下文推断        
接口中只能有一个抽象方法, 才能推断出来重写的是这个抽象方法Day - 08
File类 递归


1. File类概述

file: 文件   

directory: 目录

path: 路径


2. 绝对路径和相对路径

1. 绝对路径是以盘符开始的

2.相对路径不是盘符开始的,IDEA项目, 相对于项目的根目录

注意事项:

1. 路径是不区分大小写的

2. 路径一般写成字符串,而字符串一个 \是转义,所以需要写两个\\


3. File类: 构造方法

1.   File File(String pathname): 根据 路径字符串 封装一个File对象

2. File File(File parent, String child): 根据 父路径的File对象和子路径 封装File对


3. File File(String parent, String child): 根据 父路径字符串 和 子路径字符串 封装

File对象

                           File f1 = new File("z:\\z.txt");


4.  File类: 获取方法

String getAbsolutePath(): 返回此File的绝对路径名字符串   

  String getPath(): 获取File对象的封装路径 (创建对象时传入的路径)

  String getName(): 获取File对象的文件名或目录名  d:\a\b\c\aaa.txt               

long length(): 获取File表示的"文件"大小的字节byte数 (不能获取目录的大小)


5. File类: 判断方法

boolean exists(): 判断File对象代表的文件或目录是否实际存在

  boolean isDirectory(): 判断File表示的是否为目录         

  boolean isFile(): 判断File表示的是否为文件


6. File类: 创建删除方法

boolean createNewFile(): 当文件不存在时, 创建一个新的空文件

false: 路径已经存在(无论文件还是目录)

抛IO异常: 写的路径不符合逻辑

boolean delete(): 删除由此File表示的文件或目录

删除目录时: 必须是空目录

boolean mkdir(): 创建File表示的目录  "d:\\a\\b\\c\\我的目录"

boolean mkdirs(): 创建File表示的多级目录


7. File类: 遍历目录方法

String[] list(): 获取当前File目录下的所有子文件或目录的名字数组

File[] listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组     


8. 递归

Java中实现递归的方式:     

方法内部调用方法自己

递归时的注意事项:

1. 递归要有限定条件(出口), 保证递归能够停止(就是在某种情况下方法不再调用

自己), 否则会栈内存溢出   

2. 递归次数不能太多, 否则会栈内存溢出   

3. 构造方法不能递归


9. FileFilter文件过滤器的原理和使用

File[] listFiles(FileFilter filter): 返回文件过滤器过滤后的File对象数组   

File[] listFiles(FilenameFilter filter): 返回文件过滤器过滤后的File对象数组

accept(File pathName): true则会将参数的File对象加入返回的File[], false则不

加入


API

File File(String pathname): 根据 路径字符串 封装一个File对象


// 常用获取方法

getAbsolutePath(): 返回此File的绝对路径名字符串   

getPath(): 获取File对象的封装路径 (创建对象时传入的路径)

getName(): 获取File对象的文件名或目录名

length(): 获取File表示的文件大小的字节数 (不能获取目录的大小)

// 常用判断方法

exists(): 判断File对象代表的文件或目录是否实际存在   

isDirectory(): 判断File表示的是否为目录   

isFile(): 判断File表示的是否为文件

// 常用创建删除方法

createNewFile(): 当文件不存在时, 创建一个新的空文件   

delete(): 删除由此File表示的文件或目录. (删除目录时必须是空目录)   

mkdir(): 创建File表示的目录   

mkdirs(): 创建File表示的多级目录

// 常用获取目录中内容的方法

String[] list(): 获取当前File目录下的所有子文件或目录的名字数组

File[] listFiles(): 获取当前File目录中的所有子文件或目录的File对象数组         

File[] listFiles(FileFilter filter): 通过File对象过滤, 返回文件过滤器过滤后的File对

象数组   

File[] listFiles(FilenameFilter filter): 通过File对象的文件名过滤, 返回文件过滤器

过滤后的

FileFilter接口: 用于File对象的过滤器

accept(File pathName): true则会将参数的File对象加入返回的File[], false则不加入

      boolean accept(File dir, String name): true则会将参数的File对象加入返回的

File[], false则 不加入

Day - 09
字节流 字符流 Properties


1. IO流

IO流: 输入(Input)输出(Output)流

流: 数据流

输入: 从硬盘(文件)读取到内存(Java程序)

输出: 从内存(Java程序)写入到硬盘(文件)  

输入流                                                                 输出流

字节流 字节输入流 InputStream                         字节输出流 OutputStream

字符流 字符输入流 Reader                                 字符输出流 Writer


2. 字节流

计算机中, 计算机中一切皆为字节


2.1 字节输出流: OutputStream和FileOutputStream

close() :释放资源

write(int b): 一次写一个字节 (参数int便于传递byte的整数不用强转)

write(byte[] b, int offset, int len): 一次写一个字节数组的一部分

FileOutputStream(String name): 通过文件路径创建文件字节输出流

FileOutputStream(File file): 通过File对象创建文件字节输出流            

构造方法的作用:

1. 创建一个FileOutputStream对象        

2. 根据构造方法传递的路径, 在磁盘上创建一个空文件 ("如果文件存在则会清空

数据")        

3. 将创建的FileOutputStream对象指向这个磁盘上的文件


2.2 字节输出流: 一次写一个字节到文件

使用字节输出流写数据到文件的步骤:

1. 创建对象: 创建FileOutputStream对象, 构造方法中传递文件路径   

2. 写入数据: 使用FileOutputStream对象调用 write(int b) 方法, 将字节写入文件                      

3. 释放资源: 使用FileOutputStream对象调用 close() 方法, 关闭流对象释放资



2.4 字节输出流: 一次写多个字节

byte[] getBytes(): 使用平台的默认字符集将此String编码为byte数组

write(byte[] b): 一次写一个字节数组

write(byte[] b, int off, int len): 一次写一个字节数组的一部分


2.5 字节输出流: 续写, 换行

FileOutputStream(String name, boolean append): 通过文件路径创建流, true可以续写

FileOutputStream(File file, boolean append): 通过File对象创建流, true可以续写

换行符:    

Windows系统: "\r\n"    

Linux系统: "\n"   

MacOS系统: "\r"


2.6 字节输入流: InputStream和FileInputStream

int read(): 一次读一个字节

read(byte[] b): 一次读一个字节数组  

  // 构造方法

FileInputStream(String name): 使用文件路径创建文件字节输入流

FileInputStream(File file): 使用File对象创建文件字节输入流

构造方法的作用:

  1. 创建FileInputStream对象        

  2. 将FileInputStream对象指向磁盘上的文件


2.7 字节输入流: 一次读取一个字节

int read(): 一次读一个字节

读到文件末尾返回-1 (返回int也是为了代码编写方便)

FileInputStream读数据步骤:

1. 创建FileInputStream对象   

2. 使用FileInputStream对象, 调用 int read() 方法, 一次读取一个byte

3. 释放资源     


2.8 字节输入流: 一次一个字节数组       

String(byte[] bytes): 使用平台默认字符集解码将byte数组转换为String   

String(byte[] bytes, int offset, int length): 使用平台默认字符集将数组一部分转换为String

int read(byte[] b): 一次读一个字节数组

// 示例代码

FileInputStream fis = new FileInputStream("模块名\\文件名");

byte[] bytes = new byte[1024];     // 定义字节数组, 用于保存每次读取到的数据

int len;                                            // 定义int变量, 用于保存每次读取到的长度

while ((len = fis.read(bytes)) != -1) {

String s = new String(bytes, 0, len);   // 将读取到的字节转换为字符串, 读到多少个就转换多少个   

System.out.print(s);

}

fis.close();    // 释放资源


2.9 字节流复制图片文件

文件复制的步骤:

1.创建一个字节输入流对象,构造方法中绑定要读取的数据源   

2.创建一个字节输出流对象,构造方法中绑定要写入的目的地   

3.使用字节输入流对象中的方法read读取文件   

4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中   

5.释放资源



GBK编码中, 一个汉字占用2个byte

UTF-8编码中, 一个汉字占用3个byte


3. 字符流

3.1 字符输入流: Reader和FileReader

read(): 一次读一个字符char, 返回读到的字符.

read(char[] cbuf): 一次读取一个字符数组char[]

FileReader(File file): 根据File对象创建文件字符输入流

FileReader(String fileName): 根据File对象创建文件字符输入流

构造方法的作用:    

  1. 创建FileReader对象        

  2. 将FileReader对象指向磁盘上的文件

  

3.2 字符输入流: 2种方式读取文本文件

String(char[] value): 将char数组转换为String   

String(char[] value, int offset, int count): 将char数组的一部分转换为String


3.3 字符输出流: Writer和FileWriter

write(int c): 写一个字符 (int类型为了代码编写方便)

write(char[] cbuf): 写一个字符数组

write(char[] b, int off, int len): 写一个字符数组的一部分

FileWriter(File file): 通过File对象创建文件字符输出流

FileWriter(String fileName): 通过文件路径创建文件字符输出流

  作用:

1. 创建FileWriter对象        

2. 根据构造方法中的路径, 在磁盘上创建文件 ("如果文件已存在, 则清空文件

内容")        

3. 将FileWriter对象指向磁盘上的文件


3.4 字符输出流: 一次写一个字符

write(int c): 写一个字符 (int类型为了代码编写方便)

FileWriter使用步骤:

1.创建FileWriter对象, 构造方法中绑定要写入数据的目的地   

2.使用FileWriter中的方法 write(), 把数据写入到"内存缓冲区"中(字符转换为

字节的过程)   

3.使用FileWriter中的方法 flush(), 把内存缓冲区中的数据,"刷新到文件中"   

4.释放资源 close() (会先把内存缓冲区中的数据刷新到文件中)


3.5 字符输出流: flush与close区别

区别:

flush(): 刷新缓冲区 (将数据从内存中写入到磁盘)   

close(): 刷新缓冲区, 并释放资源. 关闭流后不能再用同一个流对象操作


3.6 字符输出流: 其他方法

write(char[] cbuf): 写一个字符数组

write(char[] b, int off, int len): 写一个字符数组的一部分

write(String str, int off, int len): 写一个字符串的一部分


3.7 字符输出流: 续写, 换行

FileWriter中带有续写功能的构造:

FileWriter(File file, boolean append): 通过File对象创建流. 第二个参数为true可以续

写   

FileWriter(String fileName, boolean append): 通过文件路径创建流. 第二个参数为

true可以续写


4. IO异常处理

IO流的标准格式:

FileWriter fw = null;

try {

//IO流对象的创建, 操作等代码

fw = new FileWriter("d:\\09_IOAndProperties\\g.txt", true);

for (int i = 0; i <10 ; i++) {

fw.write("HelloWorld"+i+"\r\n");

}

} catch (IOException e) {

e.printStackTrace();

} finally {

// 释放资源

if(fw != null){

  try {

fw.close();

} catch (IOException e) {

e.printStackTrace();

}

  }

}


5. Properties集合

  // 构造方法

Properties(): 创建一个Properties集合

// 特有成员方法

setProperty(String key, String value): 保存/替换键值对

getProperty(String key): 通过键获取值. 键不存在返回null

Set<String> stringPropertyNames(): 返回键的集合

store(OutputStream out, String comments): 将集合用字节流写入文件(不能中

文),并写入注释

store(Writer writer, String comments): 将集合用字符流写入文件(可以中文),并写

入注释

load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以中

文)

load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集

合(不能中文)


5.1 Properties: store()存储数据到文件

Properties将数据写入到文件的方法:

store(OutputStream out, String comments): 将集合用字节流写入文件(不

能中文),并写入注释

使用步骤:

1.创建Properties集合对象,添加数据   

2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地   

3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到

硬盘中存储   

4.释放资源


5.2 Properties: load()从文件加载数据到集合

使用步骤:

1.创建Properties集合对象   

2.使用Properties集合对象中的方法load读取保存键值对的文件   

3.遍历Properties集合Day - 10
缓冲流 转换流 序列化流 打印流


1. 缓冲流


1.1 缓冲字节输出流: BufferedOutputStream

// 构造方法

BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流

BufferedOutputStream使用步骤:

1.创建FileOutputStream对象, 构造方法中绑定要输出的目的地

2.创建BufferedOutputStream对象, 构造方法中传递FileOutputStream对象

3.使用BufferedOutputStream对象中的方法 write(), 把数据写入到内部缓冲区

    中  

4.使用BufferedOutputStream对象中的方法 flush(), 把内部缓冲区中的数据,刷

     新到文件中

5.释放资源(会先调用flush方法刷新数据, 第4步可以省略)


FileOutputStream fos = new FileOutputStream("文件路径");

BufferedOutputStream bos = new BufferedOutputStream(fos);        

bos.write("你好".getBytes());   

// bos.flush();  // 可以省略   

bos.close();


1.2 缓冲字节输入流: BufferedInputStream

// 构造方法

BufferedInputStream(InputStream in): 使用基本流创建一个缓冲字节输入流

使用步骤:

1.创建FileInputStream对象, 构造方法中绑定要读取的数据源   

2.创建BufferedInputStream对象, 构造方法中传递FileInputStream对象   

3.使用BufferedInputStream对象中的方法 read(), 读取文件   

4.释放资源 close()


FileInputStream fis = new FileInputStream("文件路径");

BufferedInputStream bis = new BufferedInputStream(fis);

  byte[] bytes = new byte[1024];

int len;

while ((len = bis.read(bytes)) != -1) {

System.out.println(new String(bytes, 0, len));

}

bis.close();


1.3 缓冲字符输出流: BufferedWriter

// 构造方法

       BufferedWriter(Writer out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小

// 特有方法

void newLine(): 写入一个换行符, 换行符自动根据当前系统确定


1.4 缓冲字符输入流: BufferedReader

    // 构造方法

     BufferedReader(Reader in): 使用基本流创建一个缓冲字符输入流

     BufferedReader(Reader in, int size): 使用基本流创建一个缓冲字符输入流, 设置缓冲区大小

    // 特有方法

    String readLine(): 一次读一行字符串, "不包含换行符". 读到文件末尾返回null


2. 转换流


2.1 乱码问题: FileReader读取GBK编码

乱码原因: 读写编码不一致

GBK文件中存储的是"你好"在GBK中对应的byte

而IDEA中使用FileReader读取文件时, 是将byte按照UTF-8编码表查找字符, 结

果找不到, 就显示了问号


2.2 转换流原理: 字符流和转换流的关系

file:///C:/Users/%25E7%25A5%259E%25E5%25A5%2587%25E5%25AE%259D%25E8%25B4%259D/AppData/Local/YNote/data/qqED41ADEF79E33AADEEC40B27412B0329/5a288082c038441fb9948569eea405d3/afe424e4131b4b32a50d77be7ed4cbc6.jpg


2.3 OutputStreamWriter类介绍及使用

// 构造方法

OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流

OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流

// 使用默认UTF-8

OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt"));

o.write("dsfdsfdsaf")

// 使用指定的GBK

InputStreamReader isr = new InputStreamReader(newFileInputStream("a.txt"), "GBK");  

   

3. 序列化流(对象流)

序列化: 内存中的对象转换为字节序列, 以流的方式写入到磁盘的文件中

对象 -> 字节

反序列化: 磁盘文件中的字节序列, 以流的方式读取到内存中变成对象

字节 -> 对象


3.1 对象序列化流: ObjectOutputStream

// 构造方法

ObjectOutputStream(OutputStream out)

// 特有成员方法   

void writeObject(Object obj): 将对象写出

// 创建对象输出流

ObjectOutputStream oos = new ObjectOutputStream(newFileOutputStream("student.txt"));

// 写对象

Student s = new Student("小美女", 18);

oos.writeObject(s);

// 释放资源

oos.close();

注意:

被读写的对象的类必须实现"java.io.Serializable"接口, 否则会抛出"NotSerializableException"


3.2 对象反序列化流: ObjectInputStream

// 构造方法

ObjectInputStream(InputStream in)

// 特有成员方法

Object readObject(): 读取对象

// 创建对象输入流

ObjectInputStream oos = new ObjectInputStream(new FileInputStream("student.txt"));

// 读对象

Object o = oos.readObject();

Student s = (Student)o;

System.out.println(s);

// 释放资源

oos.close();


3.3 transient瞬态关键字: 避免属性序列化

static 修饰的成员变量属于类不属于对象, 所以不能序列化

transient 修饰的成员变量, 不能被序列化


3.4 InvalidClassException异常: 原因和解决方案

serialVersionUID序列号的作用:

序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中.     

该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会发生 变化

当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException



4. 打印流


4.1 打印流PrintStream: 概述和使用

PrintStream特点:

1. 只有输出流, 没有输入流   

2. PrintStream不会抛出IOException   

3. 有特殊方法 print(), println(), 可以输出任意类型的值, 原样输出

  

// 构造方法

  PrintStream(File file): 创建字节打印流, 输出到一个文件   

  PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流

  PrintStream(String fileName): 创建字节打印流, 输出到一个文件路径









欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2