Java 比较器、Comparable 和 TreeSet.contains
Java Comparator, Comparable and TreeSet.contains
编辑 - 下面稍微简化的示例(任何更简单的,我不确定它是否包含所需行为的所有元素)
下面是一个代码片段,它代表了我试图用 Comparator 做的一件事。我想在第二次调用 doRSM
时包含 return true
:
package comparisonTest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.SortedSet;
import java.util.TreeSet;
public class ComparisonTest {
private static class ArbitraryItem {
String node;
ArbitraryItem(String node) {
this.node = node;
}
public String getNode() {
return node;
}
}
private static final Map<String, ResultSet> idToArbitraryItems = new HashMap<>();
private static class ArbitraryItemComparable implements Comparable<ArbitraryItemComparable> {
ArbitraryItem item;
Comparator<ArbitraryItemComparable> c;
ArbitraryItemComparable(ArbitraryItem item, Comparator<ArbitraryItemComparable> c) {
this.item = item;
this.c = c;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ArbitraryItemComparable)) {
System.out.println("not a ArbitraryItemComparable="+o);
return false;
}
boolean eq = this.c.compare(this, ((ArbitraryItemComparable)o)) == 0;
System.out.println(" equality val="+eq);
return eq;
}
@Override
public int compareTo(ArbitraryItemComparable o) {
int compVal = this.c.compare(this, ((ArbitraryItemComparable)o));
System.out.println(" comparison val="+compVal);
return compVal;
}
}
private static class ResultSet {
SortedSet<ArbitraryItemComparable> usedResults;
String node;
Comparator<ArbitraryItemComparable> comparator;
ResultSet(String node, Comparator<ArbitraryItemComparable> comparator) {
this.usedResults = new TreeSet<ArbitraryItemComparable>();
this.node = node;
this.comparator = comparator;
}
}
static private void doRSM(Collection <ArbitraryItem> foobar, ResultSet set, int max, boolean close, String id) {
Iterator<ArbitraryItem> items = foobar.iterator();
for (;items.hasNext();) {
ArbitraryItem item = (ArbitraryItem) items.next();
ArbitraryItemComparable itemComparable = new ArbitraryItemComparable(item, set.comparator);
System.out.println("*** looking at node "+itemComparable.item.getNode()+"***, sur size="+set.usedResults.size());
if (!set.usedResults.contains(itemComparable)); {
System.out.println("*** node "+itemComparable.item.getNode()+" not in usedResults");
}
set.usedResults.add(itemComparable);
}
}
public static void main(String [] args)
{
Collection<ArbitraryItem> items = new ArrayList<>();
for (int i = 0; i < 3; i++) {
items.add(new ArbitraryItem(""+i));
}
Comparator<ArbitraryItemComparable> comparator = new Comparator<ArbitraryItemComparable>() {
@Override
public int compare(ArbitraryItemComparable o1, ArbitraryItemComparable o2) {
// this is where the magic needs to happen!!
System.out.println("calling compare: o1 node="+o1.item.getNode()+" "+o1.item.getNode().hashCode()+" o2 node="+o2.item.getNode()+" "+o2.item.getNode().hashCode());
return o1.item.getNode().hashCode() - o2.item.getNode().hashCode();
}
@Override
public boolean equals(Object o) {
System.out.println("why is this called?");
return false;
}
};
ResultSet set = new ResultSet("3", comparator);
idToArbitraryItems.put("q", set);
doRSM(items, set, 1000, false, "q");
doRSM(items, set, 1000, false, "q");
}
}
但是,日志显示如下:
*** looking at node 0***, sur size=0
*** node 0 not in usedResults
calling compare: o1 node=0 48 o2 node=0 48
comparison val=0
*** looking at node 1***, sur size=1
calling compare: o1 node=1 49 o2 node=0 48
comparison val=1
*** node 1 not in usedResults
calling compare: o1 node=1 49 o2 node=0 48
comparison val=1
*** looking at node 2***, sur size=2
calling compare: o1 node=2 50 o2 node=0 48
comparison val=2
calling compare: o1 node=2 50 o2 node=1 49
comparison val=1
*** node 2 not in usedResults
calling compare: o1 node=2 50 o2 node=0 48
comparison val=2
calling compare: o1 node=2 50 o2 node=1 49
comparison val=1
*** looking at node 0***, sur size=3
calling compare: o1 node=0 48 o2 node=1 49
comparison val=-1
calling compare: o1 node=0 48 o2 node=0 48
comparison val=0
*** node 0 not in usedResults
calling compare: o1 node=0 48 o2 node=1 49
comparison val=-1
calling compare: o1 node=0 48 o2 node=0 48
comparison val=0
*** looking at node 1***, sur size=3
calling compare: o1 node=1 49 o2 node=1 49
comparison val=0
*** node 1 not in usedResults
calling compare: o1 node=1 49 o2 node=1 49
comparison val=0
*** looking at node 2***, sur size=3
calling compare: o1 node=2 50 o2 node=1 49
comparison val=1
calling compare: o1 node=2 50 o2 node=2 50
comparison val=0
*** node 2 not in usedResults
calling compare: o1 node=2 50 o2 node=1 49
comparison val=1
calling compare: o1 node=2 50 o2 node=2 50
comparison val=0
违规行从这里开始:
*** looking at node 0***, sur size=3
calling compare: o1 node=0 48 o2 node=1 49
comparison val=-1
calling compare: o1 node=0 48 o2 node=0 48
comparison val=0
*** node 0 not in usedResults
表示比较值为 0(表示它们相等),但仍在调用添加代码,表示列表并未表示它包含该值。为什么?我认为 returning a compareTo
of 0
意味着平等?此外,为什么 equals
永远不会被调用? TreeSet
文档说明 contains
:
Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
哪个会让我相信 ArbitraryItemComparable.equals
会被调用,但事实并非如此?关于如何使 usedResults.contains
函数变为 return true 的任何想法?
你有这个:
...
if (!set.usedResults.contains(itemComparable)); { // NOTE THE SEMICOLON!!!!
这基本上意味着 "ignore this condition and unconditionally execute the following block"。
编辑 - 下面稍微简化的示例(任何更简单的,我不确定它是否包含所需行为的所有元素)
下面是一个代码片段,它代表了我试图用 Comparator 做的一件事。我想在第二次调用 doRSM
时包含 return true
:
package comparisonTest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.SortedSet;
import java.util.TreeSet;
public class ComparisonTest {
private static class ArbitraryItem {
String node;
ArbitraryItem(String node) {
this.node = node;
}
public String getNode() {
return node;
}
}
private static final Map<String, ResultSet> idToArbitraryItems = new HashMap<>();
private static class ArbitraryItemComparable implements Comparable<ArbitraryItemComparable> {
ArbitraryItem item;
Comparator<ArbitraryItemComparable> c;
ArbitraryItemComparable(ArbitraryItem item, Comparator<ArbitraryItemComparable> c) {
this.item = item;
this.c = c;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ArbitraryItemComparable)) {
System.out.println("not a ArbitraryItemComparable="+o);
return false;
}
boolean eq = this.c.compare(this, ((ArbitraryItemComparable)o)) == 0;
System.out.println(" equality val="+eq);
return eq;
}
@Override
public int compareTo(ArbitraryItemComparable o) {
int compVal = this.c.compare(this, ((ArbitraryItemComparable)o));
System.out.println(" comparison val="+compVal);
return compVal;
}
}
private static class ResultSet {
SortedSet<ArbitraryItemComparable> usedResults;
String node;
Comparator<ArbitraryItemComparable> comparator;
ResultSet(String node, Comparator<ArbitraryItemComparable> comparator) {
this.usedResults = new TreeSet<ArbitraryItemComparable>();
this.node = node;
this.comparator = comparator;
}
}
static private void doRSM(Collection <ArbitraryItem> foobar, ResultSet set, int max, boolean close, String id) {
Iterator<ArbitraryItem> items = foobar.iterator();
for (;items.hasNext();) {
ArbitraryItem item = (ArbitraryItem) items.next();
ArbitraryItemComparable itemComparable = new ArbitraryItemComparable(item, set.comparator);
System.out.println("*** looking at node "+itemComparable.item.getNode()+"***, sur size="+set.usedResults.size());
if (!set.usedResults.contains(itemComparable)); {
System.out.println("*** node "+itemComparable.item.getNode()+" not in usedResults");
}
set.usedResults.add(itemComparable);
}
}
public static void main(String [] args)
{
Collection<ArbitraryItem> items = new ArrayList<>();
for (int i = 0; i < 3; i++) {
items.add(new ArbitraryItem(""+i));
}
Comparator<ArbitraryItemComparable> comparator = new Comparator<ArbitraryItemComparable>() {
@Override
public int compare(ArbitraryItemComparable o1, ArbitraryItemComparable o2) {
// this is where the magic needs to happen!!
System.out.println("calling compare: o1 node="+o1.item.getNode()+" "+o1.item.getNode().hashCode()+" o2 node="+o2.item.getNode()+" "+o2.item.getNode().hashCode());
return o1.item.getNode().hashCode() - o2.item.getNode().hashCode();
}
@Override
public boolean equals(Object o) {
System.out.println("why is this called?");
return false;
}
};
ResultSet set = new ResultSet("3", comparator);
idToArbitraryItems.put("q", set);
doRSM(items, set, 1000, false, "q");
doRSM(items, set, 1000, false, "q");
}
}
但是,日志显示如下:
*** looking at node 0***, sur size=0
*** node 0 not in usedResults
calling compare: o1 node=0 48 o2 node=0 48
comparison val=0
*** looking at node 1***, sur size=1
calling compare: o1 node=1 49 o2 node=0 48
comparison val=1
*** node 1 not in usedResults
calling compare: o1 node=1 49 o2 node=0 48
comparison val=1
*** looking at node 2***, sur size=2
calling compare: o1 node=2 50 o2 node=0 48
comparison val=2
calling compare: o1 node=2 50 o2 node=1 49
comparison val=1
*** node 2 not in usedResults
calling compare: o1 node=2 50 o2 node=0 48
comparison val=2
calling compare: o1 node=2 50 o2 node=1 49
comparison val=1
*** looking at node 0***, sur size=3
calling compare: o1 node=0 48 o2 node=1 49
comparison val=-1
calling compare: o1 node=0 48 o2 node=0 48
comparison val=0
*** node 0 not in usedResults
calling compare: o1 node=0 48 o2 node=1 49
comparison val=-1
calling compare: o1 node=0 48 o2 node=0 48
comparison val=0
*** looking at node 1***, sur size=3
calling compare: o1 node=1 49 o2 node=1 49
comparison val=0
*** node 1 not in usedResults
calling compare: o1 node=1 49 o2 node=1 49
comparison val=0
*** looking at node 2***, sur size=3
calling compare: o1 node=2 50 o2 node=1 49
comparison val=1
calling compare: o1 node=2 50 o2 node=2 50
comparison val=0
*** node 2 not in usedResults
calling compare: o1 node=2 50 o2 node=1 49
comparison val=1
calling compare: o1 node=2 50 o2 node=2 50
comparison val=0
违规行从这里开始:
*** looking at node 0***, sur size=3
calling compare: o1 node=0 48 o2 node=1 49
comparison val=-1
calling compare: o1 node=0 48 o2 node=0 48
comparison val=0
*** node 0 not in usedResults
表示比较值为 0(表示它们相等),但仍在调用添加代码,表示列表并未表示它包含该值。为什么?我认为 returning a compareTo
of 0
意味着平等?此外,为什么 equals
永远不会被调用? TreeSet
文档说明 contains
:
Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
哪个会让我相信 ArbitraryItemComparable.equals
会被调用,但事实并非如此?关于如何使 usedResults.contains
函数变为 return true 的任何想法?
你有这个:
...
if (!set.usedResults.contains(itemComparable)); { // NOTE THE SEMICOLON!!!!
这基本上意味着 "ignore this condition and unconditionally execute the following block"。