javaxojo

Can someone unpack this very terse Java function into a more verbose example?


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:

  1. Get the Id of the passed node GraphNode
  2. Get the Set<String> from the connections Map whose key matches the retrieved Id

What I don't understand is what is happening here:

.map(this::getNode).collect(Collectors.toSet())

Can someone provide pseudocode to explain this?


Solution

  • Streams are basically glorified for-each loops. Generally, when you see XXX.stream() or a method that returns a Stream<XXX>, it means "for each thing in XXX" and "For each XXX..." respectively.

    So, here it says "for each string in the Set<String>..."

    map means "turn each thing into something else", in other words, a transformation. With a for loop, it's like this in pseudocode:

    For Each x In set
        f(x)
    Next x
    

    f is the function that you pass in. In this case, it's getNode.

    Now, getNode returns T, so every element in our original set has been transformed into a T. The last call is a collect, which means to put all these elements back into some collection, or some other object. In this case, we put all these transformed Ts back into a new Set.

    The whole code in pseudocode would be:

    originalSet = connections.get(node.getId())
    newSet = []
    For Each x In originalSet
        newSet.add(x)
    Next x