TreeSet contains 方法对我不起作用
我想将自定义的数据放入 TreeSet
中。当自定义数量相同时,我添加贸易量。
这是我的 TradeNode
类,它实现了 Comparable
Interator。
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得到了答案。有一个叫亨利的人告诉了我答案。现在我认为当我们在 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 背后的代码。
I want to put the custom's data into a TreeSet
. When the custom number is same, I add the volume of trade.
Here is my TradeNode
class that implements the Comparable
Interator.
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;
}
}
and the test class is :
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);
}
}
I supposed the output shoud be like this :
[B] [1010]
[A] [100]
but the output is
[B] [1000]
[A] [100]
[B] [10]
Could someone help me and point me out where my fault is?
if I change my compareTo() method like this, it still doesn't work.
public int compareTo(TradeNode o) {
if (o.cstm.equals(this.cstm)) {
return 0;
} else {
return o.mon.compareTo(this.mon);
}
}
and the result is:
[B] [1000]
[A] [100]
[B] [10]
I tryed Ben Xu's method, and here is the code:
My new compareTo() method:
public int compareTo(TradeNode o) {
if (o.cstm.equals(this.cstm)) {
return 0;
} else {
return this.mon.compareTo(o.mon);
}
}
My new Testtree class:
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());
}
}
}
and the result is:
[44010234235687] [423400]
[44010358010481] [570995]
[44010039275685] [995000]
finally, it satisfied my requirement. But I still don't know why this new compareTo() method doesn't work in the following test method:
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);
}
}
}
and the result is:
[B] [10]
[A] [100]
[B] [1000]
and I supposed it to be :
[B] [10]
[A] [100]
could someone tell me where the fault is in my new compareTo() methods? Thanks a lot and thanks for anyone helping me.
Hahaha,I've got the answer from JavaRanch. There's someone named Henry told me the answer. Now I think when we use the contains() method in the TreeSet, it doesn't search everything in this Set, it only searched the sorted value.
The new Testtree3 class is :
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);
}
}
}
and the result is :
[A] [100]
[B] [200]
Haha. Now I'll go find the codes behinds the TreeSet.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
TreeSet.add
并没有做你想象的那样。如果它检测到某个值已经存在,它不会尝试将新值“添加”到现有值中 - 它只是返回而不更改集合。这只是一个基于集合的操作。
(此外,您的比较与
equals
方法不同步这一事实有点奇怪,并且this.mon == o.mon
的比较不适合整数
。)TreeSet.add
doesn't do what you think it does.If it detects that a value already exists, it doesn't try to "add" the new value to the existing one - it just returns without changing the set. It's just a set-based operation.
(Additionally, the fact that your comparison is out of sync with your
equals
method is a little odd, and the comparison ofthis.mon == o.mon
is inappropriate forInteger
.)运行结果为 ,可以检查再次运行程序。
结果是由于树集使用了您实现的比较器,
我不知道您想做什么。
但至少有一个明显的不好的做法:
你不应该在compareTo方法中改变它的值“o.mon += this.mon; ”,这非常令人困惑。
如果你想对所有同名的TreeNode求和,
不要使用 Collection ,而是使用 map 。
例如,使用 hashmap,键是 name 或(TreeNode 因为它等于并且 hashcode 仅使用 cstm ),值是 num。每次添加TreeNode时,检查是否存在同名,如果不存在,则添加到map,否则添加值。
以下是使用地图的示例代码:
The run result is , you can check to run the program again.
the result is due to treeset uses your implemented comparator
I don't know what you want to do.
but there is at least one obvious bad practice:
you should not change its value in a compareTo method “ o.mon += this.mon; ”, this is very confusing.
if you want to sum all TreeNode with the same name,
don't use a Collection , use map instead.
for example, use a hashmap, key is name or(TreeNode since its equals and hashcode only uses cstm ), value is num. every time you add a TreeNode, check if the same name exsit, if not , add to map, else add the value.
following is one example code using map:
您确实不应该改变
TradeNode#compareTo(...)
中的参数。无法保证在进行比较时TreeSet
是否会调用newItem.compareTo(existingItem)
或existingItem.compareTo(newItem)
。您可能应该修复您的
TradeNode#compareTo(...)
,以便它在不发生突变的情况下满足Comparator
合约。如果您想改变它包含的对象,我不确定
Set
(TreeSet
或其他)是否真的是正确的数据结构。也许从String
到TradeNode
的Map
会是更好的选择?You really shouldn't be mutating the argument in
TradeNode#compareTo(...)
. There is no guarantee whetherTreeSet
will callnewItem.compareTo(existingItem)
orexistingItem.compareTo(newItem)
when doing comparisons.You should probably fix your
TradeNode#compareTo(...)
so that it fulfills theComparator
contract without mutations.I'm not sure that a
Set
(TreeSet
or otherwise) is really the right data structure if you want to mutate the objects it contains. Perhaps aMap
fromString
toTradeNode
would be a better choice?您的compareTo方法包含更改状态
o.mon += this.mon;
的代码,这是非常糟糕的设计,更糟糕的是,该状态用于确定compareToif (this .mon == o.mon)
。由于存在这种有毒关系,您的实现几乎肯定违反了compareTo的合同:请参阅其 javadoc这太可怕了。消除 CompareTo 方法中的副作用样式状态更改。
Your compareTo method contains code that changes state
o.mon += this.mon;
, which is very bad design, and worse, that state is used to determine the result of compareToif (this.mon == o.mon)
. Since this toxic relationship exists, your implementation almost certainly violates the contract of compareTo: see its javadocThis is horrible. Get rid of side-effect style state changes in your compareTo method.