linkedHashSet 中重复项的索引

Duplicate item's index in linkedHashSet

我正在向 LinkedHashSet 添加一些值,并基于 add() 方法的输出,即 true/false,我正在执行其他操作。

如果 Set 包含重复元素,则 returns 为 false,在这种情况下,我想知道 Set 中重复元素的索引,因为我需要使用该索引别的地方。作为一个 'linked' 集合,必须有一些方法来获取索引,但我在 Set/LinkedHashSet API.

中找不到任何这样的东西

LinkedHashSet 未明确索引 本身 。如果您需要索引,对此类应用程序使用 Set 通常是错误抽象 and/or 糟糕编程的标志。 LinkedHashSet 仅保证您可预测的迭代顺序, 正确索引元素。在这种情况下,您 应该 使用 List,因为这是为您提供索引保证的接口。但是,您可以使用多种方法推断索引,例如(不推荐,请注意):

a) 在集合中使用索引迭代(例如使用 for 循环),查找重复项并在找到时中断;获取索引的复杂度为 O(n),

Object o; // this is the object you want to add to collection
if ( !linkedHashSet.add(o) ) {
    int index = 0;
    for( Object obj : linkedHashSet ) {
        if ( obj == o ) // or obj.equals(o), depending on your code's semantics
            return index;
        index++;
    }
}

b) 使用 .toArray() 并找到数组中的元素,例如通过

Object o; // this is the object you want to add to collection
int index;
if ( !linkedHashSet.add(o) )
    index = Arrays.asList(linkedHashSet.toArray()).indexOf(o);

同样,获取索引的复杂度为 O(n)。

两者都会导致严重的运行时损失(第二种解决方案在效率方面显然更差,因为它会在您每次查找索引时创建一个数组;创建一个镜像集合的并行数组会更好)。总而言之,我在你的例子中看到了一个破碎的抽象。你说

I need to use that index somewhere else

...如果确实是 情况,使用 Set 本身 99% 的时间都是错误的。

另一方面,您可以使用 Map(例如 HashMap),其中包含 [index,Object](或 [Object,index],具体取决于具体用途案例)对在里面。它需要一些重构,但 IMO 是执行此操作的首选方法。对于大多数操作,它会为您提供与 LinkedHashSet 相同的复杂度顺序,但您基本上免费获得索引的时间为 O(1)(Java 的 HashSet 使用 HashMap 内部无论如何,所以你不会失去任何内存替换 HashSetHashMap).

更好的方法是使用 class 显式 处理整数映射 - 参见 HashMap and int as key for more information; tl;dr - http://trove.starlight-systems.com/TIntObjectHashMapTObjectIntHashMap ,为您提供可能的此类操作的最佳速度。