4

I have following situation, where two neighborhood objects and same street but different houses.

i am wondering using stream how can i group into one neighborhood object

in summary i have following data

Neighborhood: n11
streets: s11
houses: h1

Neighborhood: n11
streets: s11
houses: h2

and i want to merge it to display like as following

Neighborhood: n11
streets: s11
houses: h1,h2

code as follows

public class Neighborhood{
    public UUID id;
    public List<Street> streets;

    public Neighborhood(UUID id, List<Street> streets)
    {
        this.id=id;
        this.streets=streets;
    }
}

public class Streets
{
    public UUID id;
    public List<House> houses;

    public Streets(UUID id, List<House> houses)
    {
        this.id=id;
        this.houses=houses
    }
}

public class House
{
    public UUID id;

    public House(id)
    {
        this.id=id;
    }
}

House h1= new House("h11")
Street s1= new Street("s11", asList(h1))
Neighborhood n1 = new Neighborhood("n11", asList(s1));

House h2= new House("h12")
Street s2= new Street("s11", asList(h2))
Neighborhood n2 = new Neighborhood("n11", asList(s2));
4
  • try to explain with some minimum input and output example Commented Feb 1, 2019 at 20:02
  • I just tried writing this code and... it's insanely un-readable if I understood you correctly. I wish you would show us your attempts without streams Commented Feb 1, 2019 at 20:14
  • in essence, think about it: first there would be a Collectors.toMap( Neighborhood::getId, Function.identity(), (left, right) -> {merge two neighborhood}... but this merge is quite a beast. you would have to collect again to a Map so that you end up with a Map<String, List<String>> where Key is Street::id and Value is a List of House ids's and from that build a Neighborhood back... Commented Feb 1, 2019 at 20:19
  • i have updated the question may be it will help now Commented Feb 1, 2019 at 20:19

2 Answers 2

1

Well, you could build a Map<String, Map<String, List<String>>>, where key is Neighborhood::id and value is a Map that has key as Street::id and value a List of House::id. From here building it back to whatever you want is left an exercise to you...

Map<String, Map<String, List<String>>> map = new HashMap<>();

    neighborhoods.forEach(neighborhood -> {

        Map<String, List<String>> m = map.computeIfAbsent(neighborhood.getId(), (key) -> new HashMap<>());
        neighborhood.getStreets()
                    .forEach(street -> {
                        m.merge(street.getId(),
                                street.getHouses()
                                      .stream()
                                      .map(House::getId)
                                      .collect(Collectors.toCollection(ArrayList::new)),
                                (oldV, newV) -> {
                                    oldV.addAll(newV);
                                    return oldV;
                                }
                        );
                    });
    });
Sign up to request clarification or add additional context in comments.

Comments

0

I had to change the code you provided a little:

import java.util.List;

public class Neighborhood {
    public String id;
    public List<Street> streets;

    public Neighborhood(String id, List<Street> streets) {
        this.id = id;
        this.streets = streets;
    }
}

class Street {

    public Street(String id, List<House> houses) {
        this.id = id;
        this.houses = houses;
    }

    public String id;
    public List<House> houses;
}

class House {
    public String id;

    public House(String id) {
        this.id = id;
    }
}

Here is my answer then:

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {

    public static void main(String[] args) {
        House h1 = new House("h11");
        Street s1 = new Street("s11", Arrays.asList(h1));


        House h2 = new House("h12");
        Street s2 = new Street("s11", Arrays.asList(h2));

        Neighborhood n1 = new Neighborhood("n11", Arrays.asList(s1));
        Neighborhood n2 = new Neighborhood("n11", Arrays.asList(s2));

        Set<Street> collect = Stream.of(n1, n2).flatMap(neighborhood -> neighborhood.streets.stream())
                                          .collect(Collectors.toSet());

        System.out.println(collect);

        final Map<String, List<Street>> collect1 = collect.stream().collect(Collectors.groupingBy(street -> street.id));

        final List<Neighborhood> neighborhoods = new ArrayList<>();

        collect1.forEach((s, streets) -> {
            final List<House> collect2 = streets.stream().flatMap(street -> street.houses.stream())
                                                .collect(Collectors.toList());
            final Street street = new Street(s, collect2);
            neighborhoods.add(new Neighborhood(s, Arrays.asList(street)));
        });
    }
}

1 Comment

you at least assume that Street implements hashCod/equals, but there are other pieces of code that look weird. try to add this House h3 = new House("h13"); Street s3 = new Street("s13", Arrays.asList(h3));Neighborhood n3 = new Neighborhood("n11", Arrays.asList(s3));.. how many neighborhoods will you get?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.