Java 从NavigableSet获取特定索引处的元素

Java 从NavigableSet获取特定索引处的元素,java,collections,set,median,Java,Collections,Set,Median,我有一个NavigableSet,我想得到它的中间对象 因为它是一个NavigableSet,所以我知道它是经过排序的,因此我知道它的中值要么是中间元素,要么是两个中间元素的算术中间 因此,我想访问set.size()/2处的元素,但是NavigableSet接口不允许我访问 有没有一种简单的方法可以在不必手动遍历集合的情况下获取特定元素?是集合不允许从特定索引获取元素。但是我认为如果你把它转换成一个数组,那么你就能够实现你所需要的。我尝试了以下示例代码,看看是否有帮助: NavigableSe

我有一个
NavigableSet
,我想得到它的中间对象

因为它是一个
NavigableSet
,所以我知道它是经过排序的,因此我知道它的中值要么是中间元素,要么是两个中间元素的算术中间

因此,我想访问
set.size()/2
处的元素,但是
NavigableSet
接口不允许我访问


有没有一种简单的方法可以在不必手动遍历集合的情况下获取特定元素?

是集合不允许从特定索引获取元素。但是我认为如果你把它转换成一个数组,那么你就能够实现你所需要的。我尝试了以下示例代码,看看是否有帮助:

NavigableSet set = new TreeSet<Integer>();
set.add(new Integer(5));
set.add(new Integer(4));
set.add(new Integer(3));
set.add(new Integer(2));
set.add(new Integer(1));
Integer medianIndex = set.size()/2;
System.out.println(set.toArray()[medianIndex]);
NavigableSet集=新树集();
set.add(新的整数(5));
set.add(新的整数(4));
set.add(新整数(3));
set.add(新整数(2));
set.add(新整数(1));
整数medianIndex=set.size()/2;
System.out.println(set.toArray()[medianIndex]);
产出:3


字符串按字母顺序排列,请看以下小示例:

编辑:现在它真的做到了你想要的

public static void main(String[] args) {
    NavigableSet<String> set = new TreeSet<String>();
    set.add("gamma");
    set.add("alpha");
    set.add("beta");

    System.out.println(Arrays.toString(set.toArray()));

    int indexOfGamma = set.headSet("gamma").size();

    System.out.println(indexOfGamma);

    System.out.println(get(set, set.first(), indexOfGamma));
}

public static String get(NavigableSet<String> set, String e, int index) {
    if (index == 0) {
        return e;
    }
    return get(set, set.higher(e), --index);
}

我没有用更大的数据集做任何基准测试,但我想它应该表现得相当不错。
higher()
方法应该直接指向树中的下一个元素。

除了遍历设置的“索引”次数之外,我找不到其他方法。但是,由于我们知道集合的大小,我们可以通过使用升序和降序迭代将其速度提高到至少一半:

public static <T> T getInNavigableSetByIndex(NavigableSet<T> set, int index) {
    Objects.requireNonNull(set);

    final int size = set.size();

    if (index < 0 || index >= size) {
        throw new IndexOutOfBoundsException();
    }

    final boolean descend = index >= size / 2;
    final Iterator<T> itr = descend ? set.descendingIterator() : set.iterator();
    final int stepCount = descend ? size - index : index + 1;
    T object = null;

    for (int i = 0; i < stepCount && itr.hasNext(); i++) {
        object = itr.next();
    }

    return object;
}
public static T getInNavigableSetByIndex(NavigableSet集合,int索引){
对象。requirennull(集合);
最终整数大小=set.size();
如果(索引<0 | |索引>=大小){
抛出新的IndexOutOfBoundsException();
}
最终布尔下降=索引>=大小/2;
最终迭代器itr=Descent?set.descendingIterator():set.Iterator();
最终整数步数=下降?大小-索引:索引+1;
T object=null;
对于(int i=0;i
将其转换为数组的操作比遍历数组的操作成本更高,因此我不会选择此解决方案。抱歉,但我看不出这与我的问题有什么关系。你是对的,我的建议正好相反:查找集合中某个对象的索引。我道歉。
public static <T> T getInNavigableSetByIndex(NavigableSet<T> set, int index) {
    Objects.requireNonNull(set);

    final int size = set.size();

    if (index < 0 || index >= size) {
        throw new IndexOutOfBoundsException();
    }

    final boolean descend = index >= size / 2;
    final Iterator<T> itr = descend ? set.descendingIterator() : set.iterator();
    final int stepCount = descend ? size - index : index + 1;
    T object = null;

    for (int i = 0; i < stepCount && itr.hasNext(); i++) {
        object = itr.next();
    }

    return object;
}