2010-11-20 75 views
2

我知道一个java treeset不能有相同的元素,所以我必须以某种方式区分一个元素,即使它们具有相同的“值”。我希望能够排列元素,并且我注意到一个有趣的行为。TreeSet中的排名元素

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,但是treeset认为他们是不同的数字。我想我可以使用TreeMultiSet或其他第三方库。

回答

0

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

既然你违反的一组的基本特征之一,我说你不应该一个SetTreeSet,至少直接使用。选项:

  • 使用List(并保持与排序Collections.sort()和Collections.binarySearch())
  • 使用IdentityHashMap,只使用该值作为键映射到自身
  • 使用一个TreeMap和值映射到OCCURENCES的#(提取物的清单和排序需要的话)
  • 使用第三方库(袋或者多集)
  • 实现自己的包/多集

因为我对编程上下文了解不多,所以很难提出具体的解决方案,但希望能够提出一些其他想法。

+0

这是一个很好的观点。我可以尝试使用常规列表并保持排序 – JPC 2010-11-21 00:10:16

2

两个20是一个问题,因为你的比较实施违反the contract

实现程序必须确保SGN(则x.compareTo(Y))== -sgn(y.compareTo(X))的所有x和y。

如果x = 20和y = 20,这是不是真的在你的实行:1 == - (1)

您可以通过返回0解决这个问题,如果arg0.equals(ARG1) 。

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

+0

如果它们相等,我不能返回0,因为我仍然需要它们在集合中。 – JPC 2010-11-21 00:08:23

+0

如果你想要多个相同的条目,那么你应该使用一个List而不是滥用Set。 Collections.sort()将为您排序。 – 2010-11-21 08:55:38