Что по умолчанию для этого Collectors.toList ожидает список объектов?

Мы работаем над асинхронизацией некоторых вызовов с использованием аннотации @Async и CompletableFutures в Java. У нас есть несколько Pojo, для которых мы создаем объекты в нашем асинхронном вызове, но при попытке собрать результаты в список Eclipse хочет, чтобы я изменил список нашего Pojo на список объектов, а я не понимание того, является ли CompletableFuture ответом от потока по умолчанию.

List<Pojo1> crudResponse = null;
List<Pojo1> listOfIterations =  new ArrayList<>();

//populates object with multiple entries in list
listOfIteration = populateIterationObject(param);

crudResponse = listOfIterations.stream()
    .map(str -> CompletableFuture.supplyAsync(() -> {
        try {
            return async.hitCrud(str);
            }catch(RequestProcessingException e){
                log.error(e);
            }
            return function;
        }))
        .map(CompletableFuture::join)
        .collect(Collectors.toList());
        }

//async class
    public CompletableFuture<Pojo1> hitCrud(Pojo1 iteration) throws RequestProcessingException {

        try {
            String response;
            Pojo1 pojoResponse;
            response = connectToCrud(iteration);

            if(response != null) {
                pojoResponse.add(response);
            }                       
        }catch(Exception ex){
            log.error(ex);
        }
        return CompletableFuture.completedFuture(pojoResponse);
    }

Я нажимаю метод, чтобы вернуть объект Pojo1, но когда я пытаюсь создать список с помощью Collectors.toList (), он ожидает, что у меня будет список <Object>, с которым я могу работать, но требуется больше кода для извлечения и преобразования каждого ответ я возвращаюсь от асинхронного вызова.

Является ли это CompletableFuture значением Object по умолчанию? Если да, то можно ли по умолчанию использовать тип Pojo1?

Изменить: ошибка, которую я вижу в среде IDE:

Type mismatch: cannot convert from List<Object> to List<Pojo1>

person Criel    schedule 12.12.2017    source источник
comment
Нет, редактор запутался и не смог определить тип. Иногда они так поступают.   -  person Kayaman    schedule 12.12.2017
comment
На самом деле, похоже, что у вас действительно есть проблемы с безопасностью типов, но в этом трудно быть уверенным из-за неполноты вашего примера. Мне удалось заменить большинство недостающих битов, но какой тип function?   -  person John Bollinger    schedule 12.12.2017


Ответы (1)


Java предполагает привязку другого типа, чем вы хотите, потому что ваш код неверен. Данный

//async class
public CompletableFuture<Pojo1> hitCrud(Pojo1 iteration) // ...

а также

List<Pojo1> crudResponse = null;
List<Pojo1> listOfIterations =  new ArrayList<>();

..., давайте проанализируем это выражение потока:

crudResponse = listOfIterations.stream()
    .map(str -> CompletableFuture.supplyAsync(() -> {
        try {
            return async.hitCrud(str);
            }catch(RequestProcessingException e){
                log.error(e);
            }
            return function;
        }))
        .map(CompletableFuture::join)
        .collect(Collectors.toList());
  • listOfIterations.stream() производит Stream<Pojo1>
  • параметр типа первого вызова map() метода должен быть выведен из аргумента как тип возвращаемого значения внешней лямбды.
  • тип возвращаемого значения внешней лямбды должен быть выведен из типа вызова CompletableFuture.supplyAsync(), ...
  • which is itself the return type of the inner lambda. So what is that return type?
    • well, the inner lambda can return the result of invoking async.hitCrud(str), a CompletableFuture<Pojo1>,
    • или он может вернуть function, независимо от его типа.
    • предполагаемый тип будет ближайшим общим предком этих двух типов, по всей вероятности, либо CompletableFuture<Pojo1>, либо Object. Учитывая сообщение об ошибке, это предположительно Object.
  • Итак, вы сопоставили Stream<CompletableFuture<Object>>, поэтому следующее сопоставление дает Stream<Object>
  • Собирая это в список, вы получаете List<Object>, а не List<Pojo1>.

Это не просто косметическая проблема: в списке могут действительно содержаться объекты, не относящиеся к Pojo1.

Чтобы увидеть это, подумайте, как изменился бы анализ, если бы function имел тип CompletableFuture<Pojo1>, как и возвращаемое значение hitCrud(). Тогда тип возврата внутренней лямбды будет CompletableFuture<Pojo1>, но это сделает возвращаемый тип внешней лямбды CompletableFuture<CompletableFuture<Pojo1>>, что в конечном итоге даст вам List<CompletableFuture<Pojo1>>, что по-прежнему не то, что вы хотите. Если это действительно ваш случай, вы можете решить проблему, удалив внешнюю лямбду, чтобы вы отображали str, используя только внутреннюю:

crudResponse = listOfIterations.stream()
    .map(str -> {
            try {
                return async.hitCrud(str);
            } catch(RequestProcessingException e) {
                log.error(e);
            }
            return function;
        })
        .map(CompletableFuture::join)
        .collect(Collectors.toList());
person John Bollinger    schedule 12.12.2017