Вопрос: Java 8 stream - ссылка на исходный объект потока после плоской карты


В настоящее время у меня есть код.

Метод - parseGreeting ()

    public GetGreetingNmsObjects parseGreeting(String greetingType, GetGreetingNmsResponse xmlFromNms) {

    GetGreetingNmsObjects objectFound = null;
    List<GetGreetingNmsObjects> objList = xmlFromNms.getObject();
    for (GetGreetingNmsObjects obj : objList) {

        List<Attribute> attrs = obj.getAttributes();
        Optional<Boolean> found = attrs.stream()
                                 .filter(a -> a.name.equals(GREETING_TYPE))
                                 .map(a -> a.value.equals(greetingType))
                                 .findAny();

        if(found.get()) {
            objectFound = obj;
            break;
        }

    return objectFound;
}

GetGreetingNmsObjects .java

public class GetGreetingNmsObjects {
    List<Attribute> attributeList;

    public List<Attribute> getAttributes() {
        return attributeList;
    } 
}

В вышеприведенном методе существует ли способ избежать цикла for и if и дескриптора с самими потоками?

Я попытался использовать «flatmap» и получить поток для «attributesList», но как только совпадение найдено, я не смог получить ссылку на объект GetGreetingNmsObjects.

GetGreetingNmsObjects objectFound = objList.stream()
                                   .flatMap(grt -> grt.getAttributes())
                                   .filter(a -> a.name.equals(GREETING_TYPE))
                                   .map(a -> a.value.equals(greetingType))
                                   ????

5


источник


Ответы:


Исходный код содержит логическую ошибку:

Optional<Boolean> found = …
                         .map(a -> a.value.equals(greetingType))
                         .findAny();

Это вернет результат произвольного сравнения в последовательном контексте, это, скорее всего, результат первого элемента.

Я совершенно уверен, что вы действительно хотите знать, есть ли соответствующий элемент, следовательно, следует использовать

boolean found = …
               .anyMatch(a -> a.value.equals(greetingType));

Это можно просто использовать как предикат, чтобы найти первый элемент, имеющий соответствующий элемент:

return xmlFromNms.getObject().stream()
    .filter(obj -> obj.getAttributes().stream()
                      .filter(  a -> a.name.equals(GREETING_TYPE))
                      .anyMatch(a -> a.value.equals(greetingType)))
    .findFirst().orElse(null);

11