vavr return 如果条件失败则循环

vavr return from loop if condition fails

我正在编写代码以使用 vavr 验证类别

private static Validation<ConstraintViolation, List<Category>> isCategoryValid(
        List<Category> categories) {

    java.util.List<Category> categoryList = new ArrayList<>();

    for (Category category : categories) {

        List<Product> detailsRequest = validateList(category.getDetails());

        if (detailsRequest .isEmpty()) {
            return invalid(new ConstraintViolation("Details", "Details cannot be empty"));
        }

        ...more validations
    
        categoryList.add(WCategory.builder().details(List.ofAll(detailsList))
                .type(category.getType()).build());
    }
    return valid(List.ofAll(categoryList));
}

我必须使用 java.util.List,因为我无法使用 vavr 本身实现它。如果我使用

categories.map(x -> x..);

如果验证失败,我无法从循环中 return 并将得到输出 List<Validations<ConstraintViolation, List<Category>>>,这不是我想要的。

编辑:

private static Validation<RuntimeException, List<String>> isCategoryValid(
        List<String> categories) {

    java.util.List<String> categoryList = new ArrayList<>();

    for (String category : categories) {

        String detailsRequest = validateList(category);

        if (detailsRequest != "") {
            return invalid(new RuntimeException("Details cannot be empty"));
        }

        ...more validations
    
        categoryList.add(detailsRequest);
    }
    return valid(List.ofAll(categoryList));
}

这在一定程度上取决于您想要实现的行为。如果您只想获取列表中第一个类别的失败验证(这似乎是这种情况),您可以使用 Either.traverseRight 然后将其转换为验证。 traverseRight只会保留第一个失败的条目或成功的事情列表。

因此代码可能如下所示:

private static Validation<RuntimeException, List<String>> isCategoryValid(List<String> categories) {
    return Validation.fromEither(
            Either.traverseRight(categories, Example::validateCategory).map(Seq::toList)
    );
}

private static Either<RuntimeException, String> validateCategory(String category) {
    // ...more validations
    return category.equals("") ? Either.left(new RuntimeException("Details cannot be empty")) : Either.right(category);
}

根据用例,保留更多验证错误可能也是个好主意。如果您选择这种方法,您可能会查看 Validation.traverse 以尽可能多地保留验证错误。在我看来,这就是 Validation 真正闪耀的地方。

那么代码将如下所示:

private static Validation<Seq<RuntimeException>, List<String>> isCategoryValid(
        List<String> categories) {

    return Validation.traverse(categories, Example::validateCategory).map(Seq::toList);
}


private static Validation<List<RuntimeException>, String> validateCategory(String category) {
    // ... combine multiple validations for the same category
    return category.equals("") ? invalid(List.of(new RuntimeException("Details cannot be empty"))) : valid(category);
}