devd
devd

Reputation: 55

Getting a Stream of objects based on value of other member object

I have a Java class of type Project which contains Map of type Process and class Process subsequently contains Map of type Activity.

public class Project {
    private String name;
    private Path path;
    private Map<String, Process> processes;
    //getters and setters
    }

public class Process {
    private String name;
    private String path;
    private Map<String, Activity> activities;
    //getters and setters
    }

public class Activity {
    private String name;
    private String type;
    //getters and setters
    }

I'm trying to write a function which will return a Stream of Process or Process.path where the Process contains at least one activity having type="starter" i.e. Activity.type="starter".

I came up with the below code but it returns a Stream<Activity> whereas what I'm looking for is a Stream<Process> or Stream<String> containing the path.

project.processes.values().stream()
    .flatMap(process -> process.getActivities().values().stream()
            .filter(activity -> "starter".equals(activity.getType())));

What is the most efficient way of doing this?

Upvotes: 2

Views: 151

Answers (2)

Sweeper
Sweeper

Reputation: 271735

Don't use flatMap if you want a Stream<Process> because flatMap will "destroy" information about the processes.

You should create a "nested" stream:

project.getProcesses().values().stream()
        .filter(x -> 
                x.getActivities().values().stream().anyMatch(
                        y -> "starter".equals(y.getType())
                )
        );

Now it's a Stream<Process>.

Upvotes: 2

Markio
Markio

Reputation: 158

The code given will map the processes to activities via the .flatMap operator.

The operator You are looking for is probably .filter if I understand correcly the request of

I'm trying to write a function which will return a Stream of Process or Process.path where the Process contains at least one activity having type="starter" i.e. Activity.type="starter".

project.processes.values().stream()
    .filter(process -> process.getActivities().values().stream()
            .filter(activity -> "starter".equals(activity.getType())).findFirst().isPresent());

You can then map to Project.path via a .map operator. Given the previous operation as processStream, we might write

processStream.map(process -> process.getPath())

It may be worth to note that, if the list of activities may be finite, the .findFirst terminal operation may be substituted for a .count terminal operation. It all depends on the clarity of the code, and the speed requirements of the code.

Upvotes: 1

Related Questions