简体   繁体   English

带有自定义比较器的 TreeSet() 的异常行为

[英]Anomalous behaviour with TreeSet() with custom comparator

What I've done in the below program is, I've created a TreeSet named "alls" with a custom comparator which compares two list and if they are equal it returns 0 else returns 1. But if I add two same list into TreeSet then TreeSet accepts two same list into it.我在下面的程序中所做的是,我创建了一个名为“alls”的 TreeSet,它带有一个自定义比较器,它比较两个列表,如果它们相等则返回 0,否则返回 1。但是如果我将两个相同的列表添加到 TreeSet 中然后 TreeSet 接受两个相同的列表。 But it should not contain two same list cuz i've defined a comparator like that.但它不应该包含两个相同的列表,因为我已经定义了一个这样的比较器。

   List<Integer> a1 = new ArrayList<Integer>() {{add(1);add(2);add(3);add(4);}};
    List<Integer> a2 = new ArrayList<Integer>() {{add(1);add(1);}};
    List<Integer> a3 = new ArrayList<Integer>() {{add(2);add(1);}};
    List<Integer> a4 = new ArrayList<Integer>() {{add(3);add(1);}};
    List<Integer> a5 = new ArrayList<Integer>() {{add(4);add(1);}};
    List<Integer> a6 = new ArrayList<Integer>() {{add(5);add(1);}};
    
    Comparator b1 = (l1,l2)->{if(l1.equals(l2)) return 0; else return 1;};
    Collection<List<Integer>> alls = new TreeSet(b1);
    alls.add(a1);
    alls.add(a1);
    alls.add(a1);
    alls.add(a2);
    alls.add(a3);
    alls.add(a1);
    alls.add(a4);
    alls.add(a6);
    alls.add(a5);
    alls.add(a2);
    alls.add(a1);

When I try to Print my TreeSet(name alls) then the following output shows up:当我尝试打印我的 TreeSet(name alls) 时,会显示以下输出:

1 2 3 4 1 2 3 4

1 1 1 1

2 1 2 1

1 2 3 4 1 2 3 4

3 1 3 1

5 1 5 1

4 1 4 1

You can see [1 2 3 4] is inserted into my TreeSet(whose name is alls) twice but it does not get inserted after.您可以看到 [1 2 3 4] 两次插入到我的 TreeSet(其名称为 alls)中,但之后没有插入。

How is this possible?这怎么可能? I though TreeSet with my custom comparator doesn't allow duplicates.我虽然带有我的自定义比较器的 TreeSet 不允许重复。 Also if it allows why not the same elements doesn't get inserted further in my program此外,如果它允许为什么不在我的程序中进一步插入相同的元素

Your Comparator doesn't work你的比较器不工作

Collection<List<Integer>> alls = new TreeSet(b1);
alls.add(a1);
alls.add(a2);
alls.add(a3);

Your implementaton sorts two different list with the second always bigger due to return 1 so your Tree looks like :由于return 1 ,您的实现对两个不同的列表进行排序,第二个总是更大,因此您的树看起来像:

a1 <- a3 -> a2 a1 <- a3 -> a2

Now let's add a1 :现在让我们添加 a1 :

Collection<List<Integer>> alls = new TreeSet(b1);
alls.add(a1);
alls.add(a2);
alls.add(a3);
alls.add(a1);

a1 <- a3 ? a1 <- a3 ? a1 -> a2 RESULT a1 is bigger a1 -> a2 结果 a1 更大
a1 <- a3 -> a2 ? a1 <- a3 -> a2 ? a1 RESULT a1 is bigger a1 结果 a1 更大
a1 <- a3 -> a2 -> a1 a1 <- a3 -> a2 -> a1

Your tree has now duplicated a1.你的树现在已经复制了 a1。
SOLUTION : Use a correct Comparator mentionned in comments解决方案:使用评论中提到的正确Comparator

Try this:尝试这个:

        Comparator<List<Integer>> b1 = (l1, l2)->{

        if(l1.equals(l2)) {
            return 0;
        } else {
            if(l1.isEmpty())
                return 1;
            if(l2.isEmpty())
                return -1;

            int i = 0;
            while (l1.get(i).equals(l2.get(i))) i++;

            if(l1.get(i) > l2.get(i))
                return 1;
            else
                return -1;
        }};

Your comparator doesn't handle the situation when one list "is lower" than the second.当一个列表“低于”第二个列表时,您的比较器无法处理这种情况。 Your comparator returns only 0 and 1. I think that TreeSet uses binary search or any faster method to find an object and check if is a particular object is a set.您的比较器仅返回 0 和 1。我认为 TreeSet 使用二分搜索或任何更快的方法来查找对象并检查特定对象是否为集合。 Methods like that need to have clearly defined whether an object is greater or lower than others.像这样的方法需要明确定义一个对象是大于还是小于其他对象。 If TreeSets use primitive comparing by equal object with each in the set your comparator would be working.如果 TreeSet 使用相等对象与集合中的每个对象进行原始比较,则您的比较器将起作用。 In sorted structures are more complex and better methods to find an object.在排序结构中,找到对象的方法更复杂、更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM