简体   繁体   中英

Collecting after filtering a stream with Java 8

i have a list of DTOs, these dtos contains a list of tags. I'm searching to find dtos that contain 2 tags each with its own key and value. this code will work - but it would only find first on the inner filters, i would like to collect instead of finding the first, in case there is more than one object with that criteria

List<myDTO> responsesList = getAllData(parameters);
List<myDTO> result = responsesList.stream()
                    .filter(d ->
                            d.getData().getTags().stream()
                                .filter(t ->  t.getKey().equals(key1) && t.getValue().equals(value1))
                                .findFirst().isPresent())
                    .filter(d ->
                            d.getData().getTags().stream()
                                .filter(t -> t.getKey().equals(key2) && t.getValue().equals(value2))
                                .findFirst().isPresent())
                    .collect(Collectors.toList());

what am I missing to collect a collection instead of the findFirst().isPresent() ? if I do Collect(collectors.toList) I get an error message like "inference variable T has incompatible bounds"?

It's not actually clear what do you want. If you need to collect all the myDTO objects which have both key1/value1 tag and key2/value2 tag, then your code already works. You can just shorten it as filter(predicate).findFirst().isPresent() could be replaced with anyMatch(predicate) :

List<myDTO> result = responsesList.stream()
                .filter(d ->
                        d.getData().getTags().stream()
                            .anyMatch(t -> t.getKey().equals(key1) && t.getValue().equals(value1)))
                .filter(d ->
                        d.getData().getTags().stream()
                            .anyMatch(t -> t.getKey().equals(key2) && t.getValue().equals(value2)))
                .collect(Collectors.toList());

You can also join both filters into single predicate, though this is a matter of taste:

List<myDTO> result = responsesList.stream()
                .filter(d ->
                        d.getData().getTags().stream()
                            .anyMatch(t -> t.getKey().equals(key1) && t.getValue().equals(value1))
                        &&
                        d.getData().getTags().stream()
                            .anyMatch(t -> t.getKey().equals(key2) && t.getValue().equals(value2)))
                .collect(Collectors.toList());

If you actually want to collect matching tags, you may need a flatMap :

List<myTag> result = responsesList.stream()
                .flatMap(d -> d.getData().getTags().stream())
                .filter(t -> t.getKey().equals(key1) && t.getValue().equals(value1) ||
                             t.getKey().equals(key2) && t.getValue().equals(value2))
                .collect(Collectors.toList());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM