第十章笔记
十二、Java 8新增的Predicate操作Collection集合
使用 Predicate 可以充分简化集合的运算,假设依然有上面程序所示的 objs 集合,如果程序有如下三个统计需求: 1、统计集合中出现“C语言中文网”字符串的数量。 2、统计集合中出现“Java”字符串的数量。 3、统计集合中出现字符串长度大于 12 的数量。
十三、Java 8新增的Stream操作Collection集合
独立使用 Stream 的步骤如下: 1、使用 Stream 或 XxxStream 的 builder() 类方法创建该 Stream 对应的 Builder。 2、重复调用 Builder 的 add() 方法向该流中添加多个元素。 3、调用 Builder 的 build() 方法获取对应的 Stream。 4、调用 Stream 的聚集方法。
Stream 提供了大量的方法进行聚集操作,这些方法既可以是“中间的”(intermediate),也可以是 "末端的"(terminal)。 中间方法:中间操作允许流保持打开状态,并允许直接调用后续方法。上面程序中的 map() 方法就是中间方法。中间方法的返 回值是另外一个流。 末端方法:末端方法是对流的最终操作。当对某个 Stream 执行末端方法后,该流将会被“消耗”且不再可用。上面程序中的 sum()、count()、average() 等方法都是末端方法。
除此之外,关于流的方法还有如下两个特征。 有状态的方法:这种方法会给流增加一些新的属性,比如元素的唯一性、元素的最大数量、保证元素以排序的方式被处理等。有 状态的方法往往需要更大的性能开销。 短路方法:短路方法可以尽早结束对流的操作,不必检查所有的元素。
十四、泛型
前面我们提到 Java 集合有个缺点,就是把一个对象“丢进”集合里之后,集合就会“忘记”这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了 Object 类型(其运行时类型没变)。
Java 集合之所以被设计成这样,是因为集合的设计者不知道我们会用集合来保存什么类型的对象,所以他们把集合设计成能保存任何类型的对象,只要求具有很好的通用性,但这样做带来如下两个问题: 1、集合对元素类型没有任何限制,这样可能引发一些问题。例如,想创建一个只能保存 Dog 对象的集合,但程序也可以轻易地 将 Cat 对象“丢”进去,所以可能引发异常。 2、由于把对象“丢进”集合时,集合丢失了对象的状态信息,集合只知道它盛装的是 Object,因此取出集合元素后通常还需要进 行强制类型转换。这种强制类型转换既增加了编程的复杂度,也可能引发 ClassCastException 异常。
I/O 流
一、流的概念
在 Java 中所有数据都是使用流读写的。流是一组有序的数据序列,将数据从一个地方带到另一个地方。根据数据流向的不同,可以分为输入(Input)流和输出(Output)流两种。
1、什么是输入/输出流
输入就是将数据从各种输入设备(包括文件、键盘等)中读取到内存中,输出则正好相反,是将数据写入到各种输出设备(比如文件、显示器、磁盘等)。例如键盘就是一个标准的输入设备,而显示器就是一个标准的输出设备,但是文件既可以作为输入设备,又可以作为输出设备。
数据流是 Java 进行 I/O 操作的对象,它按照不同的标准可以分为不同的类别。 1、按照流的方向主要分为输入流和输出流两大类。 2、数据流按照数据单位的不同分为字节流和字符流。 3、按照功能可以划分为节点流和处理流。
2、输入流
Java 流相关的类都封装在 java.io 包中,而且每个数据流都是一个对象。所有输入流类都是 InputStream 抽象类(字节输入流)和 Reader 抽象类(字符输入流)的子类。其中 InputStream 类是字节输入流的抽象类,是所有字节输入流的父类,
3、输出流
在 Java 中所有输出流类都是 OutputStream 抽象类(字节输出流)和 Writer 抽象类(字符输出流)的子类。其中 OutputStream 类是字节输出流的抽象类,是所有字节输出流的父类,
二、系统流
System.in:标准输入流,默认设备是键盘。 System.out:标准输出流,默认设备是控制台。 System.err:标准错误流,默认设备是控制台。
四、File类(文件操作类)
1、File类简介
File 类不能访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流。
File 类提供了如下三种形式构造方法。 File(String path):如果 path 是实际存在的路径,则该 File 对象表示的是目录;如果 path 是文件名,则该 File 对象表示的是文 件。 File(String path, String name):path 是路径名,name 是文件名。 File(File dir, String name):dir 是路径对象,name 是文件名。
File 类中有以下两个常用常量: public static final String pathSeparator:指的是分隔连续多个路径字符串的分隔符,Windows 下指;。例如 java -cp test.jar;abc.jar HelloWorld。 public static final String separator:用来分隔同一个路径字符串中的目录的,Windows 下指/。例如 C:/Program Files/Common Files。
5、遍历目录
通过遍历目录可以在指定的目录中查找文件,或者显示所有的文件列表。File 类的 list() 方法提供了遍历目录功能,该方法有如下两种重载形式。
1. String[] list()
该方法表示返回由 File 对象表示目录中所有文件和子目录名称组成的字符串数组,如果调用的 File 对象不是目录,则返回 null。
提示:list() 方法返回的数组中仅包含文件名称,而不包含路径。但不保证所得数组中的相同字符串将以特定顺序出现,特别是不保证它们按字母顺序出现。
2. String[] list(FilenameFilter filter)
该方法的作用与 list() 方法相同,不同的是返回数组中仅包含符合 filter 过滤器的文件和目录,如果 filter 为 null,则接受所有名称。
五、RandomAccessFile类
1、动态读取文件内容
所谓动态读取是指从文件的任意位置开始访问文件,而不是必须从文件开始位置读取到文件末尾。动态读取需要用到 Java 中的 RandomAccessFile 类。
RandomAccessFile 类的构造方法有如下两种重载形式。
1、RandomAccessFile(File file, String mode):访问参数 file 指定的文件,访问形式由参数 mode 指定,mode 参数有两个常用的可选值 r 和 rw,其中 r 表示只读,rw 表示读写。
2、RandomAccessFile(String name, String mode):访问参数 name 指定的文件,mode 参数的含义同上。
注意:如果使用 rw 方式声明 RandomAccessFile 对象时,要写入的文件不存在,系统将自动进行创建。
RandomAccessFile 是 Java 输入/输出流体系中功能最丰富的文件内容访问类,
它提供了众多的方法来访问文件内容,它既可以读取文件内容,也可以向文件输出数据。
由于 RandomAccessFile 可以从任意位置访问文件,所以在只需要访问文件部分内容的情况下,
使用 RandomAccessFile 类是一个很好的选择
RandomAccessFile类提供了两个构造方法:
RandomAccessFile(File file, String mode)
其中file表示文件对象,mode表示文档的属性(常用属性有r:只读模式,w:只写模式, rw:可读可写模式)
RandomAccessFile(String path, String mode)其中path表示文件所在路径,mode表示文档的属性(常用属性有r:只读模式,w:只写模式,rw:可读可写模式)
注意:当指定路径下文件不存在,则会创建改文件对象
六、字节流的使用
InputStream 是 Java 所有字节输入流类的父类,OutputStream 是 Java 所有字节输出流类的父类,它们都是一个抽象类,因此继承它们的子类要重新定义父类中的抽象方法。
下面首先介绍上述两个父类提供的常用方法,然后介绍如何使用它们的子类输入和输出字节流,包括 ByteArrayInputStream 类、ByteArrayOutputStream 类、FileInputStream 类和 FileOutputStream 类。
1、字节输入流
InputStream 类及其子类的对象表示字节输入流,InputStream 类的常用子类如下。 ByteArrayInputStream 类:将字节数组转换为字节输入流,从中读取字节。 FileInputStream 类:从文件中读取数据。 PipedInputStream 类:连接到一个 PipedOutputStream(管道输出流)。 SequenceInputStream 类:将多个字节输入流串联成一个字节输入流。 ObjectInputStream 类:将对象反序列化。
2、字节输出流
OutputStream 类及其子类的对象表示一个字节输出流。OutputStream 类的常用子类如下。 ByteArrayOutputStream 类:向内存缓冲区的字节数组中写数据。 FileOutputStream 类:向文件中写数据。 PipedOutputStream 类:连接到一个 PipedlntputStream(管道输入流)。 ObjectOutputStream 类:将对象序列化。
3、字节数组输入流
ByteArrayInputStream 类可以从内存的字节数组中读取数据,该类有如下两种构造方法重载形式。
1、ByteArrayInputStream(byte[] buf):创建一个字节数组输入流,字节数组类型的数据源由参数 buf 指定。
2、ByteArrayInputStream(byte[] buf,int offse,int length):创建一个字节数组输入流,其中,参数 buf 指定字节数组类型的数据源,offset 指定在数组中开始读取数据的起始下标位置,length 指定读取的元素个数。
4、字节数组输出流
ByteArrayOutputStream 类可以向内存的字节数组中写入数据,该类的构造方法有如下两种重载形式。 1、ByteArrayOutputStream():创建一个字节数组输出流,输出流缓冲区的初始容量大小为 32 字节。 2、ByteArrayOutputStream(int size):创建一个字节数组输出流,输出流缓冲区的初始容量大小由参数 size 指定。
ByteArrayOutputStream 类中除了有前面介绍的字节输出流中的常用方法以外,还有如下两个方法。 1、intsize():返回缓冲区中的当前字节数。 2、byte[] toByteArray():以字节数组的形式返回输出流中的当前内容。
5、文件输入流
FileInputStream 是 Java 流中比较常用的一种,它表示从文件系统的某个文件中获取输入字节。通过使用 FileInputStream 可以访