Извлеките все строковые значения из списка карт

#java #java-8 #java-stream

Вопрос:

Я получаю ответ rest в следующем формате.

 {
    "query_result": {
        "status": "SUCCESS",
        "message": "Results Found",
        "results": [
            {
                "key": "123"
            },
            {
                "key": "465"
            }
        ]
    }
}
 

Исходя из этого ответа, я хочу создать список строк из ключей.
Таким образом, мы хотим получить результат списка следующим образом:

 ["123", "456"]
 

Пытаюсь вывести результат следующим образом, но застрял на шаге сопоставления в следующем блоке кода.

 public Optional<List<String>> get(HttpEntity<Request> request){
    ResponseEntity<Response> response = getResponse(request); // this response holds above json data 

    return Optional.ofNullable(response)
            .map(ResponseEntity::getBody)
            .map(Response::getQueryResult)
            .map(QueryResult::getResults)
            .filter(CollectionUtils::isNotEmpty)
            .map(results -> results.) // Stuck here. results here is the list of results shown in above json. 
}
 

Я не могу извлечь отсюда все значения ключа.
В итоге мне приходится указывать индекс следующим образом, что не сработает, так как мне нужны все ключи.

 .map(results -> results.get(0))
 

Попытался рассмотреть возможность использования итератора, но это снова приведет только к захвату только первого ключа.

 .filter(CollectionUtils::isNotEmpty)
.map(List::iterator)
.map(Iterator::next)
.map(result -> result.getKey())
 

Не мог бы я, пожалуйста, получить некоторую помощь в этом. Спасибо.

Ответ №1:

 .map(QueryResult::getResults)
.filter(CollectionUtils::isNotEmpty)
.map(results -> results.stream().map(Key::getKey).collect(Collectors.toList()));
 

Предполагается, что каждый ключевой объект правильно сопоставлен с классом Key , который называется так:

 class Key {
    String key;

    String getKey() {
        return key;
    }
}
 

вы хотите, чтобы в вашей Optional цепочке внутренний список Key s был преобразован в список String s. Так что последний шаг просто позаботится об этой части.

Примечание
  1. Ваш метод возвращает необязательный список. Как правило , с точки зрения семантики лучше, если вместо этого вы возвращаете пустой список null , но это зависит от реализации.
  2. Если становится трудно понять лямбды, перенесите их логику на методы. Например, приведенная выше цепочка может стать:
 List<String> collectKeys(List<Key> keys) {
    return keys.stream().map(Key::getKey).collect(Collectors.toList())
}

// and then:
.map(QueryResult::getResults)
.filter(CollectionUtils::isNotEmpty)
.map(this::collectKeys);