这个 Lambda 表达式的解释
Explanation of this Lambda Expression
我正在创建一个单词比较 class,它也会计算单词的出现次数。 (这是Java)
这是我原来的方法:
/**
* @param map The map of words to search
* @param num The number of words you want printed
* @return list of words
*/
public static List<String> findMaxOccurrence(Map<String, Integer> map, int num) {
List<WordComparable> l = new ArrayList<>();
for (Map.Entry<String, Integer> entry : map.entrySet())
l.add(new WordComparable(entry.getKey(), entry.getValue()));
我的 IDE 建议可以将循环和列表赋值替换为 "collect call": "stream api calls"
它在其中生成了这段代码:
List<WordComparable> l =
map.entrySet().stream()
.map(entry -> new WordComparable
(entry.getKey(), entry.getValue())).collect(Collectors.toList());
我对 lambda 数学的工作原理有点困惑。如果我没记错的话,-> 是 for each 循环,但其他调用完全令人困惑。
我的IDE也可以把代码展开成这两个片段:
List<WordComparable> l =
map.entrySet().stream()
.map(entry -> {
return new WordComparable
(entry.getKey(), entry.getValue());
}).collect(Collectors.toList());
和
List<WordComparable> l =
map.entrySet().stream()
.map(new Function<Map.Entry<String, Integer>, WordComparable>() {
@Override
public WordComparable apply(Map.Entry<String, Integer> entry) {
return new WordComparable
(entry.getKey(), entry.getValue());
}
}).collect(Collectors.toList());
任何光脱落都会很棒。
这是 Function
的 lambda 表达式。它需要一个对象和 returns 一个对象。在这种情况下,它需要一个 Map.Entry<String, Integer>
和 returns 一个 WordComparable
.
entry -> new WordComparable(entry.getKey(), entry.getValue())
您可以手写等效代码:
final class ConversionFunction
implements Function<Map.Entry<String, Integer>, WordComparable>
{
@Override
public WordComparable apply(Map.Entry<String, Integer> entry) {
return new WordComparable(entry.getKey(), entry.getValue());
}
}
map.entrySet().stream().map(new ConversionFunction()).collect(...);
Stream.map()
方法采用可应用于流中每个元素 (Map.Entry
) 的 Function
,并生成新类型的元素流 (WordComparable
).
Stream.collect()
方法使用 Collector
将流的所有元素压缩为单个对象。通常它是一个集合,就像它在这里一样,但它可以是任何类型的聚合函数。
List<WordComparable> l = map.entrySet().stream()
.map(entry -> new WordComparable(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
"->" 是 lambda 本身的一部分。
在此代码段中,.stream() 类似于 foreach 循环,然后开始数据处理集 "directives"(地图、收集等)。
map 意味着您将当前集合的每个元素映射到具有某些规则的某个新集合:
entry -> new WordComparable(entry.getKey(), entry.getValue())
您的规则意味着您使用每个元素(带有 "entry" 别名)为 map() 结果集合创建新元素。
那么你应该收集你的元素,通过使用合适的收集器进行适当的收集。
注意,collect 适用于 map() 结果。
让我们仔细看看for循环,看看我们如何编写它functionally:
List<WordComparable> l = new ArrayList<>();
for (Map.Entry<String, Integer> entry : map.entrySet())
l.add(new WordComparable(entry.getKey(), entry.getValue()));
如果我们用简单的英语阅读该代码,我们可能会说 "for each entry of my map, let's convert it to a WordComparable
and add it to a list"。
现在,我们可以将该句子改写为 "for each entry of my map, let's convert it to a WordComparable
, and when we have converted it all, let's make a list out of it"。
使用这句话,我们看到我们需要创建一个函数:一个获取地图条目并将其转换为 WordComparable
的函数。所以让我们建造一个吧! Java 8引入了一个名为Function
, which has one important method: apply
的新类型。此方法接受一个输入,对其进行转换,然后 return 输出一个。
写好老Java,因为Function
是一个接口,我们可以实现它来编写我们的转换代码:
public class EntryConverter implements Function<Map.Entry<String, Integer>, WordComparable> {
public WordComparable apply(Map.Entry<String, Integer> entry) {
return new WordComparable(entry.getKey(), entry.getValue());
}
}
现在我们有了这个转换器,我们需要在所有条目上使用它。 Java 8 还介绍了 Stream
, that is to say, a sequence of elements (note that this sequence can be infinite). Using this sequence, we can finally write into code what we said earlier, i.e. "for each entry, let's convert it to a WordComparable
". We make use of the map
方法的概念,其目标是对流的每个元素应用一个方法。
我们有方法:EntryConverter
,我们使用 stream
方法构建条目的 Stream
。
所以,我们得到:
map.entrySet().stream().map(new EntryConverter());
剩下的就是句子的最后部分:"make a List
out of it",即将所有的元素汇集成一个List
。这是使用 collect
method. This method takes a Collector
as argument, i.e. an object capable of reducing a stream into a final container. Java 8 comes with a lot of prebuilt collectors; one of them being Collectors.toList()
.
完成的
最后,我们得到:
map.entrySet().stream().map(new EntryConverter()).collect(Collectors.toList());
现在,如果我们删除临时 class EntryConverter
并使其匿名,我们就会得到您的 IDE 的建议:
List<WordComparable> l = map.entrySet()
.stream() //make a Stream of our entries
.map(new Function<Map.Entry<String, Integer>, WordComparable>() {
@Override
public WordComparable apply(Map.Entry<String, Integer> entry) {
return new WordComparable(entry.getKey(), entry.getValue());
}
}) //let's convert each entry to a WordComparable
.collect(Collectors.toList()); //and make a List out of it
现在写那么多代码有点麻烦,尤其是匿名的声明class。 Java 8 使用新的 ->
运算符进行救援。此运算符允许创建 Function
比以前更轻松:左侧对应于函数的参数,右侧对应于结果。这称为 lambda expression.
在我们的例子中,我们得到:
entry -> new WordComparable(entry.getKey(), entry.getValue())
也可以使用块体和 return 语句来编写此 lambda 表达式:
entry -> {
return new WordComparable(entry.getKey(), entry.getValue());
}
注意这与我们之前在 EntryConverter
.
中所写内容的对应关系
这意味着我们可以将代码重构为:
List<WordComparable> l = map.entrySet()
.stream()
.map(entry -> new WordComparable(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
这更具可读性,也是您的 IDE 所建议的。
您可以在 Oracle site.
上找到有关 lambda 表达式的更多信息
我正在创建一个单词比较 class,它也会计算单词的出现次数。 (这是Java)
这是我原来的方法:
/**
* @param map The map of words to search
* @param num The number of words you want printed
* @return list of words
*/
public static List<String> findMaxOccurrence(Map<String, Integer> map, int num) {
List<WordComparable> l = new ArrayList<>();
for (Map.Entry<String, Integer> entry : map.entrySet())
l.add(new WordComparable(entry.getKey(), entry.getValue()));
我的 IDE 建议可以将循环和列表赋值替换为 "collect call": "stream api calls"
它在其中生成了这段代码:
List<WordComparable> l =
map.entrySet().stream()
.map(entry -> new WordComparable
(entry.getKey(), entry.getValue())).collect(Collectors.toList());
我对 lambda 数学的工作原理有点困惑。如果我没记错的话,-> 是 for each 循环,但其他调用完全令人困惑。
我的IDE也可以把代码展开成这两个片段:
List<WordComparable> l =
map.entrySet().stream()
.map(entry -> {
return new WordComparable
(entry.getKey(), entry.getValue());
}).collect(Collectors.toList());
和
List<WordComparable> l =
map.entrySet().stream()
.map(new Function<Map.Entry<String, Integer>, WordComparable>() {
@Override
public WordComparable apply(Map.Entry<String, Integer> entry) {
return new WordComparable
(entry.getKey(), entry.getValue());
}
}).collect(Collectors.toList());
任何光脱落都会很棒。
这是 Function
的 lambda 表达式。它需要一个对象和 returns 一个对象。在这种情况下,它需要一个 Map.Entry<String, Integer>
和 returns 一个 WordComparable
.
entry -> new WordComparable(entry.getKey(), entry.getValue())
您可以手写等效代码:
final class ConversionFunction
implements Function<Map.Entry<String, Integer>, WordComparable>
{
@Override
public WordComparable apply(Map.Entry<String, Integer> entry) {
return new WordComparable(entry.getKey(), entry.getValue());
}
}
map.entrySet().stream().map(new ConversionFunction()).collect(...);
Stream.map()
方法采用可应用于流中每个元素 (Map.Entry
) 的 Function
,并生成新类型的元素流 (WordComparable
).
Stream.collect()
方法使用 Collector
将流的所有元素压缩为单个对象。通常它是一个集合,就像它在这里一样,但它可以是任何类型的聚合函数。
List<WordComparable> l = map.entrySet().stream()
.map(entry -> new WordComparable(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
"->" 是 lambda 本身的一部分。 在此代码段中,.stream() 类似于 foreach 循环,然后开始数据处理集 "directives"(地图、收集等)。
map 意味着您将当前集合的每个元素映射到具有某些规则的某个新集合:
entry -> new WordComparable(entry.getKey(), entry.getValue())
您的规则意味着您使用每个元素(带有 "entry" 别名)为 map() 结果集合创建新元素。 那么你应该收集你的元素,通过使用合适的收集器进行适当的收集。
注意,collect 适用于 map() 结果。
让我们仔细看看for循环,看看我们如何编写它functionally:
List<WordComparable> l = new ArrayList<>();
for (Map.Entry<String, Integer> entry : map.entrySet())
l.add(new WordComparable(entry.getKey(), entry.getValue()));
如果我们用简单的英语阅读该代码,我们可能会说 "for each entry of my map, let's convert it to a WordComparable
and add it to a list"。
现在,我们可以将该句子改写为 "for each entry of my map, let's convert it to a WordComparable
, and when we have converted it all, let's make a list out of it"。
使用这句话,我们看到我们需要创建一个函数:一个获取地图条目并将其转换为 WordComparable
的函数。所以让我们建造一个吧! Java 8引入了一个名为Function
, which has one important method: apply
的新类型。此方法接受一个输入,对其进行转换,然后 return 输出一个。
写好老Java,因为Function
是一个接口,我们可以实现它来编写我们的转换代码:
public class EntryConverter implements Function<Map.Entry<String, Integer>, WordComparable> {
public WordComparable apply(Map.Entry<String, Integer> entry) {
return new WordComparable(entry.getKey(), entry.getValue());
}
}
现在我们有了这个转换器,我们需要在所有条目上使用它。 Java 8 还介绍了 Stream
, that is to say, a sequence of elements (note that this sequence can be infinite). Using this sequence, we can finally write into code what we said earlier, i.e. "for each entry, let's convert it to a WordComparable
". We make use of the map
方法的概念,其目标是对流的每个元素应用一个方法。
我们有方法:EntryConverter
,我们使用 stream
方法构建条目的 Stream
。
所以,我们得到:
map.entrySet().stream().map(new EntryConverter());
剩下的就是句子的最后部分:"make a List
out of it",即将所有的元素汇集成一个List
。这是使用 collect
method. This method takes a Collector
as argument, i.e. an object capable of reducing a stream into a final container. Java 8 comes with a lot of prebuilt collectors; one of them being Collectors.toList()
.
最后,我们得到:
map.entrySet().stream().map(new EntryConverter()).collect(Collectors.toList());
现在,如果我们删除临时 class EntryConverter
并使其匿名,我们就会得到您的 IDE 的建议:
List<WordComparable> l = map.entrySet()
.stream() //make a Stream of our entries
.map(new Function<Map.Entry<String, Integer>, WordComparable>() {
@Override
public WordComparable apply(Map.Entry<String, Integer> entry) {
return new WordComparable(entry.getKey(), entry.getValue());
}
}) //let's convert each entry to a WordComparable
.collect(Collectors.toList()); //and make a List out of it
现在写那么多代码有点麻烦,尤其是匿名的声明class。 Java 8 使用新的 ->
运算符进行救援。此运算符允许创建 Function
比以前更轻松:左侧对应于函数的参数,右侧对应于结果。这称为 lambda expression.
在我们的例子中,我们得到:
entry -> new WordComparable(entry.getKey(), entry.getValue())
也可以使用块体和 return 语句来编写此 lambda 表达式:
entry -> {
return new WordComparable(entry.getKey(), entry.getValue());
}
注意这与我们之前在 EntryConverter
.
这意味着我们可以将代码重构为:
List<WordComparable> l = map.entrySet()
.stream()
.map(entry -> new WordComparable(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
这更具可读性,也是您的 IDE 所建议的。
您可以在 Oracle site.
上找到有关 lambda 表达式的更多信息