求助一个自己写程序中的关于TreeSet同时去重和按加入顺序存储的bug。

TS败类 2019-04-04 01:24:20
昨天在写一个题目其中一块的任务是:将一些字符串去重,并且按给你时候的顺序输出出来,我没有想到用LinkedHashSet,第一想到的是使用TreeSet,故构造一个带comparator的treeset,让俩东西相等时候输出0,表示重复,那么treeset应该会不添加这个新元素,其余情况输出1表示直接添加到末尾,不做交换。然鹅实际情况与我想象的不一样,重复元素出现在特定位置时候无法去除(这一部分我通过debug 自己定义的compartatoro1,o2进行了对比已经证实comparator书写正确,是没有进行全遍历而造成的无法识别重复)。为了简单复现这个问题,我书写了加入简单integer类型的treeset,代码如下

public class Tree {

public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<>(new Comparator<Integer>() {

@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
if(o1.equals(o2))
{
return 0;
}
return 1;
}
});
treeSet.add(1);
treeSet.add(2);
treeSet.add(3);
treeSet.add(1);
treeSet.add(4);
treeSet.add(1);
treeSet.add(5);
treeSet.add(7);
treeSet.add(1);
treeSet.add(6);
treeSet.add(7);
treeSet.add(1);
for(int i : treeSet)
{
System.out.println(i);
}
}
}

这个代码也许你以为会输出1,2,3,4,5,7,6
但是实际情况是
1
2
3
1
4
5
7
6

根据debug结果可以发现在加入第二个1时候(也就是加入这个1之前是1,2,3),这时候我认为加入1之后o1一直作为1,去和剩余3个元素作对比,如果重复就不会添加,然鹅实际情况再一次不同,o1一直作为1,也就是新添加的元素,只与2,3做了对比(也就是o2元素只遍历了2,3这两个)就结束了,程序发现并没有重复,因为根本就没看开头位置的东西是1,当然认为无重复,就把1又加了进去。
这个同理可以验证到字符串上面,并且更多的试验表明在总长超过6之后下标为2的元素也不会被o2遍历到。
小弟长时间自己思考,百度源码结论都应该是冒泡逐个遍历,但是并没能解决,还请各位老师指点一二。非常感谢!
...全文
164 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_39936465 2019-04-04
  • 打赏
  • 举报
回复
红黑树是种平衡树,任意节点左边不为空的话,左边节点连接的所以值都小于该节点,右边都大于该节点

所以放入1,2,3时 1在左节点 2为根节点 ,3在有节点。
qq_39936465 2019-04-04
  • 打赏
  • 举报
回复
引用 6 楼 weixin_42546808 的回复:
这里看到一个觉得在理的回答:
因为treeSet的存储是使用treemap来实现的 结构为二叉树 你的例子中 在添加了 123三个数之后 根结点为2 左节点(比父节点小)为1 右节点为3 在这个时候插入1这个数 比较器先与2判断 返回1(新插入的1比2大) 则继续与3比较 也返回1 并没有去按照你所想的 先与1比较

也就是说 你所写的这个比较方法 插入同样的数 可能会因为不同的插入顺序 导致不同的结果。

但是个人还有个问题为啥二叉树进去1.2.3时候是2为根节点而不是1,是因为红黑树的左右旋转调整结果吗


因为红黑树 小的放左边,大的放右边,负表示小,正表示大,你的比较2个数不相等结果都是1,这时候第2个1被放3的右边,等于树的左右2边都有1,所以后面的1会和放在右边第2个1比较被去重。
TS败类 2019-04-04
  • 打赏
  • 举报
回复
这里看到一个觉得在理的回答:
因为treeSet的存储是使用treemap来实现的 结构为二叉树 你的例子中 在添加了 123三个数之后 根结点为2 左节点(比父节点小)为1 右节点为3 在这个时候插入1这个数 比较器先与2判断 返回1(新插入的1比2大) 则继续与3比较 也返回1 并没有去按照你所想的 先与1比较

也就是说 你所写的这个比较方法 插入同样的数 可能会因为不同的插入顺序 导致不同的结果。

但是个人还有个问题为啥二叉树进去1.2.3时候是2为根节点而不是1,是因为红黑树的左右旋转调整结果吗
qq_39936465 2019-04-04
  • 打赏
  • 举报
回复
引用错了程序,楼主缺少返回值-1
qq_39936465 2019-04-04
  • 打赏
  • 举报
回复
引用 1 楼 bcsflilong 的回复:


public class Student {
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<Integer>(new Comparator<Integer>() {

public int compare(Integer o1, Integer o2) {
/*if (o1.equals(o2)) {
return 0;
}
return 1;*/

return o1.compareTo(o2);
}

});
treeSet.add(1);
treeSet.add(2);
treeSet.add(3);
treeSet.add(1);
treeSet.add(4);
treeSet.add(1);
treeSet.add(5);
treeSet.add(7);
treeSet.add(1);
treeSet.add(6);
treeSet.add(7);
treeSet.add(1);


for (int i : treeSet) {
System.out.println(i);
}
}
}



应该是缺少返回值-1吧
qq_39936465 2019-04-04
  • 打赏
  • 举报
回复

public class Tree {

public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<Integer>(new Comparator<Integer>() {

@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
int num=o1-o2;
return num==0?o1.compareTo(o2):num;
}
});
treeSet.add(1);
treeSet.add(2);
treeSet.add(3);
treeSet.add(1);
treeSet.add(4);
treeSet.add(1);
treeSet.add(5);
treeSet.add(7);
treeSet.add(1);
treeSet.add(6);
treeSet.add(7);
treeSet.add(1);
for (int i : treeSet) {
System.out.println(i);
}
}
}
十八道胡同 2019-04-04
  • 打赏
  • 举报
回复
引用 1 楼 bcsflilong 的回复:


public class Student {
	public static void main(String[] args) {
		TreeSet<Integer> treeSet = new TreeSet<Integer>(new Comparator<Integer>() {

			public int compare(Integer o1, Integer o2) {
				/*if (o1.equals(o2)) {
					return 0;
				}
				return 1;*/
				
				return o1.compareTo(o2);
			}

		});
		treeSet.add(1);
		treeSet.add(2);
		treeSet.add(3);
		treeSet.add(1);
		treeSet.add(4);
		treeSet.add(1);
		treeSet.add(5);
		treeSet.add(7);
		treeSet.add(1);
		treeSet.add(6);
		treeSet.add(7);
		treeSet.add(1);

		
		for (int i : treeSet) {
			System.out.println(i);
		}
	}
}

你这样写return o1.compareTo(o2); 是完全排序了,楼主的意思 不是要排序,只判重 我看了下,只判重,楼主的cmopare好像是没问题的,但是没想明白为啥结果不对。。。
bcsflilong 2019-04-04
  • 打赏
  • 举报
回复


public class Student {
public static void main(String[] args) {
TreeSet<Integer> treeSet = new TreeSet<Integer>(new Comparator<Integer>() {

public int compare(Integer o1, Integer o2) {
/*if (o1.equals(o2)) {
return 0;
}
return 1;*/

return o1.compareTo(o2);
}

});
treeSet.add(1);
treeSet.add(2);
treeSet.add(3);
treeSet.add(1);
treeSet.add(4);
treeSet.add(1);
treeSet.add(5);
treeSet.add(7);
treeSet.add(1);
treeSet.add(6);
treeSet.add(7);
treeSet.add(1);


for (int i : treeSet) {
System.out.println(i);
}
}
}

62,625

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧