将嵌套的foreach重构为Java 8流

时间:2015-12-22 00:38:38

标签: java java-8 java-stream

我有两个列表,我循环填充最终列表,因为内部循环满足条件。

private List<Enum> getEnumFromType(List<Bean.Var> vars, List<Enum> enums) {
    List<Enum> enumList = new ArrayList<>();

    for (Bean.Var var : vars) {
        String typeWithoutTypeIdentifierPrefix = var.getType().substring(1,var.getType().length());
        for (Enum enumVal : enums) {
            if (typeWithoutTypeIdentifierPrefix.equals(enumVal.getName())) {
                if (!enumList.contains(enumVal)) {
                    enumList.add(enumVal);
                }
            }
        }
    }

    return enumList;
}

我已经重构了使用最新Java 8流API的代码,我提出了这个:

vars.stream().forEach(
    var -> {
            String typeWithoutPrimitiveIdentifier = var.getType().substring(1,var.getType().length());

            enums.stream()
                    .filter(enumVal -> typeWithoutPrimitiveIdentifier(enumVal.getName()))
                    .forEach(enumVal -> {

                if (!enumList.contains(enumVal)) {
                    enumList.add(enumVal);
                }
        });
    }
);

我怎样才能更进一步去除嵌套的foreach()方法?

3 个答案:

答案 0 :(得分:7)

使用stream().forEach(..)add内调用forEach(以便改变外部enumList实例)的问题是,您可以轻松地运行并发问题如果有人并行转动流并且集合不是线程安全的。

相反,你应该赞成适合可变减少的收集方法:

private Set<Enum> getEnumFromType(List<Bean.Var> vars, List<Enum> enums) {
    return vars.stream()
               .map(var -> var.getType().substring(1))
               .map(v -> enums.stream().filter(e -> v.equals(e.getName())).findAny())
               .filter(Optional::isPresent)
               .map(Optional::get)
               .collect(toSet());
}

您可能还希望预先构建映射String -> Enum以避免多次过滤。

private Set<Enum> getEnumFromType(List<Bean.Var> vars, List<Enum> enums) {
    Map<String, Enum> enumsName = enums.stream().collect(toMap(Enum::getName, e -> e, (e1, e2) -> e1));
    return vars.stream()
               .map(var -> var.getType().substring(1))
               .map(enumsName::get)
               .filter(Objects::nonNull)
               .collect(toSet());
}

如果您真的想要返回List,可以查看Collectors.collectingAndThen

答案 1 :(得分:2)

我会把它分成两个操作:

  1. 获取没有原始标识符的类型列表。
  2. 查找名称为其中之一的所有Enum,将其收集到Set以确保没有重复项。
  3. 这是我想出来的,但它未经测试:

    private List<Enum> getEnumFromType(List<Bean.Var> vars, List<Enum> enums) {
        List<String> typesWithoutPrefix = vars.stream()
            .map(e -> e.getType().substring(1))
            .collect(Collectors.toList());
    
        Set<Enum> set = enums.stream()
            .filter(e -> typesWithoutPrefix.contains(e.getName()))
            .collect(Collectors.toSet());
        return new ArrayList<>(set);
    }
    

答案 2 :(得分:1)

试试这个。

operator delete[]

返回值的顺序与您的顺序不同。