提交 74ca454d 编写于 作者: W wizardforcel

2021-05-24 23:32:31

上级 fcef0089
......@@ -372,7 +372,7 @@ Path path3 = Paths.get("D:/learning/packt/JavaModernChallenge.pdf");
在下面的部分中,我们将研究用于比较文件路径的不同方法。
# 路径.equals()
# `Path.equals()`
`path1`等于`path2`吗?或者,`path2`等于`path3`吗?好吧,如果我们通过`Path.equals()`进行这些测试,那么可能的结果将显示`path1`等于`path2`,但`path2`不等于`path3`:
......@@ -400,7 +400,7 @@ boolean path1IsSameFilePath3 = Files.isSameFile(path1, path3);
boolean path2IsSameFilePath3 = Files.isSameFile(path2, path3);
```
# 辞书比较
# 词典比较
如果我们只需要对路径进行词典比较,那么我们可以依赖于`Path.compareTo()`方法(这对于排序很有用)。
......@@ -427,9 +427,9 @@ boolean sw = path1.startsWith("/learning/packt"); // true
boolean ew = path1.endsWith("JavaModernChallenge.pdf"); // true
```
# 134 步行道
# 134 遍历
对于行走(或访问)路径有不同的解决方案,其中一种由 NIO.2API 通过`FileVisitor`接口提供。
对于遍历(或访问)路径有不同的解决方案,其中一种由 NIO.2API 通过`FileVisitor`接口提供。
此接口公开了一组方法,这些方法表示访问给定路径的递归过程中的检查点。通过覆盖这些检查点,我们可以干预这个过程。我们可以处理当前访问的文件/文件夹,并通过`FileVisitResult`枚举决定应该进一步执行的操作,该枚举包含以下常量:
......@@ -1247,7 +1247,7 @@ try (FileChannel fileChannel = (FileChannel.open(chineseFile,
JDK13 准备发布非易失性`MappedByteBuffer`。敬请期待!
# 编写文本文件
# 写入文本文件
对于每个专用于读取文本文件的类/方法(例如,`BufferedReader`和`readString()`),Java 提供其对应的用于写入文本文件的类/方法(例如,`BufferedWriter`和`writeString()`)。下面是通过`BufferedWriter`写入文本文件的示例:
......@@ -1545,7 +1545,7 @@ public static int countOccurrences(Path path, String text, Charset ch)
}
```
# 解决方案基于文件.readAllLines()
# 基于`Files.readAllLines()`的解决方案
如果内存(RAM)对我们来说不是问题,那么我们可以尝试将整个文件读入内存(通过`Files.readAllLines()`并从那里处理它。将整个文件放在内存中支持并行处理。因此,如果我们的硬件可以通过并行处理突出显示,那么我们可以尝试依赖`parallelStream()`,如下所示:
......@@ -1561,9 +1561,9 @@ public static int countOccurrences(Path path, String text, Charset ch)
如果`parallelStream()`没有任何好处,那么我们可以简单地切换到`stream()`。这只是一个基准问题。
# 解决方案基于文件.lines()
# 基于`Files.lines()`的解决方案
我们也可以尝试通过`Files.lines()`利用流。这一次,我们将文件作为一个懒惰的`Stream<String>`来获取。如果我们可以利用并行处理(基准测试显示出更好的性能),那么通过调用`parallel()`方法来并行化`Stream<String>`就非常简单了:
我们也可以尝试通过`Files.lines()`利用流。这一次,我们将文件作为一个懒惰的`Stream<String>`来获取。如果我们可以利用并行处理(基准测试显示出更好的性能),那么通过调用`parallel()`方法来并行化`Stream<String>`就非常简单了:
```java
public static int countOccurrences(Path path, String text, Charset ch)
......@@ -1643,11 +1643,11 @@ public static int countOccurrences(Path path, String text)
这个解决方案非常快,因为文件直接从操作系统的内存中读取,而不必加载到 JVM 中。这些操作在本机级别进行,称为操作系统级别。请注意,此实现仅适用于 UTF-8 字符集,但也可以适用于其他字符集。
# 141 将 JSON/CSV 文件作为对象读取
# 141 将 JSON/CSV 文件读取为对象
如今,JSON 和 CSV 文件无处不在。读取(反序列化)JSON/CSV 文件可能是一项日常任务,通常位于业务逻辑之前。编写(序列化)JSON/CSV 文件也是一项常见的任务,通常发生在业务逻辑的末尾。在读写这些文件之间,应用将数据用作对象。
# 将 JSON 文件作为对象读/写
# 将 JSON 文件读/写为对象
让我们从三个文本文件开始,它们代表典型的类似 JSON 的映射:
......@@ -2070,11 +2070,11 @@ try (BufferedWriter bw = Files.newBufferedWriter(tmpFile,
此解决方案可用于任何文件。它不是针对临时资源的。
# 143 筛选文件
# 143 过滤文件
从`Path`中过滤文件是一项非常常见的任务。例如,我们可能只需要特定类型的文件、具有特定名称模式的文件、今天修改的文件等等。
# 过滤通过文件.newDirectoryStream()
# 通过`Files.newDirectoryStream()`过滤
不需要任何类型的过滤器,我们可以通过`Files.newDirectoryStream(Path dir)`方法轻松地循环文件夹的内容(一层深)。此方法返回一个`DirectoryStream<Path>`,这是一个对象,我们可以使用它来迭代目录中的条目:
......@@ -3027,7 +3027,7 @@ JDK10 中引入了支持字符集的`Scanner`构造器。
我们来看看`Scanner``BufferedReader`的区别。
# 扫描器与缓冲阅读器
# 扫描器与`BufferedReader`
那么,我们应该使用`Scanner`还是`BufferedReader`?好吧,如果我们需要解析这个文件,那么`Scanner`就是最好的方法,否则`BufferedReader`更合适,对它们进行一个正面比较,会发现:
......
......@@ -395,7 +395,7 @@ private static boolean evenBetween0And10(int value) {
在这个问题的第一部分,我们将讨论无限流。在第二部分中,我们将讨论`takeWhile()``dropWhile()`api。
无限流是无限期地创建数据的流。因为流是懒惰的,它们可以是无限的。更准确地说,创建无限流是作为中间操作完成的,因此在执行管道的终端操作之前,不会创建任何数据。
无限流是无限期地创建数据的流。因为流是懒惰的,它们可以是无限的。更准确地说,创建无限流是作为中间操作完成的,因此在执行管道的终端操作之前,不会创建任何数据。
例如,下面的代码理论上将永远运行。此行为由`forEach()`终端操作触发,并由缺少约束或限制引起:
......@@ -1600,7 +1600,7 @@ long numberOfWords = Stream.of(str)
.count();
```
但是让我们看看我们的流里有多少重 3000 磅的`Melon`
但是让我们看看我们的流里有多少重 3000 磅的`Melon`
```java
long nrOfMelon = melons.stream()
......
......@@ -10,7 +10,7 @@
* 使用反射
* Java 函数式编程使用:
* Lambda 表达式
*
*
* 从 Java 调用脚本
# 我的业务订单
......@@ -747,7 +747,7 @@ sort.setComparator((var a, var b) -> {
当我们想将函数作为参数传递时,Lambda 表达式非常方便。方法声明处参数类型的声明应为函数式接口类型。这些接口可以选择使用`@FunctionalInterface`进行注释。Java 运行时在`java.util.function`包中定义了许多这样的接口。我们将在下一节讨论其中的一些,以及它们在流中的使用。对于其余部分,标准 Java 文档可从 Oracle 获得。
#
# 流
流在 Java8 中也是新的,就像 Lambda 表达式一样。他们一起工作非常强烈,所以他们的出现在同一时间并不令人惊讶。Lambda 表达式以及流都支持函数式编程风格。
......@@ -755,7 +755,7 @@ sort.setComparator((var a, var b) -> {
流支持对多个数据执行相同的计算。该结构称为**单指令多数据****SIMD**)。别害怕这个表情。这是一件非常简单的事情。这本书我们已经做了很多次了。循环也是一种 SIMD 结构。当我们循环检查类以查看其中是否有一个反对该顺序时,我们对每个和每个检查程序执行相同的指令。多个检查器意味着多个数据。
循环的一个问题是,我们定义了不需要的执行顺序。在跳棋的情况下,我们并不关心跳棋的执行顺序。我们关心的是,所有人都同意这个命令。在编程循环时,我们仍然指定一些顺序。这来自循环的本质,我们无法改变这一点。他们就是这样工作的。然而,如果我们能,不知何故,说“对每个检查者做这个和那个”,那就太好了。这就是流发挥作用的地方。
循环的一个问题是,我们定义了不需要的执行顺序。在跳棋的情况下,我们并不关心跳棋的执行顺序。我们关心的是,所有人都同意这个命令。在编程循环时,我们仍然指定一些顺序。这来自循环的本质,我们无法改变这一点。他们就是这样工作的。然而,如果我们能,不知何故,说“对每个检查者做这个和那个”,那就太好了。这就是流发挥作用的地方。
另一点是,使用循环的代码更重要,而不是描述性的。当我们阅读循环构造的程序时,我们将重点放在各个步骤上。我们首先看到循环中的命令是做什么的。这些命令作用于数据的单个元素,而不是整个集合或数组。
......@@ -1056,7 +1056,7 @@ public boolean isConsistent(Order order) {
}
```
因为您已经学习了大多数重要的流方法,所以这里几乎没有什么新问题。我们可以提到`anyMatch()`方法,如果至少有一个元素,则返回`true`,这样传递给`anyMatch()``Predicate`参数就是`true`。它可能还需要一些住宿,这样我们就可以使用另一条溪流中的一条溪流。这很可能是一个例子,当一个流表达式过于复杂,需要使用局部变量分解成更小的片段。
因为您已经学习了大多数重要的流方法,所以这里几乎没有什么新问题。我们可以提到`anyMatch()`方法,如果至少有一个元素,则返回`true`,这样传递给`anyMatch()``Predicate`参数就是`true`。它可能还需要一些住宿,这样我们就可以使用另一条流中的一条流。这很可能是一个例子,当一个流表达式过于复杂,需要使用局部变量分解成更小的片段。
最后,在离开函数样式之前,我们重写了`CheckHelper`类中的`containsOneOf()`方法。这不包含新元素,将帮助您检查您对`map()``filter()``flatMap()``Collector`的了解。请注意,如我们所讨论的,如果`order`至少包含一个以字符串形式给出的订单 ID,则此方法返回`true`
......
......@@ -353,7 +353,7 @@ System.out.println("'" + StringUtils.trimToEmpty(" ") + "'"); // ''
# I/O 流
任何软件系统都必须接收和生成某种数据,这些数据可以组织为一组独立的输入/输出或数据流。流可以是有限的,也可以是无穷无尽的。一个程序可以从一个流中读取(然后称为一个**输入流**),或者写入一个流(然后称为一个**输出流**)。java I/O 流要么基于字节,要么基于字符,这意味着它的数据要么被解释为原始字节,要么被解释为字符。
任何软件系统都必须接收和生成某种数据,这些数据可以组织为一组独立的输入/输出或数据流。流可以是有限的,也可以是无穷无尽的。一个程序可以从一个流中读取(然后称为一个**输入流**),或者写入一个流(然后称为一个**输出流**)。java I/O 流要么基于字节,要么基于字符,这意味着它的数据要么被解释为原始字节,要么被解释为字符。
`java.io`包包含支持许多(但不是所有)可能数据源的类。它主要围绕文件、网络流和内部内存缓冲区的输入来构建。它不包含许多网络通信所必需的类。它们属于 Java 网络 API 的`java.net``javax.net`等包。只有在建立了网络源或目的地(例如网络套接字)之后,程序才能使用`java.io`包的`InputStream``OutputStream`类读写数据
......
......@@ -121,7 +121,7 @@ public class CheckEligibility {
一开始,这个参数设置似乎很复杂,很难理解。更合乎逻辑的做法是返回提供`StackFrame`对象的`Stream`,而不是强制调用者定义一个将其作为参数的函数。
示例代码使用 Lambda 表达式将函数定义为`walk()`方法的参数。Lambda 表达式的参数是流。因为这个流的第一个元素是实际的调用,所以我们放弃它。因为如果调用方不符合条件,也应该拒绝这些调用,即使对`hello()`方法的调用是通过库中已经存在的其他类和方法进行的,所以我们从框架中删除属于`CheckEligibility`类包中类的所有元素。这个包是`packt.java9.deep.stackwalker.myrestrictivelibrary`,在代码中,这个字符串存储在`packageName`字段中。结果流只包含来自库外部的`StackFrame`对象。我们把这些也扔下去,直到流耗尽,或者直到我们发现`StackFrame`又属于图书馆。如果所有的元素都消失了,我们就好了。在这种情况下,`count()`的结果为零。如果我们在`StackFrame`中找到一个属于库的类,这意味着外部代码是从库中调用的,在这种情况下,我们必须拒绝工作。在这种情况下,变量`eligible`将是`false`,我们抛出一个异常,如下面的屏幕截图所示:
示例代码使用 Lambda 表达式将函数定义为`walk()`方法的参数。Lambda 表达式的参数是流。因为这个流的第一个元素是实际的调用,所以我们放弃它。因为如果调用方不符合条件,也应该拒绝这些调用,即使对`hello()`方法的调用是通过库中已经存在的其他类和方法进行的,所以我们从框架中删除属于`CheckEligibility`类包中类的所有元素。这个包是`packt.java9.deep.stackwalker.myrestrictivelibrary`,在代码中,这个字符串存储在`packageName`字段中。结果流只包含来自库外部的`StackFrame`对象。我们把这些也扔下去,直到流耗尽,或者直到我们发现`StackFrame`又属于图书馆。如果所有的元素都消失了,我们就好了。在这种情况下,`count()`的结果为零。如果我们在`StackFrame`中找到一个属于库的类,这意味着外部代码是从库中调用的,在这种情况下,我们必须拒绝工作。在这种情况下,变量`eligible`将是`false`,我们抛出一个异常,如下面的屏幕截图所示:
![](img/8da943bd-0406-4257-8bcb-2707259cb2a4.png)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册