在TreeSet中排列元素

时间:2010-11-20 20:20:00

标签: java sorting collections treeset

我知道java树集不能有相同的元素,因此即使它们具有相同的“值”,我也必须以某种方式将元素与另一元素区分开来。我希望能够对元素进行排名,并且我注意到一个有趣的行为。

TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>()
        {
            public int compare(Integer arg0, Integer arg1) 
            {
                if(arg0 > arg1)
                    return -1;
                return 1;
            }
        });

        set.add(40);
            set.add(20);
        set.add(30);
            set.add(20);

        for(Integer i:set)
        {
            System.out.println("Rank: "+(set.headSet(i,false).size()+1)+" Number: "+i);
        } 

这是输出:

Rank: 1 Number: 40
Rank: 3 Number: 30
Rank: 5 Number: 20
Rank: 5 Number: 20

这是耳机应该做的事情:

Returns a view of the portion of this set whose elements are less than (or equal to, if inclusive is true) toElement. The returned set is backed by this set, so changes in the returned set are reflected in this set, and vice-versa. The returned set supports all optional set operations that this set supports. 

我按降序排序,所以我认为它应该相反。第一个元素没有任何大于它,所以它返回0,然后我加1来获得它的排名。第二个元素有一个大于它的东西,所以我认为它应该返回1,添加1个使2.这有点奇怪。我想我犯了一个简单的错误。我还需要弄清楚如何处理这两个20。我希望他们的排名都是3,但树集认为他们的数字不同。我想我可以使用TreeMultiSet或其他一些第三方库。

2 个答案:

答案 0 :(得分:2)

这两个问题是一个问题,因为您的比较实施违反了the contract

  

实现者必须确保所有x和y的sgn(x.compareTo(y))== -sgn(y.compareTo(x))。

如果x = 20且y = 20,则在实现中不是这样:1 == - (1)

如果是arg0.equals(arg1),则可以通过返回0来解决此问题。

注意:对于Integer类的对象,您需要使用“equals”而不是“==”。

答案 1 :(得分:0)

  

我想我可以使用TreeMultiSet或其他一些第三方库。

由于您违反了套装的基本特征之一,我会说您不应该使用SetTreeSet,至少应该直接使用List或{{1}}。选项:

  • 使用{{1}}(并使用Collections.sort()和Collections.binarySearch()保存它)
  • 使用IdentityHashMap,只使用该值作为映射到自身的键
  • 使用TreeMap并将值映射到出现次数(提取到列表并根据需要排序)
  • 使用第三方库(Bag或MultiSet)
  • 实施自己的包/ multiset

由于我不太了解编程环境,因此很难提出具体的解决方案,但希望这会带来一些其他想法。