我正试图将本Java教程移植到Xojo。我很难打开下面的Set
函数,因为它虽然简短而优雅,但在一个小空间里却包含了大量转换,我不确定我是否正确理解了它。这很困难,因为Java不是我的主要语言,Xojo缺乏对泛型的支持:
public interface GraphNode {
String getId();
}
public class Graph<T extends GraphNode> {
private final Set<T> nodes;
private final Map<String, Set<String>> connections;
public T getNode(String id) {
return nodes.stream()
.filter(node -> node.getId().equals(id))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No node found with ID"));
}
public Set<T> getConnections(T node) {
return connections.get(node.getId()).stream()
.map(this::getNode)
.collect(Collectors.toSet());
}
}
我基本上只能计算出.stream()
方法调用之前发生了什么:
- 获取通过的
node
GraphNode
的Id
- 从密钥与检索到的
Id
匹配的connections
Map
中获取Set<String>
我不明白的是这里发生了什么:
.map(this::getNode).collect(Collectors.toSet())
有人能提供伪代码来解释这一点吗?
它意味着map
、id
到Node
并将其放入(收集(set
this::getNode
翻译为:从这个类中,在id
上使用getNode,这只是.map(id -> getNode(id)).collect(Collectors.toSet())
的语法糖
public T getNode(String id) {
return nodes.stream()
.filter(node -> node.getId().equals(id))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("No node found with ID"));
}
此代码返回节点Set中具有id
的第一个Node,nodes.stream()
.filter(node -> node.getId().equals(id))
将返回一个集合,其中每个节点都将id
作为参数传递,findFirst()
将返回集合中的第一个节点
public Set<T> getConnections(T node) {
return connections.get(node.getId()).stream()
.map(this::getNode)
.collect(Collectors.toSet());
}
由于connections
是映射,connections.get(node.getId())
将使用关键字node.getId()
返回值,然后map(this::getNode)
使用getNode(String id)
将其从id
映射到Node
,最后将其放入set
流基本上为每个循环美化。通常,当您看到XXX.stream()
或返回Stream<XXX>
的方法时,它分别表示"对于XXX
中的每件事"one_answers"对于每个XXX…"。
所以,这里说"对于Set<String>
中的每个字符串…">
map
的意思是"把每一件事都变成另一件事",换句话说,一个变换。对于for循环,它在伪代码中是这样的:
For Each x In set
f(x)
Next x
f
是您传入的函数。在本例中,它是getNode
。
现在,getNode
返回T
,因此我们原始集合中的每个元素都已转换为T
。最后一个调用是collect
,意思是将所有这些元素放回某个集合或其他对象中。在这种情况下,我们将所有这些经过转换的T
放回一个新的Set
中。
伪代码中的整个代码将是:
originalSet = connections.get(node.getId())
newSet = []
For Each x In originalSet
newSet.add(x)
Next x