代码重新分解最终不会给出相同的结果

时间:2017-04-25 15:01:57

标签: java

我正在尝试重写和重新考虑我的代码,但最后我没有相同的结果(当我执行这两个函数时,List vgs不包含相同的结果)。 另外,我无法弄清楚下面的代码有什么问题。有人能告诉我怎么做才能保持我的元素在List andVars,notVars和orVars中的顺序? 此函数的目标是删除andVars&的所有null或空String元素值。 notVars list +我的String元素值中的所有重复元素andVars& notVars列表 对于每个varGroup元素并保持andVars,notVars列表元素的顺序。谢谢

public static void RemoveDuplicateListElements(List<VarGroup> vgs) {
        if (vgs == null) {
            return;
        }
        for (VarGroup vg : vgs) {
            RemoveDuplicateListElements(vg.getOrVars());
            if (vg.getAndVars() != null) {
                for (int x = vg.getAndVars().size()-1 ; x >= 0; x--) {
                    if (vg.getAndVars().get(x) == null
                            || vg.getAndVars().get(x).isEmpty())
                    {
                        vg.getAndVars().remove(x);
                    } else {
                        for (int y = 0; y < x; y++) {
                            if (vg.getAndVars().get(x).equals(vg.getAndVars().get(y))) {
                                vg.getAndVars().remove(x);
                                break;
                            }
                        }
                    }
                }
            }

            if (vg.getNotVars() != null) {
                for (int x = vg.getNotVars().size()-1 ; x >= 0; x--) {
                    if (vg.getNotVars().get(x) == null
                            || vg.getNotVars().get(x).isEmpty())
                    {
                        vg.getNotVars().remove(x);
                    } else {        
                        for (int y = 0; y < x; y++) {
                            if (vg.getNotVars().get(x).equals(vg.getNotVars().get(y))) {
                                vg.getNotVars().remove(x);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
public class VarGroup {
    private List<String> notVars = new ArrayList();
    private List<VarGroup> orVars = new ArrayList();
    private List<String> andVars = new ArrayList();

    public List<VarGroup> getOrVs() {
        return this.orVars;
    }
    public void setOrVars(List<VarGroup> orVars) {
        this.orVars = orVars;
    }
    public List<String> getAndVars() {
        return this.andVars;
    }
    public void setAndVars(List<String> andVars) {
        this.andVars = andVars;
    }
    public List<String> getNotVars() {
        return this.notVars;
    }
    public void setNotVars(List<String> notVars) {
        this.notVars = notVars;
    }
}

我的重构在这里:

public static void RemoveDuplicateListElements(List<VarGroup> vgs) {
    if (vgs == null) {
        return;
    }
    for (VarGroup vg : vgs) {
        RemoveDuplicateListElements(vg.getOrVars());
        if (vg.getAndVars() != null) {
            vg.getAndVars().stream().distinct()
                    .filter(andVar -> Objects.nonNull(andVar) || !andVar.isEmpty())
                    .collect(Collectors.toList());
        }

        if (vg.getNotVars() != null) {
            vg.getNotVars().stream().distinct()
                    .filter(notVar -> Objects.nonNull(notVar) || !notVar.isEmpty())
                    .collect(Collectors.toList());
        }
    }
} 

4 个答案:

答案 0 :(得分:2)

重构方法中的此代码不执行任何操作:

if (vg.getAndVars() != null) {
    vg.getAndVars().stream().distinct()
                .filter(andVar -> Objects.nonNull(andVar) || !andVar.isEmpty())
                .collect(Collectors.toList());
}

它只是从列表中创建一个流,过滤流,然后从过滤的流中创建一个新列表。但是那个新列表会被立即丢弃。您应该使用setAndVars使用创建的过滤列表,例如使用retainAll修改现有列表。

或者,如果你想使用stream和lambdas,那么使用removeIf怎么样?您可以使用Set 1)跟踪重复项。简单的例子:

List<String> lst = new ArrayList<>(Arrays.asList("foo", "bar", "foo", "blub", null));
Set<String> seen = new HashSet<>();
lst.removeIf(x ->  x == null || ! seen.add(x));

1)通常你不应该在流中使用带副作用的方法。

答案 1 :(得分:2)

我认为你应该在这里提取一些功能:

public static void removeDuplicateListElements(List<VarGroup> vgs) {
    if (vgs == null) {
        return;
    }
    for (final VarGroup vg : vgs) {
        removeDuplicateListElements(vg.getOrVars());
        handleVars(vg.getAndVars());
        handleVars(vg.getNotVars());
    }
}

private static void handleVars(final List<String> theVars) {
    if (theVars != null) {
        for (int x = theVars.size() - 1; x >= 0; x--) {
            if (theVars.get(x) == null || theVars.get(x).isEmpty()) {
                theVars.remove(x);
            } else {
                for (int y = 0; y < x; y++) {
                    if (theVars.get(x).equals(theVars.get(y))) {
                        theVars.remove(x);
                        break;
                    }
                }
            }
        }
    }
}

使用的方法(Intellij Idea):

  • 选择vg.getAndVars()并为其提取变量
  • 选择vg.getOrVars()并为其提取变量
  • 收到有关重复代码的警告
  • 选择标记为重复的第1个区块并提取方法(接受IntelliJ提议以替换第2个区块)
  • 在第一步中提取的内联变量
  • (奖励步骤:重命名)

答案 2 :(得分:0)

在我看来,此代码将删除列表中的每个元素

for (int x = vg.getAndVars().size()-1 ; x >= 0; x--) {
    // ...
    for (int y = 0; y < x; y++) {
        if (vg.getAndVars().get(x).equals(vg.getAndVars().get(y))) {
            vg.getAndVars().remove(x);
              break;
            }
        }
    }
}

由于您要从循环中的列表中删除元素,因此存储在给定索引中的数据可能会在循环期间发生变化。

答案 3 :(得分:0)

如果您想删除重复项并保留顺序,为什么不使用TreeSet