Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/389.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否有一个Java 8版本的内置Python enumerate?_Java_Python_Java 8 - Fatal编程技术网

是否有一个Java 8版本的内置Python enumerate?

是否有一个Java 8版本的内置Python enumerate?,java,python,java-8,Java,Python,Java 8,3年前,这里也提出了一个类似的问题: 我非常感谢listIterator()解决方案。尽管如此,我现在仍在大量使用新的streams和Lambda(在JDK 8中引入)并想知道:有没有一种优雅的方法来获取当前正在处理的元素的索引?下面是我的,但我并不觉得它特别吸引人 IntStream.range(0, myList.size()) .mapToObj(i -> doSthWith(myList.get(i), i)); 这可能有一些解决办法 您可以使用一个Atomi

3年前,这里也提出了一个类似的问题:

我非常感谢
listIterator()
解决方案。尽管如此,我现在仍在大量使用新的streams和Lambda(在JDK 8中引入)并想知道:有没有一种优雅的方法来获取当前正在处理的元素的索引?下面是我的,但我并不觉得它特别吸引人

IntStream.range(0, myList.size())
         .mapToObj(i -> doSthWith(myList.get(i), i));

这可能有一些解决办法

您可以使用一个
AtomicInteger
,每次通过流的元素时都会增加它

final AtomicInteger atom = new AtomicInteger(); 
list.stream().forEach(i -> System.out.println(i+"-"+atom.getAndIncrement()));
或者使用另一个流中的迭代器作为索引(有点像您最初的想法),但由于不在列表中调用
get
,因此效率更高

final Iterator<Integer> a = IntStream.range(0, list.size()).iterator();
list.stream().forEach(i -> System.out.println(i+"-"+a.next()));
final迭代器a=IntStream.range(0,list.size()).Iterator();
list.stream().forEach(i->System.out.println(i+“-”+a.next());
嗯,我不确定是否还有其他更好的替代方案(当然),但这就是我目前的想法


注意,它假设您没有使用并行流。在后一种情况下,不可能像这样获得元素与其列表中原始索引的映射。

您提供的链接中的python示例是:

final Iterator<Integer> a = IntStream.range(0, list.size()).iterator();
list.stream().forEach(i -> System.out.println(i+"-"+a.next()));
>>> numbers = ["zero", "one", "two"]
>>> for i, s in enumerate(numbers):
...     print i, s
... 
0 zero
1 one
2 two
有几种方法可以使用Java 8实现相同的输出,例如:

String[] numbers = {"zero", "one", "two"};
IntStream.range(0, numbers.length)
        .mapToObj(i -> i + " " + numbers[i])
        .forEach(System.out::println);
哪些产出:

0 zero
1 one
2 two

这个问题以前有人问过几个问题。关键的观察结果是,除非您有完美的大小和分割信息(基本上,如果您的源是一个数组),否则这将是一个仅顺序的操作

你提出的“不吸引人”的答案是:

IntStream.range(0, myList.size())
         .mapToObj(i -> doSthWith(myList.get(i), i));

myList
是一个
ArrayList
或其他具有快速O(1)索引get操作的列表时,它实际上非常有效,并且可以干净地并行化。所以我认为这没什么问题

如果您想要更清晰的语法,只需结束一些通话:

public class IndexedValue<T> {
    public final int index;
    public final T value;
    public IndexedValue(int index, T value) {
        this.index = index;
        this.value = value;
    }
}

public class Itertools {
    public static <T> Stream<IndexedValue<T>> enumerate(ArrayList<T> lst) {
        return IntStream.range(0, lst.size())
            .mapToObj(i -> new IndexedValue<T>(i, lst.get(i)));
    }
}

如果您想要一个高效的LinkedList解决方案,那么您需要在不调用LinkedList.get()的情况下处理该问题。

如果您想要一个同样适用于非
随机访问
列表的解决方案,您可以编写一个简单的实用程序方法:

public static <T> void forEach(List<T> list, BiConsumer<Integer,? super T> c) {
    Objects.requireNonNull(c);
    if(list.isEmpty()) return;
    if(list instanceof RandomAccess)
        for(int i=0, num=list.size(); i<num; i++)
            c.accept(i, list.get(i));
    else
        for(ListIterator<T> it=list.listIterator(); it.hasNext(); ) {
            c.accept(it.nextIndex(), it.next());
    }
}

然后,像
forEach(list,(s,i)->System.out.println(i+“\t”+s))一样使用
..

尽管它不太常用,
enumerate
可用于任何iterable(您只需找到索引的用途,因为它不再对应于序列)。我怀疑Java解决方案也可以毫无问题地完成同样的工作,尽管它将非常复杂,足以在自己的类中提取并重新使用(而不是像您的示例中那样在一行中)。这还取决于您使用的列表的具体实现,但在LinkedList上调用get是O(n)。所以不确定这个解决方案是否值得。这就是为什么我如此希望一个“哦,你就是这样做的”的解决方案来自一个有更高知识的人。我显然不想向任何人推荐上述方法@RadosławŁazarz一个解决方法是执行
final AtomicInteger atom=new AtomicInteger();list.stream().forEach(i->System.out.println(i+“-”+atom.getAndIncrement())任何使用第三方库(如apache collections/google Guava)的更干净的解决方案?事实上,如果使用并行流,您(无声地)只会得到错误的答案。坏主意!无需使用
list.stream().forEach(…)
。不仅
list.forEach(…)
更简单,它还保证尊重元素顺序,而
list.stream().forEach(…)
则不是(与
list.stream().forEachOrdered(…)
public static <T> void forEach(List<T> list, ObjIntConsumer<? super T> c) {
    Objects.requireNonNull(c);
    if(list.isEmpty()) return;
    if(list instanceof RandomAccess)
        for(int i=0, num=list.size(); i<num; i++)
            c.accept(list.get(i), i);
    else
        for(ListIterator<T> it=list.listIterator(); it.hasNext(); ) {
            c.accept(it.next(), it.previousIndex());
    }
}