Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
apachecn-java-zh
提交
9f57fbac
A
apachecn-java-zh
项目概览
OpenDocCN
/
apachecn-java-zh
11 个月 前同步成功
通知
5
Star
53
Fork
13
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
apachecn-java-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9f57fbac
编写于
5月 25, 2021
作者:
W
wizardforcel
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
2021-05-25 21:24:23
上级
5287bfe7
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
29 addition
and
29 deletion
+29
-29
new/java-coding-prob/08.md
new/java-coding-prob/08.md
+5
-5
new/java-coding-prob/09.md
new/java-coding-prob/09.md
+24
-24
未找到文件。
new/java-coding-prob/08.md
浏览文件 @
9f57fbac
...
...
@@ -45,7 +45,7 @@ public class Melon {
假设我们有一个客户——我们叫他马克——他想开一家卖瓜的公司。我们根据他的描述塑造了前面的班级。他的主要目标是拥有一个库存应用来支持他的想法和决策,因此需要创建一个必须基于业务需求和发展的应用。我们将在下面几节中查看每天开发此应用所需的时间。
# 第 1 天(按瓜
类
过滤)
# 第 1 天(按瓜
的类型
过滤)
有一天,马克让我们提供一个功能,可以按瓜的类型过滤瓜。因此,我们创建了一个名为
`Filters`
的实用程序类,并实现了一个
`static`
方法,该方法将瓜列表和要过滤的类型作为参数。
...
...
@@ -95,7 +95,7 @@ public static List<Melon> filterByWeight(
这与
`filterByType()`
类似,只是它有不同的条件/过滤器。作为开发人员,我们开始明白,如果我们继续这样做,
`Filters`
类最终会有很多方法,这些方法只是重复代码并使用不同的条件。我们非常接近一个
*样板代码*
案例。
# 第 3 天(按类型和重量过滤
西
瓜)
# 第 3 天(按类型和重量过滤瓜)
事情变得更糟了。马克现在要求我们添加一个新的过滤器,按类型和重量过滤西瓜,他需要这个很快。然而,最快的实现是最丑陋的。过来看:
...
...
@@ -193,7 +193,7 @@ List<Melon> huge = Filters.filterMelons(
melons
,
new
HugeMelonPredicate
());
```
# 第 5 天(实
施
另外 100 个过滤器)
# 第 5 天(实
现
另外 100 个过滤器)
马克要求我们再安装 100 个过滤器。这一次,我们有足够的灵活性和支持来完成这项任务,但是我们仍然需要为每个选择标准编写 100 个实现
`MelonPredicate`
的策略或类。此外,我们必须创建这些策略的实例,并将它们传递给
`filterMelons()`
方法。
...
...
@@ -300,7 +300,7 @@ Predicate<Melon> predicate = (Melon m)
->
"Watermelon"
.
equalsIgnoreCase
(
m
.
getType
());
```
# 167
简而言之就是兰博达斯
# 167
Lambda 简述
剖析 Lambda 表达式将显示三个主要部分,如下图所示:
...
...
@@ -329,7 +329,7 @@ FilenameFilter filter = new FilenameFilter() {
Lambda 支持行为参数化,这是一个很大的优点(查看前面的问题以获得对此的详细解释)。最后,请记住 Lambda 只能在函数式接口的上下文中使用。
# 168
.
实现环绕执行模式
# 168
实现环绕执行模式
环绕执行模式试图消除围绕特定任务的
*样板*
代码。例如,为了打开和关闭文件,特定于文件的任务需要被代码包围。
...
...
new/java-coding-prob/09.md
浏览文件 @
9f57fbac
# 函数式编程
-
深入研究
# 函数式编程
——
深入研究
本章包括 22 个涉及 Java 函数式编程的问题。这里,我们将重点讨论在流中遇到的涉及经典操作的几个问题(例如,
`filter`
和
`map`
),并讨论无限流、空安全流和缺省方法。这个问题的综合列表将涵盖分组、分区和收集器,包括 JDK12
`teeing()`
收集器和编写自定义收集器。此外,还将讨论
`takeWhile()`
、
`dropWhile()`
、组合函数、谓词和比较器、Lambda 测试和调试以及其他一些很酷的话题。
...
...
@@ -121,7 +121,7 @@ public void testReduceStrings() throws Exception {
}
```
# 178
使用 Lambda 的测试
方法
# 178
测试使用 Lambda 的
方法
让我们从测试一个没有包装在方法中的 Lambda 开始。例如,以下 Lambda 与一个字段关联(用于重用),我们要测试其逻辑:
...
...
@@ -422,7 +422,7 @@ Stream<Integer> unorderedStream = list.stream()
.
unordered
();
```
# 无限序流
# 无限
有
序流
通过
`Stream.iterate(T seed, UnaryOperator<T> f)`
可以得到无限的有序流。结果流从指定的种子开始,并通过将
`f`
函数应用于前一个元素(例如,
`n`
元素是
`f(n-1)`
来继续)。
...
...
@@ -558,7 +558,7 @@ AIW?F1obl3KPKMItqY8>
`Stream.ints()`
comes with two more flavors: one that doesn't take any argument (an unlimited stream of integers) and another that takes a single argument representing the number of values that should be generated, that is,
`ints(long streamSize)`
.
# 无限
序贯
无序流
# 无限
连续
无序流
为了创建一个无限连续的无序流,我们可以依赖于
`Stream.generate(Supplier<? extends T> s)`
。在这种情况下,每个元素由提供的
`Supplier`
生成。这适用于生成恒定流、随机元素流等。
...
...
@@ -596,7 +596,7 @@ List<String> result = passwordStream
213
c1b1c
,
2
badc
$
21
,
d33321d
$
,
@a0dc323
,
3
!
1
aa
!
dc
,
0
a3
##@
3
!,
$
!
b2
#
1
d
@
,
0
@
0
#
dd
$#
,
cb
$
12
d2
@
,
d2
@
@cc@d
```
#
在
谓词返回`true`时执行
# 谓词返回`true`时执行
从 JDK9 开始,添加到
`Stream`
类中最有用的方法之一是
`takeWhile(Predicate<? super T> predicate)`
。此方法具有两种不同的行为,如下所示:
...
...
@@ -768,7 +768,7 @@ List<Integer> result = setOfInts.stream()
映射一个流的元素是一个中间操作,用于将这些元素转换成一个新的版本,方法是将给定的函数应用于每个元素,并将结果累加到一个新的
`Stream`
(例如,将
`Stream<String>`
转换成
`Stream<Integer>`
,或将
`Stream<String>`
转换成另一个
`Stream<String>`
等)。
# 使用
流.map()
# 使用
`Stream.map()`
基本上,我们调用
`Stream.map(Function<? super T,? extends R> mapper)`
对流的每个元素应用
`mapper`
函数。结果是一个新的
`Stream`
。不修改源
`Stream`
。
...
...
@@ -873,7 +873,7 @@ Gac(1500g), Hemi(1100g), Gac(2500g), Apollo(1500g), Horned(1200g)
根据经验,在使用
`peek()`
改变状态之前,要三思而后行。另外,请注意,这种做法是一种辩论,属于不良做法,甚至反模式的保护伞。
# 使用
流.flatMap()
# 使用
`Stream.flatMap()`
正如我们刚才看到的,
`map()`
知道如何在
`Stream`
中包装一系列元素。
...
...
@@ -1000,7 +1000,7 @@ List<String> melons = Arrays.asList(
"Hemi"
,
"Cantaloupe"
,
"Horned"
,
"Hemi"
,
"Hemi"
);
```
#
芬丹
#
`findAny()`
`findAny()`
方法从流中返回任意(不确定)元素。例如,以下代码片段将返回前面列表中的元素:
...
...
@@ -1028,7 +1028,7 @@ String anyApollo = melons.stream()
这一次,结果将是
`nope`
。列表中没有
`Apollo`
,因此
`filter()`
操作将产生一个空流。此外,
`findAny()`
还将返回一个空流,因此
`orElse()`
将返回最终结果作为指定的字符串
`nope`
。
#
首先查找
#
`findFirst()`
如果
`findAny()`
返回任何元素,
`findFirst()`
返回流中的第一个元素。显然,当我们只对流的第一个元素感兴趣时(例如,竞赛的获胜者应该是竞争对手排序列表中的第一个元素),这种方法很有用。
...
...
@@ -2192,7 +2192,7 @@ Java`Stream`API 提供了`filtering()`、`flatMapping()`和`mapping()`,特别
在概念上,
`filtering()`
的目标与
`filter()`
相同,
`flatMapping()`
的目标与
`flatMap()`
相同,
`mapping()`
的目标与
`map()`
相同。
#
筛选()
#
`filtering()`
用户问题:
*我想把所有重 2000 克以上的西瓜都按种类分类。对于每种类型,将它们添加到适当的容器中(每种类型都有一个容器—只需检查容器的标签即可)*
。
...
...
@@ -2256,7 +2256,7 @@ Map<Boolean, Set<Melon>> melonsFiltering = melons.stream()
{
false
=[
Hemi
(
1600
g
),
Hemi
(
2000
g
)],
true
=[
Hemi
(
2600
g
)]}
```
#
映射()
#
`mapping()`
用户问题:
*对于每种类型的甜瓜,我都需要按升序排列的权重列表*
。
...
...
@@ -2292,7 +2292,7 @@ Map<Boolean, Set<String>> melonsMapping = melons.stream()
{
false
=[
Crenshaw
,
Hemi
],
true
=[
Gac
,
Hemi
]}
```
#
平面映射()
#
`flatMapping()`
要快速提醒您如何展开流,建议阅读“映射”部分。
...
...
@@ -2373,7 +2373,7 @@ Map<Boolean, Set<String>> pestsFlatMapping = melonsGrown.stream()
}
```
# 192
发球
# 192
`teeing()`
从 JDK12 开始,我们可以通过
`Collectors.teeing()`
合并两个收集器的结果:
...
...
@@ -2581,7 +2581,7 @@ public class MelonCollector implements
*
`CONCURRENT`
:流中的元素可以由多个线程并发地累加(最终收集器可以对流进行并行归约)。流的并行处理产生的容器组合在单个结果容器中。数据源的性质应该是无序的,或者应该有
`UNORDERED`
标志。
*
`IDENTITY_FINISH`
:表示累加器本身就是最终结果(基本上我们可以将
`A`
强制转换为
`R`
),此时不调用
`finisher()`
。
# 供应
商——供应商
# 供应
者——`Supplier<A> supplier()`
`supplier()`
的任务是(在每次调用时)返回一个空的可变结果容器的
`Supplier`
。
...
...
@@ -2604,7 +2604,7 @@ public Supplier<Map<Boolean, List<Melon>>> supplier() {
在并行执行中,可以多次调用此方法。
# 累积元素
–双消费者
# 累积元素
——`BiConsumer<A, T> accumulator()`
`accumulator()`
方法返回执行归约操作的函数。这是
`BiConsumer`
,这是一个接受两个输入参数但不返回结果的操作。第一个输入参数是当前结果容器(到目前为止是归约的结果),第二个输入参数是流中的当前元素。此函数通过累积遍历的元素或遍历此元素的效果来修改结果容器本身。在我们的例子中,
`accumulator()`
将当前遍历的元素添加到两个
`ArrayList`
之一:
...
...
@@ -2618,7 +2618,7 @@ public BiConsumer<Map<Boolean, List<Melon>>, Melon> accumulator() {
}
```
# 应用最终转换
–函数
# 应用最终转换
——`Function<A, R> finisher()`
`finisher()`
方法返回在累积过程结束时应用的函数。调用此方法时,没有更多的流元素可遍历。所有元素将从中间累积类型
`A`
累积到最终结果类型
`R`
。如果不需要转换,那么我们可以返回中间结果(累加器本身):
...
...
@@ -2631,7 +2631,7 @@ public Function<Map<Boolean, List<Melon>>,
}
```
# 并行化收集器
–二进制运算符
# 并行化收集器
——`BinaryOperator<A> combiner()`
如果流是并行处理的,那么不同的线程(累加器)将生成部分结果容器。最后,这些部分结果必须合并成一个单独的结果。这正是
`combiner()`
所做的。在这种情况下,
`combiner()`
方法需要合并两个映射,将第二个
`Map`
的两个列表中的所有值加到第一个
`Map`
中相应的列表中:
...
...
@@ -2648,7 +2648,7 @@ public BinaryOperator<Map<Boolean, List<Melon>>> combiner() {
}
```
# 返回最终结果–
函数
# 返回最终结果–
`Function<A, R> finisher()`
最终结果用
`finisher()`
方法计算。在这种情况下,我们只返回
`Function.identity()`
,因为累加器不需要任何进一步的转换:
...
...
@@ -2661,7 +2661,7 @@ public Function<Map<Boolean, List<Melon>>,
}
```
# 特征
–设置<characteristics>特征();</characteristics>
# 特征
——`Set<Characteristics> characteristics()`
最后,我们指出我们的收集器是
`IDENTITY_FINISH`
和
`CONCURRENT`
:
...
...
@@ -2793,7 +2793,7 @@ melons.forEach(m -> Melon.growing100g(m));
melons
.
forEach
(
Melon:
:
growing100g
);
```
#
对
实例方法的方法引用
# 实例方法的方法引用
假设我们为
`Melon`
定义了以下
`Comparator`
:
...
...
@@ -2848,7 +2848,7 @@ List<Integer> sorted = melons.stream()
.
collect
(
Collectors
.
toList
());
```
#
对
构造器的方法引用
# 构造器的方法引用
可以通过
`new`
关键字引用构造器,如下所示:
...
...
@@ -2958,7 +2958,7 @@ double result = customThreadPool.submit(
1000
threads
(~
250
ms
)
```
#
分离
器
#
拆分
器
Java
`Spliterator`
接口(也称为
*可拆分迭代器*
)是用于并行遍历源元素(例如,集合或流)的接口。此接口定义以下方法:
...
...
@@ -3217,7 +3217,7 @@ System.out.println(
组合(或链接)函数、谓词和比较器允许我们编写应该统一应用的复合标准。
#
合成
谓词
#
组合
谓词
假设我们有以下
`Melon`
类和
`Melon`
的
`List`
:
...
...
@@ -3295,7 +3295,7 @@ List<Melon> result = melons.stream()
.
collect
(
Collectors
.
toList
());
```
#
合成
比较器
#
组合
比较器
让我们考虑上一节中相同的
`Melon`
类和
`Melon`
的
`List`
。
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录