我在这个结构中有一个自定义对象
static class Node {
int col;
int row;
int g;
int h;
int f;
public Node(int col, int row, int g, int h) {
this.col = col;
this.row = row;
this.g = g;
this.h = h;
this.f = g+h;
}
}
col
和 row
变量是唯一的,并且只能在 ArrayList<Node> myList
中出现一次.
有没有一种最佳方法可以避免添加或检查可能的重复项,而不必进行讨厌的 for 循环?
我知道 Set
接口(interface)可能是一个解决方案,因为不会出现重复,但我现在有很多代码,除非有必要,否则我不想重构。
最佳答案
这是您的选择。所有这些解决方案都需要正确实现 equals
和 hashCode
。由于您希望 row
和 col
是唯一的:
public boolean equals(Object obj) {
if (obj == null || obj.getClass() != Node.class) {
return false;
}
Node other = (Node) obj;
if (other.col != this.col) {
return false;
}
if (other.row != this.row) {
return false;
}
return true;
}
public int hashCode() {
int result = 7;
result += row * 31;
result += col * 31;
return result;
}
遍历 List
您不必自己进行迭代,但这正是调用 List.contains
所要做的。这个很简单:
if (!myList.contains(node)) {
myList.add(node);
}
这将为您迭代,因此您不必编写循环。
List
为Set
为List
这里有两个子选项。如果您想保留输入列表的顺序,则可以使用 LinkedHashSet
。如果你不在乎,你可以使用HashSet
。我的意思是,如果我有一个包含元素 A、B、C 的 List
,将其转换为 HashSet
并返回可能会生成不同的列表,例如 B、C、A . LinkedHashSet
保持元素的插入顺序,避免了这个问题。无论如何,您只需执行以下操作:
Set<Node> nodeSet = new [Linked]HashSet<Node>(myList);
nodeSet.add(node);
myList = new ArrayList<Node>(nodeSet);
请记住,这本质上也是在进行迭代,但它使用哈希码快捷方式而不是检查每个元素的相等性,这对于足够多的节点来说可能是个大问题。如果您的节点列表很小(少于 1000 个元素),那么我怀疑这会有很大的不同,您也可以使用第一个。
将所有内容转换为Set
您提到这需要在您的代码中进行大量重构,但这并不是一件坏事,尤其是如果您计划在未来大量使用此代码。我的经验是,如果重构会让代码更易于维护,那么增加一点额外的开发时间绝不是一件坏事。编写可维护、可读和可理解的代码 is what the experts do (这里的问题不相关,但这个特定的答案是)。由于 Set
暗示唯一元素而 List
没有,因此进行更改是有意义的。编译器几乎会告诉您所有需要更改的地方及其错误,并且它可能比您想象的要少。
关于java - 使用自定义对象消除或避免在 ArrayList 中添加重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13253424/