我想将自定义数据放入TreeSet
。当自定义数字相同时,我会添加交易量。
这是实现TradeNode
Interator的Comparable
类。
import java.util.Comparator;
public class TradeNode implements Comparable<TradeNode> {
private String cstm; // custom number
private Integer mon = 0; // Trade
public TradeNode() {}
public TradeNode(String cstm, int mon) {
this.mon = mon;
this.cstm = cstm;
}
public int compareTo(TradeNode o) {
if (o.cstm.equals(this.cstm)) {
o.mon += this.mon;
return 0;
} else if (this.mon == o.mon) {
return this.cstm.compareTo(o.cstm);
} else {
//return (o.mon - this.mon);
return o.mon.compareTo(this.mon);
}
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof TradeNode)) {
return false;
}
TradeNode other = (TradeNode) obj;
if (cstm == null) {
if (other.cstm != null) {
return false;
}
} else if (!cstm.equals(other.cstm)) {
return false;
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cstm == null) ? 0 : cstm.hashCode());
return result;
}
@Override
public String toString() {
return "[" + cstm + "] [" + mon + "]";
}
public int getMon() {
return mon;
}
public void setMon(Integer mon) {
this.mon = mon;
}
public String getCstm() {
return cstm;
}
}
,测试类是:
public class Testtree {
public static void main(String[] args) {
TradeNode nd1 = new TradeNode("A", 100);
TradeNode nd2 = new TradeNode("B", 10);
TradeNode nd3 = new TradeNode("B", 1000);
TreeSet<TradeNode> tree = new TreeSet<TradeNode>();
tree.add(nd1);
tree.add(nd2);
tree.add(nd3);
for (TradeNode node : tree) {
System.out.println(node);
}
}
我认为输出应该是这样的:
[B] [1010]
[A] [100]
但输出是
[B] [1000]
[A] [100]
[B] [10]
有人可以帮助我并指出我的错吗?
如果我像这样更改compareTo()方法,它仍然不起作用。
public int compareTo(TradeNode o) {
if (o.cstm.equals(this.cstm)) {
return 0;
} else {
return o.mon.compareTo(this.mon);
}
}
结果是:
[B] [1000]
[A] [100]
[B] [10]
我尝试了 Ben Xu 的方法,这里是代码: 我的新compareTo()方法:
public int compareTo(TradeNode o) {
if (o.cstm.equals(this.cstm)) {
return 0;
} else {
return this.mon.compareTo(o.mon);
}
}
我的新Testtree课程:
public class Testtree {
public static void main(String[] args) {
TradeNode nd1 = new TradeNode("44010358010481", 150354);
TradeNode nd2 = new TradeNode("44010358010481", 150641);
TradeNode nd3 = new TradeNode("44010358010481", 270000);
TradeNode nd4 = new TradeNode("44010039275685", 10000);
TradeNode nd5 = new TradeNode("44010039275685", 980000);
TradeNode nd6 = new TradeNode("44010039275685", 5000);
TradeNode nd7 = new TradeNode("44010234235687", 10000);
TradeNode nd8 = new TradeNode("44010234235687", 360000);
TradeNode nd9 = new TradeNode("44010234235687", 53400);
Map<String, Integer> map = new HashMap<String, Integer>();
addTradeNode(map, nd1);
addTradeNode(map, nd2);
addTradeNode(map, nd3);
addTradeNode(map, nd4);
addTradeNode(map, nd5);
addTradeNode(map, nd6);
addTradeNode(map, nd7);
addTradeNode(map, nd8);
addTradeNode(map, nd9);
Iterator<Entry<String, Integer>> iterator = map.entrySet().iterator();
TradeNode t;
List<TradeNode> list = new ArrayList<TradeNode>();
while(iterator.hasNext()) {
Map.Entry<String, Integer> m = iterator.next();
t = new TradeNode(m.getKey(),m.getValue());
list.add(t);
}
Collections.sort(list);
for(TradeNode tn : list) {
System.out.println(tn);
}
}
private static void addTradeNode(Map<String, Integer> map, TradeNode node) {
Integer integer = map.get(node.getCstm());
if (integer == null) {
map.put(node.getCstm(), node.getMon());
} else {
map.remove(node.getCstm());
map.put(node.getCstm(), integer.intValue() + node.getMon());
}
}
}
结果是:
[44010234235687] [423400]
[44010358010481] [570995]
[44010039275685] [995000]
最后,它满足了我的要求。但我仍然不知道为什么这个新的compareTo()方法在以下测试方法中不起作用:
public class Testtree2 {
public static void main(String[] args) {
TradeNode nd1 = new TradeNode("A", 100);
TradeNode nd2 = new TradeNode("B", 10);
TradeNode nd3 = new TradeNode("B", 1000);
TreeSet<TradeNode> tree = new TreeSet<TradeNode>();
tree.add(nd1);
tree.add(nd2);
tree.add(nd3);
for (TradeNode node : tree) {
System.out.println(node);
}
}
}
结果是:
[B] [10]
[A] [100]
[B] [1000]
我认为是:
[B] [10]
[A] [100]
有人能告诉我新的compareTo()方法中的错误在哪里吗?非常感谢,感谢任何帮助我的人。
哈哈哈,我从JavaRanch那里得到了答案。有一个名叫 Henry 的人告诉我答案。现在我想当我们在TreeSet中使用contains()方法时,它不会搜索此Set中的所有内容,它只搜索已排序的值。
新的Testtree3类是:
public class Testtree3 {
public static void main(String[] args) {
TradeNode nd1 = new TradeNode("A", 100);
TradeNode nd2 = new TradeNode("B", 200);
TradeNode nd3 = new TradeNode("B", 1000);
TreeSet<TradeNode> tree = new TreeSet<TradeNode>();
tree.add(nd1);
tree.add(nd2);
tree.add(nd3);
for (TradeNode node : tree) {
System.out.println(node);
}
}
}
结果是:
[A] [100]
[B] [200]
哈哈。现在我将找到TreeSet背后的代码。
答案 0 :(得分:4)
TreeSet.add
没有按照您的想法行事。
如果它检测到某个值已经存在,则它不会尝试将新值“添加”到现有值 - 它只返回而不更改集合。它只是一个基于集合的操作。
(此外,您的比较与equals
方法不同步的事实有点奇怪,this.mon == o.mon
的比较不适合Integer
。)
答案 1 :(得分:0)
你真的不应该在TradeNode#compareTo(...)
中改变这个论点。在进行比较时,无法保证TreeSet
是否会调用newItem.compareTo(existingItem)
或existingItem.compareTo(newItem)
。
你应该修复你的TradeNode#compareTo(...)
,使其符合Comparator
合约而不会发生突变。
如果你想改变它包含的对象,我不确定Set
(TreeSet
或其他)是否是正确的数据结构。也许从Map
到String
的{{1}}会是更好的选择吗?
答案 2 :(得分:0)
运行结果是,您可以检查再次运行程序。
[B] [1000]
[A] [100]
[B] [10]
结果是由于treeset使用了您实现的比较器
我不知道你想做什么。
但至少有一个明显的不良做法:
public int compareTo(TradeNode o) {
if (o.cstm.equals(this.cstm)) {
o.mon += this.mon;
return 0;
} else if (this.mon == o.mon) {
return this.cstm.compareTo(o.cstm);
} else {
//return (o.mon - this.mon);
return o.mon.compareTo(this.mon);
}
}
你不应该在compareTo方法中更改它的值“o.mon + = this.mon; “,这非常令人困惑。
如果要将所有TreeNode的名称相加, 不要使用Collection,而是使用map。
例如,使用hashmap,key是name或(TreeNode,因为它的equals和hashcode只使用cstm),value是num。每次添加TreeNode时,检查是否存在相同的名称,如果没有,则添加到map,否则添加值。
以下是使用map的一个示例代码:
public class Testtree {
public static void main(String[] args) {
TradeNode nd1 = new TradeNode("A", 100);
TradeNode nd2 = new TradeNode("B", 10);
TradeNode nd3 = new TradeNode("B", 1000);
Map<String, Integer> map = new HashMap<String, Integer>();
addTreeNode(map, nd1);
addTreeNode(map, nd2);
addTreeNode(map, nd3);
System.out.println(map);
}
private static void addTreeNode(Map<String, Integer> map, TradeNode node) {
Integer integer = map.get(node.getCstm());
if (integer == null) {
map.put(node.getCstm(), node.getMon());
} else {
map.remove(node.getCstm());
map.put(node.getCstm(), integer.intValue() + node.getMon());
}
}
}
答案 3 :(得分:0)
您的compareTo方法包含更改状态o.mon += this.mon;
的代码,这是非常糟糕的设计,更糟糕的是,该状态用于确定compareTo if (this.mon == o.mon)
的结果。由于存在这种毒性关系,您的实施几乎肯定违反了比较合同:见its javadoc
这太可怕了。摆脱compareTo方法中的副作用样式状态更改。
public int compareTo(TradeNode o) {
if (o.cstm.equals(this.cstm)) {
o.mon += this.mon; // ALARM BELLS!!! SIDE EFFECT!! ARRGGGHHH!
return 0;
} else if (this.mon == o.mon) { // AND THE SIDE EFFECT IS ALSO USED TO COMPARE! AVERT YOUR EYES!
return this.cstm.compareTo(o.cstm);
} else {
//return (o.mon - this.mon);
return o.mon.compareTo(this.mon);
}
}