通过 Java 列表流式传输以填充地图

Streaming over a Java list to populating a Map

Java 11 在这里。我有以下 POJO:

@Data // Lombok; adds getters, setters, all-args constructor and equals and hashCode
public class Fliflam {
    private String merf;
    private String tarf;
    private Boolean isFlerf;
}

我有一个方法可以验证 Flimflam 和 return 验证 Flimflam 时遇到的任何错误的 List<String>。如果有人出于某种原因认为这有帮助,我可以将其更改为 return Optional<List<String>>,尤其是在处理 Stream API:

public List<String> validateFlimflam(Flimflam flimflam) {
    List<String> errors = new ArrayList<>();

    // ... validation code omitted for brevity
    // 'errors' list is populated with any errors; otherwise it returns empty

    return errors;
}

我想通过 List<Flimflam> 流式传输 (Stream API) 并填充 Map<Flimflam,List<String>> errors map,其中map是一个Flimflam验证失败的,对应的值为验证错误字符串列表

我可以像这样用“老式”的方式实现这个:

List<Flimflam> flimflams = getSomehow();
Map<Flimflam,List<String>> errorsMap = new HashMap<>();
for (Flimflam ff : flimflams) {
    List<String> errors = validateFlimflam(ff);
    if (!errors.isEmpty() {
        errorsMap.put(ff, errors);
    }
}

如何通过 Stream API 完成此操作?

像这样

Map<Flimflam,List<String>> errorsMap = flimflams.stream().collect(Collectors.toMap(f -> f, f-> f::validateFlimflam));

toMap 接受 2 个参数 (keyMapper,valueMapper) 在您的情况下,键映射器是来自流本身的对象,而值是在该对象上调用 validateFlimflam

很难说出 validateFlimflam 方法的确切定义位置。我怀疑它不在 Flimflam class 本身中,因为不需要将其自身的实例传递给该方法。所以我认为它是 class 的外部方法。假设我将按如下方式进行:

thisClass = 包含 validateFlimflam 的实例。可以设置为 this

Map<Flimflam, List<String>> errorsMap =
        flimflams.stream().collect(Collectors.toMap(f -> f,
                        thisClass::validateFlimflam));

如果碰巧 Flimflam 确实包含 validateFlimflam,您可以这样做。请注意,这假定该方法 没有参数 因为它们不是必需的

Map<Flimflam, List<String>> errorsMap =
        flimflams.stream().collect(Collectors.toMap(f -> f,
                        Flimflam::validateFlimflam));

最后,如果包含的 class 是其他的 class 并且 validateFlimflam 方法被声明为静态的,那么您可以通过使用包含的 class 名称,不是实例。此外,在这种情况下,该方法将采用定义的参数。

Map<Flimflam, List<String>> errorsMap =
        flimflams.stream().collect(Collectors.toMap(f -> f,
                        SomeClass::validateFlimflam));