7

I have these classes

class LivingOrganism
{
    List<Domain> listOfDomain;
}

class Domain
{
    List<Species> listOfSpecies;
}

class Species
{
    List<Color> listOfColor;
}

class Color
{
    String color;
}

From the top to bottom, it won't have any duplicated entries until I reach to color. So some species even if they are in another domain can have the same color. And one single species can have different color.

Given a parent LivingOrganism, I want to filter a listOfDomain with a certain color.

I did it in a classic nested for loop, but with 4 nest for, the code doesn't look pretty. I was trying to use java 8 flatmap and filter to get some more elegant code, but I spent hours without success.

I even made a badly drawn graph in MSPaint

Let's say I want to get List<Species> that can be blue or List<Domain> with all the Species that can be blue. How do I proceed?

Any help would be appreciated

stackyi
  • 95
  • 1
  • 2
  • 7
  • 3
    _"I spent hours without success"_ please [edit] the questions and include your best attempt, then explain why you are stuck, people will be able to give better explanations. Also, please clarify what the expected output should be, a `List` or a `List`, or something else? – Jorn Vernee Jun 16 '17 at 20:52
  • Start with a way to filter Species with certain Color. Using it, find a way to filter Domains by given Species. Once you get the pattern, making more steps into the outer collections will be easy. – 9000 Jun 16 '17 at 21:02
  • 1
    Variable names really shouldn't reflect implementation (`listOf...`). When you realize that, say, a `Species` should not appear more than once in a given `Domain`, you likely will want to implement the collection as a `Set` instead of a `List`, and the name will not match the implementation any more. That's bad. Name variables for their domain purpose, not their implementation. (You might make even more radical changes when you decide a given `Species` should exist in only one `Domain`). – Lew Bloch Jun 16 '17 at 22:32

2 Answers2

6

Try this.

List<Domain> result = livingOrganism.listOfDomain.stream()
    .filter(d -> d.listOfSpecies.stream()
        .flatMap(s -> s.listOfColor.stream())
        .anyMatch(c -> c.equals("blue")))
    .collect(Collectors.toList());
  • This code works perfect for me, but can you explain why we don't need a deep copy for this? Imagine running the code snippets above as method with different colors on the same `livingOrganism` object wouldn't that also modify the original `livingOrganism`? – Wumba Feb 18 '21 at 14:37
3

Your Color btw looks a lot like an enum, probably should make it as such. Also the names of the methods should be listOfDomains, listOfSpecies and listOfColors (notice the s at the end).

 String colorOfIntereset = "red";

 LivingOrganism one = new LivingOrganism...
 List<Domain> domains = one.getListOfDomain()
            .stream()
            .filter(d -> {
                return d.getListOfSpecies()
                        .stream()
                        .flatMap(s -> s.getListOfColor().stream())
                        .anyMatch(c -> c.getColor().equals(colorOfIntereset));
            })
            .collect(Collectors.toList());
Eugene
  • 117,005
  • 15
  • 201
  • 306
  • `Color` is indeed an enum, but for the sake of simplicity, I use a string and a string comparison would do the work :) – stackyi Jun 16 '17 at 21:23