查找List <long>中与某个元素</long>对应的所有索引的方法

时间:2013-10-06 08:07:52

标签: java list arraylist indexing indices

假设我有一个名为long的{​​{1}}和一个名为X的{​​{1}},其中包含List<Long>作为众多元素中的一个非唯一元素。我需要应用什么方法来查找foo中与X对应的所有索引。这个foo不一定是排序的(但如果有一个需要排序的特定方法,那么一个好的答案可能会假设这一点 - 我对排序和未排序的情况感兴趣)。

例如,这可能是问题设置:

X

我希望该方法接受foo作为参数并返回包含索引long X = 5L List<Long> foo = new ArrayList<Long>(); foo.add(4L); foo.add(5L); foo.add(5L); foo.add(6L); foo.add(7L); X的列表(或其他对象),因为它们对应于{的位置{1}}内的{1}}。

中平凡,

1

但我想要更快的方式,因为我的2非常长。

3 个答案:

答案 0 :(得分:1)

如果列表已排序,请在点击更大的内容后停止。如果列表实现允许随机访问(即ArrayList),则使用二进制搜索。由于列表包含重复项,因此您需要从找到的元素向前和向后扫描,以确保获得所有索引。

如果搜索与更新的比率很大(搜索次数多于更新次数),那么您可以在Map<Long,List<Integer>>中维护一个索引,该索引将每个值映射到值列表中显示的索引列表。在原始列表更新时,您必须编写代码来维护索引。

在评估绩效时,建立和维护索引的成本可以在搜索中摊销。如果列表在创建后永远不会更新,并且搜索次数很多,那么这将是一个明显的赢家。

但是,除非列表很大(> 10000)并且查询数量很大(> 1,000,000),否则可能不值得。

答案 1 :(得分:1)

如果使用GS Collections,则可以对源列表和索引列表使用原始列表,因此不会产生装箱原始值的成本。以下代码可以在Java 8中使用lambdas和您的示例:

long X = 5L;
LongArrayList list = LongArrayList.newListWith(4L, 5L, 5L, 6L, 7L);
IntArrayList indices = new IntArrayList();
list.forEachWithIndex((each, index) -> { if (each == X) indices.add(index);});
Assert.assertEquals(IntArrayList.newListWith(1, 2), indices);   

在Java 7中,它看起来如下:

long X = 5L;
LongArrayList list = LongArrayList.newListWith(4L, 5L, 5L, 6L, 7L);
IntArrayList indices = new IntArrayList();
list.forEachWithIndex(new LongIntProcedure() 
{
    public void value(long each, int index) 
    {
        if (each == X) indices.add(index);
    }
});
Assert.assertEquals(IntArrayList.newListWith(1, 2), indices);

注意:我是GS Collections的开发人员。

答案 2 :(得分:0)

试试这个解决方案:

int firstIndex = foo.indexOf(X);

int count = Collections.frequency(foo, X);

如果您的List 已排序,则您有2个职位:firstIndexfirstIndex + 1

从你的例子:

long X = 5L
List<Long> foo = new ArrayList<Long>();
foo.add(4L);
foo.add(5L);
foo.add(5L);
foo.add(6L);
foo.add(7L);

int firstIndex = foo.indexOf(X); // 1
int count = Collections.frequency(foo, X); // 2

List<Long> output = new ArrayList<Long>();

for(int i=firstIndex; i<count; i++ ){
  output.add(i);
}