首页 > 解决方案 > 防止反馈循环/Catch22 Java 递归

问题描述

我试图检测并防止对象以递归的形式包含自己。

示例: Product A包含零件列表,其中一些属于Product. 将 a 添加PartProduct A包含的部件列表时,我想验证它不是它本身,并且产品的任何部件最终都不会导致Product A

productA -> part1, productB
productB -> part1, part2, productC
productC -> part3

productC cannot contain productA, productB, or productC
productB cannot contain productA or productB
productA cannot contain productA

这是我到目前为止所拥有的。目前,它有效——有时。

class Part {
  protected final long id;
  ...
  public final boolean equals(Object o) {
    ... // ide generated generic stuff
    return this.id == other.id; 
    // which is ultimately (this == o) in most use cases
  }
}

class final Product extends Part {

  List<? extends Part> parts;

  private boolean catch22(Product checkAgainst) {
    Set<? extends Product> products 
            = new HashSet(checkAgainst.parts.stream()
            .filter(e -> e.getClass().equals(getClass()))
            .collect(Collectors.toSet()));
    for (Product product: products) {
      if (this.equals(product)) {
        return true;
      }
      return catch22(product);
    }
    return false;
    // I have a feeling that I'm this is going to the bottom of the first
    // element in the set as it goes down the line until it finishes the
    // loop and then returning false when it hasn't finished.
  }

  public void add(Part part) {
    if (this.equals(part)) {  
      return;
    }
    if (part instanceof Product) {  // use Class.isAssignableFrom?
      Product product = (Product) part;
      if (catch22(product)) {
        return;
      }
    }
    parts.add(part);
  }
}

此外,欢迎对实施进行任何改进。

标签: javarecursion

解决方案


for (Product product: products) {
      if (this.equals(product)) {
        return true;
      }
      return catch22(product);
}

应该:

boolean catch22(Product checkAgainst) {
    if (this.equals(checkAgainst)) {
        return true;
    }
    Set<? extends Product> products 
                = new HashSet(checkAgainst.parts.stream()
                .filter(e -> e.getClass().equals(getClass()))
                .collect(Collectors.toSet()));
    for (Product product: products) {
        if (catch22(product)) {
            return true;
        }
    }
    return false;
}

推荐阅读