为什么descendingSet小于原始集?

时间:2014-06-24 07:08:01

标签: java collections set

我有一个包含191个元素的集合:

NavigableSet<Taxon> _set = new ConcurentSkipListSet<>();
...
_set.size(); // 191
_set.descendingSet().size(); // also 191
_set.descendingSet().toArray().length; // 53
_set.toArray().length; // 191

Taxon.java:

class Taxon implements Comparable<Taxon> {

    public final int x;
    public final int y;
    public final int r;
    public final List<Long> ips;

    public Taxon(int x, int y, int r, List<Long> ips) {
        this.x = x;
        this.y = y;
        this.r = r;
        this.ips = ips;
    }

    @Override
    public int compareTo(Taxon o) {
        return this.ips.size() > o.ips.size() ? 1 : -1;
    }

}

为什么_sel.descendingSet()。toArray()更小?当我迭代_sel.descendingSet()时,它会突破53元素。如何迭代整个降序集合?

更新 我确信在检查期间没有修改此套件

2 个答案:

答案 0 :(得分:0)

此问题是由于compareTo()方法的错误实现造成的。 这里没有遵循CompareTo()合约。

合同规定如果x.comparedTo(y)== - (y.comparedTo(x))。让我们考虑以下示例 假设我们为类Taxon提供了以下对象及其插入顺序,如下所述

insertion order for Taxon   ips List size 
taxon0                      3
taxon1                      1
taxon2                      1
taxon3                      3
taxon4                      1

taxon0.comparedTo(taxom3)为-1,taxon3.compareTo(taxon0)也为-1。表示taxon0小于taxom3,taxom3小于taxom0,这是错误的。

_set.descendingSet()。size()和_set.descendingSet()。toArray()。length返回不同的结果,因为_set.descendingSet()。toArray()方法在内部使用迭代器来获取集合的当前快照。 Iterator在内部使用compareTo()方法迭代集合。 size()方法不使用迭代器,只计算元素的数量。因此,它们都有不同的返回值。

ConcurrentSkipListSet按其自然顺序或基于Comparator排列其元素。当我们将taxom对象添加到ConcurrentSkipListSet中时,它们按以下顺序排列(在此处跳过索引节点)

头 - &gt; taxon4 - &gt; taxon2 - &gt; taxon1 - &gt; taxon3 - &gt; taxon0 - &gt;空

_set.descendingSet()。toArray()。length在taxon0设置指针,然后taxom0.comparedTo(taxon3)返回-1。 因此,迭代器决定tax​​om0在taxom3之前,并且在迭代期间跳过taxom3。迭代者开始明白这一点 taxom1在taxom0之前。之后指针转移到taxom1并且明智的taxon1被比作taxom4(不是taxom2,因为跳过列表算法,向下和向右指针)和taxom1.comparedTo(taxom4)说taxom1小于taxom4,这与实际安排和指针移动到头。因此迭代器只返回两个元素。

这里我们有两种长度的ips List 1,3。因此只有两个要素。在您的示例中,您可能有91种不同长度的ips列表。由于compareTo()方法,所有重复项都被跳过。

您可以在compareTo()方法中添加更多属性,以根据您的业务逻辑决定Taxon的自然顺序。

答案 1 :(得分:0)

下面是迭代整个降序集合的答案。 将其转换为列表,现在您可以轻松地迭代它......:)

 List<Taxon> taxonList = new ArrayList<Taxon>(_set);
 System.out.println(taxonList.size());
 int size = taxonList.size();
 for(int i = size-1; i<=0; i--)
  {
     System.out.println(taxonList.get(i));
  }