如何获取 LinkedHashSet 的第 n 个元素

问题描述 投票:0回答:7

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

Set
尚未存在)。

使用

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

这个问题似乎已经演变成关于any

Set
实现是否可以ever保留原始插入顺序的讨论。因此,我在 http://pastebin.com/KZJ3ETx9 上放置了一些简单的测试代码,以表明是的,LinkedHashSet 确实保留了其 Javadoc 声称的插入顺序(与其迭代顺序相同)。

编辑3

修改了问题的描述,这样每个人就不会太专注于检索

Set
的最后一个元素(我原本认为问题的标题足以暗示 - 显然我错了)。

java collections set linkedhashset
7个回答
6
投票

此方法基于更新的要求,返回第 n 个元素,而不仅仅是最后一个元素。如果来源是例如带有标识符

mySet
的 Set,可以通过
nthElement(mySet, mySet.size()-1)
选择最后一个元素。

如果

n
Set
的大小相比较小,则此方法可能比例如转换为
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;
  }

3
投票

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

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

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

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


2
投票

所以我决定对@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>

这避免了确保

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

显然,我使用

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


1
投票

您可以使用以下解决方案, 这里我在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;
    }
}

1
投票

使用流的简单方法:

mySet.stream().skip(x).findFirst()
        .orElseThrow(IndexOutOfBoundsException::new);

0
投票

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 是最后插入的..


0
投票

为了您自己的内部目的,您可以从任何

Set
实现中“破解”您自己的
List

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()

© www.soinside.com 2019 - 2024. All rights reserved.