0

I'm having some trouble dealing with streams. Essentially, I have a Map<Integer, Bucket> and each Bucket has a Set<Node>. What I want to do is return a List<Node> containing all of the nodes in all of the buckets. At the moment, I'm visiting all buckets with a for loop and, for each bucket, I'm appending all of the nodes to a List, as shown bellow.

public static synchronized List<Node> getNodes() {
        List<Node> nodes = new ArrayList<>();
        Collection<Bucket> bucketCollection = buckets.values();
        for (Bucket b : bucketCollection) {
            for (Node n : b.getNodes()) {
                nodes.add(n);
            }
        }
        return nodes;
    }

This is working and doing what it is supposed to do. However, I'm having some trouble rewriting this function using streams. I've tried the following code but it is not working because it is returning a List<Set<Node>> instead of List<Node>.

public static synchronized List<Node> getNodes() {
        return buckets.values().stream()
                .map(Bucket::getNodes)
                .collect(Collectors.toList());
    }

This being said, after the map, I have a Stream<Set<Node>>, but I need to have a Stream<Node> before calling collect(Collectors.toList()). How can I do this?

Rui
  • 31
  • 2

1 Answers1

2

map turns one 'thingie' into another 'thingie. 1 thing becomes 1 thing. This is not what you want here; you want 1 thing to turn into 0 to many things. The method you're looking for to do this, is flatMap.

return buckets.values().stream()
  .map(Bucket::getNodes)
  .flatMap(Set::stream)
  .collect(Collectors.toList())
  ;
shmosel
  • 49,289
  • 6
  • 73
  • 138
rzwitserloot
  • 85,357
  • 5
  • 51
  • 72