Reputation: 17806
Imagine I have a json like the following:
[
{
field: string,
roles: [
{
id: int,
providedFor: int
},
{
id: int,
providedFor: int
},
...
]
},
{
field: string,
roles: [
{
id: int,
providedFor: int
},
{
id: int,
providedFor: int
},
...
]
},
{
field: string,
roles: [
{
id: int,
providedFor: int
},
{
id: int,
providedFor: int
},
...
]
}
]
And this is parse into a list of objects and call this list providers. How can I go about filtering/streaming this list, find the correct provider then breaking out?
I've tried something like the following:
providers.parallelStream().filter(p -> p.getRoles().parallelStream().filter(r -> r.getProvidedFor.equal("something")).findFirst());
Upvotes: 0
Views: 2890
Reputation: 19211
Since you have not provided any classes I have experimented with the following structure:
class Field {
String field;
List<Role> roles;
Field(String field, List<Role> roles) {
this.field = field;
this.roles = roles;
}
}
class Role {
int id;
int providedFor;
Role(int id, int providedFor) {
this.id = id;
this.providedFor = providedFor;
}
}
Field
is the outer object and Role
is the inner object. So, if you build up a List
of Field
objects like this:
final List<Field> fields = Arrays.asList(
new Field("f11", Arrays.asList(new Role(11, 11), new Role(11, 12))),
new Field("f22", Arrays.asList(new Role(22, 22), new Role(22, 23))),
new Field("f33", Arrays.asList(new Role(33, 33), new Role(33, 34))));
And, you are searching for something
:
int something = 22;
You can filter out your Role
by using the flatMap
method like this:
final Optional<Role> first = fields.stream()
.flatMap(f -> f.roles.stream()) // Chain all "substreams" to one stream
.filter(r -> r.providedFor == something) // Check for the correct object
.findFirst(); // Find the first occurrence
Note that if providedFor
is not a primitive but some kind of Object
the equals
method should be used instead.
If you are instead looking for the Field
class you can simply nest the streams like this:
final Optional<Field> firstField = fields.stream()
.filter(f -> f.roles.stream() // Nested stream
.anyMatch(r -> r.providedFor == something)) // Return true if present
.findFirst(); // Find the first Field object (findAny can be used here as well if "any" hit is ok)
This will return the first Field
that matches the provided Role.providedFor
.
From the flatMap JavaDocs:
Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.
Basically you are chaining nested streams to one stream.
In the end, the findfirst
method returns the first match. This means that there may be no match and therefore an Optional
is returned. The Optional
class has method for retrieving the underlying object and checking if it exists (get()
and isPresent()
). Check out the Optional JavaDocs for more info.
Upvotes: 3