Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search list with Java Stream using multiple filters

I have a List of Java Objects (assume getters and setters):

Record(String name, String part, String value);

I need to return a boolean for if the list contains a certain name value and a certain part value.

I have it working for one filter at a time:

//assume records are added to this list
List<Record> masterList = new ArrayList<Record>();

boolean check = masterList.stream().map(Record::getName).filter(record.getName()::equals).findFirst().isPresent();

But I get error Non-static method cannot be referenced from a static context on Record::getPart for this attempt:

masterList.stream().map(Record::getName).filter(record.getName()::equals).map(Record::getPart).filter(record.getPart()::equals).findFirst().isPresent();
like image 207
Drew13 Avatar asked Jan 10 '19 23:01

Drew13


People also ask

Can we use multiple filters in stream?

The Stream API allows chaining multiple filters. We can leverage this to satisfy the complex filtering criteria described. Besides, we can use the not Predicate if we want to negate conditions.

Can we have multiple filter in stream Java?

More filters can be applied in a variety of methods, such using the filter() method twice or supplying another predicate to the Predicate.

How do you do multiple operations on a stream?

The correct approach would be to use . map() which, like the name says, maps one value to another. In your case the first operation you want to do is to map a Person to a JSONObject. The second operation is a reducer function where you want to reduce all JSONObjects to one JSONArray object.

Which methods can you use to filter and slice a stream in Java 8 +?

Streams Filtering & Slicing Basics: Java 8 Streams support declarative filtering out of elements along with the ability to slice-off portions of a list. Streams support four operations to achieve this – filter() , distinct() , limit(n) and skip(n) .


1 Answers

What you're attempting to do is just not possible i.e. when you perform map(Record::getName) you have a Stream<String> where all the strings are the record names and any chained method calls after that is based only upon the record names.

instead just use a single filter:

boolean check = masterList.stream()
                           .filter(s -> s.getName().equals(record.getName()) &&
                                        s.getPart().equals(record.getPart()))
                           .findFirst().isPresent();

or better use anyMatch

boolean check = masterList.stream()
                         .anyMatch(s -> s.getName().equals(record.getName()) &&
                                    s.getPart().equals(record.getPart()));

Edit:

if it can be one record matching name, and another record matching part?

Then you can collect all the record names and parts into a set as follows:

Set<String> container = masterList.stream()
                                  .flatMap(r -> Stream.of(r.getName(), r.getPart()))
                                  .collect(toSet());

Then do:

boolean result = container.contains(record.getName()) && 
                 container.contains(record.getPart()) ;
like image 95
Ousmane D. Avatar answered Oct 10 '22 09:10

Ousmane D.