繁体   English   中英

如何获取Set的第n个元素

[英]How to get nth element of a Set

更具体地说:如何获取LinkedHashSet的第n个元素(具有可预测的迭代顺序)? 我想检索插入此Set的第n个元素( 尚未存在 )。

使用List更好吗:

List<T> list = new ArrayList<T>(mySet);
T value = list.get(x); // x < mySet.size()

toArray(T [] a)方法:

T [] array = mySet.toArray(new T[mySet.size()]);
T value = array[y]; // y < mySet.size()

除了(可能是轻微的)性能差异之外,还有什么值得注意的? 任何明显的赢家?

编辑1

注意: 为什么我想要最后插入的元素并不重要,重要的是我想要它。 LinkedHashSet是专门选择的,因为它“定义了迭代排序,这是元素插入集合(插入顺序)的顺序。请注意,如果将元素重新插入集合中,插入顺序不会受到影响。”

编辑2

这个问题似乎已经演化成的任何是否讨论Set的实现可以永远保留原始的广告订单。 所以我在http://pastebin.com/KZJ3ETx9上提供了一些简单的测试代码来表明是的,LinkedHashSet确实保留了插入顺序(与其迭代顺序相同),就像它的Javadoc声称的那样。

编辑3

修改了问题的描述,以便每个人都不太专注于检索Set的最后一个元素(我原本以为问题的标题就足够了 - 显然我错了)。

此方法基于更新的要求返回第n个元素,而不仅仅是最后一个元素。 如果源是例如具有标识符mySet的Set,则可以通过nthElement(mySet, mySet.size()-1)选择最后一个元素。

如果nSet的大小相比较小,则此方法可能比例如转换为ArrayList更快。

  /**
   * Return an element selected by position in iteration order.
   * @param data The source from which an element is to be selected
   * @param n The index of the required element. If it is not in the 
   * range of elements of the iterable, the method returns null.
   * @return The selected element.
   */
  public static final <T> T nthElement(Iterable<T> data, int n){
    int index = 0;
    for(T element : data){
      if(index == n){
        return element;
      }
      index++;
    }
    return null;
  }

如果要检索最后一个元素,我将使用LinkedHashSet的迭代器:

Iterator<T> it = linkedHashSet.iterator();
T value = null;

while (it.hasNext()) {
    value = it.next();
}

循环执行值将引用最后一个元素。

所以我决定采用@Juvanis的答案略有不同。

要获取LinkedHashSet中的第n个元素:

Iterator<T> itr = mySet.iterator();
int nth = y;
T value = null;

for(int i = 0; itr.hasNext(); i++) {
    value = itr.next();
    if (i == nth) {
        break;
    }
}

代码版本2:

public class SetUtil {

    @Nullable
    public static <T> T nthElement(Set<T> set, int n) {
        if (null != set && n >= 0 && n < set.size()) {
            int count = 0;
            for (T element : set) {
                if (n == count)
                    return element;
                count++;
            }
        }
        return null;
    }
}

注意:通过一些细微的修改,上述方法可用于所有Iterables<T>

这避免了确保SetList保持同步的开销,并且还避免了每次都必须创建新的List (这将比任何算法复杂度更耗时)。

显然我使用Set来确保唯一性,我宁愿避免冗长的解释为什么我需要索引访问。

你可以使用下面的解决方案,这里我在HashSet中添加了ModelClass的对象。

ModelClass m1 = null;
int nth=scanner.nextInt();
for(int index=0;index<hashset1.size();index++){
    m1 = (ModelClass) itr.next();
    if(nth == index) {
        System.out.println(m1);
        break;
    }
}

Set是无序的,因此插入的最后一个元素的信息将丢失。 你不能这样插入最后一个元素。 所以不要首先使用Set,或者,如果你真的想跟踪最后一个元素,创建一个包含这样的类的类

class mySetAndLast extends Set{
   T last;
   Set<T> mySet;       
}

现在的问题是'插入的最后一个元素'是什么。 想象一下你的装置是空的

-> insert x -> ok, x is the last inserted 
-> insert y (y!=x) -> ok: y is the last inserted 
-> insert x -> ? 

现在是最后插入的x还是y? x没有插入,因为y是插入的最后一个元素,x已经是该集合的元素,另一方面,x从用户的角度来看是最后插入的..

为了您自己的内部目的,您可以从任何List实现中“破解”您自己的Set

public class ListSet<E> extends ArrayList<E> implements Set<E> {
    @Override
    public boolean add(E item) {
        return contains(item) ? false : super.add(item);
    }

    // ... and same for add(int, E), addAll(...), etc.
}

这个例子很慢(添加O(n)),但是,正如您实现它的那样,您可以根据您的规范使用更智能的代码contains()返回到它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM