【问题标题】:How to get index of an item in java.util.Set如何在 java.util.Set 中获取项目的索引
【发布时间】:2010-12-09 07:27:03
【问题描述】:

我知道 Set 和 List 之间的区别(唯一与允许重复,未排序/排序等)。我正在寻找的是一个保持元素有序的集合(这很容易),但我还需要能够恢复插入元素的索引。因此,如果我插入四个元素,那么我希望能够知道其中一个元素的插入顺序。

MySet<String> set = MySet<String>();
set.add("one");
set.add("two");
set.add("three");
set.add("four");

int index = set.getIndex("two");

因此,在任何给定时刻,我都可以检查是否已经添加了字符串,并获取集合中字符串的索引。有没有这样的,还是需要我自己实现?

【问题讨论】:

  • 如果您同时删除“one”,您希望 getIndex 返回什么?
  • 如果它不在 commons-collections commons.apache.org/collections 那么我认为你必须自己实现它
  • 好吧,既然集合应该是有序的,如果一个元素被移除,那么所有插入的元素都将被重新分配一个位置。我想如果我对不存在或已被删除的元素执行 getIndex,我会得到 -1。

标签: java set


【解决方案1】:

创建 Set 后,只需将其转换为 List 并从 List 中按索引获取:

Set<String> stringsSet = new HashSet<>();
stringsSet.add("string1");
stringsSet.add("string2");

List<String> stringsList = new ArrayList<>(stringsSet);
stringsList.get(0); // "string1";
stringsList.get(1); // "string2";

【讨论】:

  • 我认为问题是如何获取集合中项目的索引,而不是如何通过索引获取项目。
  • stringsList.indexOf("string1");
【解决方案2】:

Util 类中的小型静态自定义方法会有所帮助:

 public static <T> int getIndex(Set<T> set, T value) {
   int result = 0;
   for (T entry:set) {
     if (entry.equals(value)) return result;
     result++;
   }
   return -1;
 }
  

如果您需要/想要一个Set 并提供getIndex() 方法的类,我强烈建议您实现一个新的Set 并使用装饰器模式:

 public class IndexAwareSet<T> implements Set {
   private Set<T> set;
   public IndexAwareSet(Set<T> set) {
     this.set = set;
   }

   // ... implement all methods from Set and delegate to the internal Set

   public int getIndex(T entry) {
     int result = 0;
     for (T entry:set) {
       if (entry.equals(value)) return result;
       result++;
     }
     return -1;
   }
 }

【讨论】:

  • 感谢您的示例。一个问题,在遍历 Set 之前调用 contains(T entry) 是否值得?
  • @Jose - 取决于集合。 HashSet:是的,包含 O(1) 中的运行。 TreeSet - 不,因为包含与 getIndex 算法完全相同的 O(n) 。所以它需要两倍的时间。
  • 请注意,如果您装饰一个 HashSet,您将无法获得所需的行为(即根据插入顺序进行索引)。您必须提供一个迭代顺序与插入顺序匹配的 Set。 LinkedHashSet 可以做到。
  • -1:我仍然看不到这个响应如何回答原始问题。不能保证索引会反映插入顺序。对 TreeSet 或 HashSet 的迭代不一定遵循插入顺序。
  • @Eyal - (1) TreeSet 不保留其他提到的插入顺序,OP 应该使用LinkedHashSet。 (2) 两个 sn-ps/examples 都可以与 any Set 实现一起使用。你只需要说new IndexAwareSet(new LinkedHashSet()) 它应该可以按预期工作。顺便说一句 - 我提到 HashSet 和 TreeSet 只是为了在他的评论中回答 Jose 的问题,而不是在答案中。
【解决方案3】:

您可以扩展 LinkedHashSet 添加所需的 getIndex() 方法。实施和测试它需要 15 分钟。只需使用迭代器和计数器遍历集合,检查对象是否相等。如果找到,则返回计数器。

【讨论】:

  • TreeSet 不会保持元素添加的顺序,它们会按照自然顺序排列。
【解决方案4】:

如何将字符串添加到值是索引的哈希表中:

  Hashtable<String, Integer> itemIndex = new Hashtable<>();
  itemIndex.put("First String",1);
  itemIndex.put("Second String",2);
  itemIndex.put("Third String",3);

  int indexOfThirdString = itemIndex.get("Third String");

【讨论】:

    【解决方案5】:

    一种解决方案(虽然不是很漂亮)是使用 Apache 常见的 List/Set 突变

    import org.apache.commons.collections.list.SetUniqueList;
    
    final List<Long> vertexes=SetUniqueList.setUniqueList(new LinkedList<>());
    

    这是一个没有重复的列表

    https://commons.apache.org/proper/commons-collections/javadocs/api-3.2.2/index.html?org/apache/commons/collections/list/SetUniqueList.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      • 2019-01-25
      • 2011-01-28
      • 1970-01-01
      • 2020-02-25
      • 2016-09-25
      • 1970-01-01
      相关资源
      最近更新 更多