Как обнаружить пустую многочастную передачу данных

Я получил эту ошибку, потому что мой контроль версий был установлен, чтобы игнорировать мою папку с bin. Очень глупо, но, возможно, кому-то это поможет.

0
задан User1291 15 January 2019 в 16:38
поделиться

1 ответ

Я не хочу проверять размер файла, потому что файл МОЖЕТ быть размером 0 байт (бесполезный файл, в большинстве случаев, правда, но все же). А проверка только на наличие пустых имен файлов позволяет мне решить, можно ли отказаться от конкретного Part.

Если я могу избежать этого, я не хочу итерировать части более одного раза.

Так что я думаю, что я мог бы сделать, это создать логический флаг, для которого я установил значение true, если я в конечном итоге загрузлю что-нибудь ...

boolean uploadedAnything = false;

Так как я использую parallelStream, обновление этого флага потребует некоторой синхронизации. Я уже синхронизируюсь в потоке out, так почему бы просто не выбросить его туда?

synchronized (out) {
    out.print(String.format("uploading '%s': %s, %d%s...", fileName, p.getContentType(), sizeInKb, "KB"));
    if (success){
        out.println("OK<br>");
        uploadedAnything = true;
    }
    else out.println("FAILED<br>");
}

, за исключением того, что Java отказывается компилировать это, потому что

локальные переменные, на которые ссылаются из лямбда-выражение должно быть окончательным или эффективно окончательным

, которое не имеет ничего общего с блоком synchronized, но больше относится к тому факту, что все это заключено в

boolean uploadedAnything = false;
req.getParts().parallelStream().forEach(p -> {
    //`uploadedAnything` gets changed here
});
[ 1127] Полагаю, замена boolean на AtomicBoolean может сработать, но мне не очень нравится это решение, потому что я ненавижу добавлять синхронизацию, которая, как я ЗНАЮ, бесполезна.

Итак ... следующая идея:

Вместо перехода к forEach, давайте перейдем к map. Таким образом, мы превращаем наш список Part в список операторов независимо от того, действительно ли загрузка файла, соответствующего этому Part, действительно удалась.

Т.е.

boolean uploadedAnything = req.getParts().parallelStream().map(p -> {
    [...]
    return success;
}).matchAny(Predicate.isEqual(true));

за исключением того, что мы не можем этого сделать, потому что matchAny затем замыкает накоротко из-за обработки всех файлов. Упс.

Итак ...

List<Boolean> uploadStatus = req.getParts().parallelStream().map(p -> {
    [...]
    return success;
}).collect(Collectors.toList());
boolean uploadedAnything = uploadStatus.stream().anyMatch(Predicate.isEqual(true));

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

Думаю, мы могли бы сделать фолд ...

boolean uploadedAnything = req.getParts().parallelStream().fold(false,(status,p) -> {
    [...]
    return status || success;
});

... за исключением того, что Java не поддерживает сгибы, и одна вещь, которая приближается к несколько схожей функциональности, требует третьего аргумента, "Combiner". Поэтому мы должны поискать в Интернете, чтобы выяснить, почему и как этот Combiner действительно вступает в игру.

Найдя https://stackoverflow.com/a/24316429/3322533 , фрагмент становится

boolean uploadedAnything = req.getParts().parallelStream().reduce(false,(status,p) -> {
    [...]
    return status || success;
},(accA, accB) -> accA || accB);

, который мы можем переписать в

boolean uploadedAnything = req.getParts().parallelStream().reduce(false,(status,p) -> {
    [...]
    return status || success;
},Boolean::logicalOr);
[1138 ] Этот STILL не складывается, потому что он наносит ущерб порядку операций (что, к счастью, в данном случае не имеет значения), но он выполняет свою работу.

0
ответ дан User1291 15 January 2019 в 16:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: