简体   繁体   English

在常量时间内通过索引从列表中获取多个元素

[英]Get multiple elements from list by indices in constant time

What is the best way to get multiple elements from a list by their indices in constant time? 在常量时间内通过索引从列表中获取多个元素的最佳方法是什么?

If I've an array: 如果我有一个数组:

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");

And I've an list/array with indices: 我有一个带索引的列表/数组:

List<Integer> indices = new ArrayList<>();
indices.add(0);
indices.add(2);
indices.add(3);

How can I get a,c,d in constant time? 如何在恒定时间内获得a,c,d? I need something like this: 我需要这样的东西:

List<String> filtered = list.filterByIndex(indices);
filtered.stream().forEach(x -> System.out.print(x));
// output:"acd"

UPDATE: The printing of the items doesn't have to be in constant time of course, only the collecting of items. 更新:物品的印刷当然不必是恒定的时间,只是收集物品。 The code above of printing the elements is just for demonstrating purposes only. 上面打印元素的代码仅用于演示目的。

I suggest: 我建议:

    List<String> filtered = indices.stream()
            .map(list::get)
            .collect(Collectors.toList());

The result is the desired: 结果是理想的:

[a, c, d]

Assuming the list has constant-time access (as an ArrayList has), this runs in time that is linear in the number of elements requested (length of indices ), but does not increase with the length of the list list . 假设列表具有常量时间访问(如ArrayList ),这将在请求的元素数量( indices长度)中呈线性,但不会随列表list的长度而增加。 As has been discussed in comments, this is the best we can do. 正如评论中所讨论的那样,这是我们能做的最好的事情。

Edit: Honestly I don't know whether the collecting step above is in linear time in the number of collected elements. 编辑:老实说我不知道​​上面的收集步骤是否在收集元素数量的线性时间内。 Possibly extensions of list capacity cost time, and probably this doesn't take more than linear time. 可能是列表容量成本增加的时间延长,并且这可能不会超过线性时间。 If we need to be sure, we need to collect this way instead: 如果我们需要确定,我们需要采用这种方式:

            .collect(Collectors.toCollection(() -> new ArrayList<>(indices.size())));

This makes sure a list with appropriate capacity is allocated from the outset so no extensions will be needed. 这样可以确保从一开始就分配具有适当容量的列表,因此不需要扩展。

To create a list: 要创建列表:

List<String> filtered = new ArrayList<>();
indices.forEach(index -> filtered.add(list.get(index)));

System.out.println(filtered);

Stream and map solution 流和地图解决方案

List<String> filtered = indices.stream()
        .map(index -> list.get(index))
        .collect(Collectors.toList());

If you need only string you can do it with StringBuilder 如果只需要字符串,可以使用StringBuilder来完成

StringBuilder sb = new StringBuffer();
indices.forEach(index -> sb.append(list.get(index)));

System.out.println(sb.toString());

You might do something like this: 你可能会这样做:

IntStream.range(0, list.size())
       .boxed()
       .filter(indices::contains)
       .map(list::get)
       .forEach(System.out::println);

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

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