I'm trying to port this Java tutorial to Xojo. I'm struggling to unpack the Set function below because, whilst short and elegant, it crams a lot of conversions into a small space and I'm not sure if I'm understanding it correctly. It's difficult as Java is not my primary language and Xojo lacks support for generics:
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());
}
}
I basically can only figure what is happening up to the .stream() method call:
- Get the
Idof the passednodeGraphNode - Get the
Set<String>from theconnectionsMapwhose key matches the retrievedId
What I don't understand is what is happening here:
.map(this::getNode).collect(Collectors.toSet())
Can someone provide pseudocode to explain this?
Streams are basically glorified for-each loops. Generally, when you see
XXX.stream()or a method that returns aStream<XXX>, it means "for each thing inXXX" and "For each XXX..." respectively.So, here it says "for each string in the
Set<String>..."mapmeans "turn each thing into something else", in other words, a transformation. With a for loop, it's like this in pseudocode:fis the function that you pass in. In this case, it'sgetNode.Now,
getNodereturnsT, so every element in our original set has been transformed into aT. The last call is acollect, which means to put all these elements back into some collection, or some other object. In this case, we put all these transformedTs back into a newSet.The whole code in pseudocode would be: