簡體   English   中英

帶有自定義比較器的 TreeSet() 的異常行為

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

我在下面的程序中所做的是,我創建了一個名為“alls”的 TreeSet,它帶有一個自定義比較器,它比較兩個列表,如果它們相等則返回 0,否則返回 1。但是如果我將兩個相同的列表添加到 TreeSet 中然后 TreeSet 接受兩個相同的列表。 但它不應該包含兩個相同的列表,因為我已經定義了一個這樣的比較器。

   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);

當我嘗試打印我的 TreeSet(name alls) 時,會顯示以下輸出:

1 2 3 4

1 1

2 1

1 2 3 4

3 1

5 1

4 1

您可以看到 [1 2 3 4] 兩次插入到我的 TreeSet(其名稱為 alls)中,但之后沒有插入。

這怎么可能? 我雖然帶有我的自定義比較器的 TreeSet 不允許重復。 此外,如果它允許為什么不在我的程序中進一步插入相同的元素

你的比較器不工作

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

由於return 1 ,您的實現對兩個不同的列表進行排序,第二個總是更大,因此您的樹看起來像:

a1 <- a3 -> a2

現在讓我們添加 a1 :

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

a1 <- a3 ? a1 -> a2 結果 a1 更大
a1 <- a3 -> a2 ? a1 結果 a1 更大
a1 <- a3 -> a2 -> a1

你的樹現在已經復制了 a1。
解決方案:使用評論中提到的正確Comparator

嘗試這個:

        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;
        }};

當一個列表“低於”第二個列表時,您的比較器無法處理這種情況。 您的比較器僅返回 0 和 1。我認為 TreeSet 使用二分搜索或任何更快的方法來查找對象並檢查特定對象是否為集合。 像這樣的方法需要明確定義一個對象是大於還是小於其他對象。 如果 TreeSet 使用相等對象與集合中的每個對象進行原始比較,則您的比較器將起作用。 在排序結構中,找到對象的方法更復雜、更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM