假设我有2个节点列表(节点是一些可比较的对象,细节无关紧要)。我想找到哪两个节点出现在两个列表上 - 不一定是相同的Node对象,而是compareTo返回0的节点。
例如,nodeA在列表A上,nodeB在列表B上。它们不是同一个节点,但nodeA.compareTo(nodeB)将返回0(相等)。
我想通过迭代列表A并将节点放在HashMap / HashSet中来解决这个问题,然后迭代列表B并检查哪些节点已经插入到HashMap / HashSet中。问题是,这不起作用,因为HashMap不会认为节点是相同的,除非它们是相同的实际节点。
我该如何解决这个问题?请注意,我不正在寻找此问题的其他解决方案,但是为了理解if(以及如何)在给定的示例场景中我可以使用HashMap,HashSet或其他类似的数据结构。
答案 0 :(得分:2)
你可以通过覆盖Node对象中的equals和hashcode方法来使用与compareTo方法相同的标准来解决这个问题(如果我理解这一点)。
答案 1 :(得分:2)
您应该使用 TreeSet
,因为依赖于排序,而不是哈希。
更新(错误!请参阅更新3):但是您仍然必须确保 a.compareTo(b)==0
iff a.equals(b)
,因为{{3}实际上通过排序找到相应的元素,然后使用equals
!
更新2:要仅使用排序,您可以对第一个列表进行排序(Collections.sort(listA)
),然后检查每个Collections.binarySearch(listA, nodeB)
的结果nodeB
来自listB
。当结果为>=0
时,nodeB
位于listA
,w.r.t他们的排序。 implementation of contains
,没有平等参与。此方法的复杂性为O(n log(n))
,因为每个二进制搜索都是O(log(n))
(n
是列表中较大者的大小 - 排序列表A也是O(n log(n))
),与使用TreeSet(O(log n)
对于insert / contains)具有相同的复杂性。
更新3:正如评论中指出的那样,TreeSet
应该开展工作,因为equals
{{未使用TreeMap's
1}},但在其他地方。但是JavaDoc说:
注意由一组维护的排序(无论是否显式 比较器提供)必须与equals一致,如果是的话 正确实现Set接口。
The implementation of binarySearch uses only ordering(!)说:
如果此set包含指定的元素,则返回true。更多 形式上,当且仅当此集合包含元素e时才返回true 这样(o == null?e == null:o.equals(e))。
因此,将containsKey
与不存在的API一起使用仍然不是一个好主意。谁知道在这种情况下另一个 Java实现可能会做什么。所以我建议坚持使用 Update 2 解决方案。
答案 2 :(得分:0)
我的建议是让你自己的HashMap子类用一个符合你标准的函数覆盖containsValue(对象值)函数。
答案 3 :(得分:0)
使用 TreeSet / TreeMap 。它使用 compareTo()方法而不是equals()和hashcode(),这是在HashMap / HashSet中分配节点时使用的。
请查看以下代码:
import java.util.HashSet;
import java.util.TreeSet;
public class TestMaps {
public static void main(String[] args) {
TreeSet<Node> set1 = new TreeSet<>();
HashSet<Node> set2 = new HashSet<>();
Node node1 = new Node(0, "First");
Node node2 = new Node(0, "Second");
System.out.println(set1.add(node1)); //Node1 added in TreeSet
System.out.println(set2.add(node1));//Node1 added in HashSet
System.out.println(set1.add(node2));//Node2 added in TreeSet
System.out.println(set2.add(node2));//Node2 added in HashSet
}
}
class Node implements Comparable<Node>{
int i;
String name;
Node(int i, String n){
this.i = i;
this.name = n;
}
@Override
public int compareTo(Node o) {
return this.i - o.i;
}
}
将此结果运行到:
true
true
false
true
希望它有所帮助!!