flatmap in a composite pattern

133 Views Asked by At

I am learning design patterns and I stumbled upon a task that interested me, but I failed completing it. I have an interface Box, that has two extending class, let's call it Leaf and BoxContainer. I tried doing something like this:

List<Box> boxContainer = new BoxContainer(new Leaf("red","fresh"),
                                                new Leaf("white","dry"),
                                                new Leaf("black","dry"),
                                                new Leaf("green", "fresh"),
                                                new BoxContainer(("red","fresh"),
                                                new Leaf("white","dry"),
                                                new Leaf("black","dry"),
                                                new Leaf("green", "fresh"),)));

and one of the method i implemented needs to flatten the list into one long list, because when i try to sum up the size of the list it gives me 5, not 8 that i expect to get, since there are 8 leafs inside a box - 4 on the outside and another 4 inside the BoxContainer in the BoxContainer. I'm trying to use flatmap because I wanted the method to be able to flatten more than 1 BoxContainer in a BoxContainer, I mean I would like to be able to pass a box in a box in a box in a box and so on, and the flatmap should help me do this as far as i understand. The problem is that when I tried this :

List<Box> getBoxes() {
        List<Box>flat= allBoxes.stream().flatMap(List::stream).collect(Collectors.toList());

the List::stream gives me error "Non-static method cannot be referenced from a static context"

is there any way around it, or is my implementation and simply thinking bad and I should go about it in some other way?

I tried some lambda solutions and I browsed other examples of the problem but didn't find anything i could implement in my own code

@Edit

class BoxContainer implements Box{
     List<Box> allBoxes= new ArrayList<>();
    String color;
    String state;

    public BoxContainer(Box... boxes) {
        allBoxes.addAll(Arrays.asList(boxes));
    }

as for class/interface definitions :

interface Box { String getColor(); String getState(); } 
1

There are 1 best solutions below

5
shmosel On

You need to have nested flatMaps if you want it to be recursive. The simplest way is to provide a method on the Box interface that streams all its nested boxes:

Stream<Leaf> leaves();

On the BoxContainer class, it would iterate over its children:

@Override
Stream<Leaf> leaves() {
    return allBoxes.stream().flatMap(Box::leaves);
}

And the Leaf class just returns itself:

@Override
Stream<Leaf> leaves() {
    return Stream.of(this);
}

Ideone Demo