我有一个包含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元素。如何迭代整个降序集合?
更新 我确信在检查期间没有修改此套件
答案 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。 因此,迭代器决定taxom0在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));
}