如何在java 8中获取findFirst()的索引?

And*_*rei 8 java java-8 java-stream

我有以下代码:

ArrayList <String> entries = new ArrayList <String>();

entries.add("0");
entries.add("1");
entries.add("2");
entries.add("3");

String firstNotHiddenItem = entries.stream()
                    .filter(e -> e.equals("2"))
                    .findFirst()
                    .get();
Run Code Online (Sandbox Code Playgroud)

我需要知道第一个返回元素的索引是什么,因为我需要在条目内编辑它ArrayList.据我所知,get()返回元素的值,而不是引用.我应该使用

int indexOf(Object o)
Run Code Online (Sandbox Code Playgroud)

代替?

Flo*_*own 7

您可以使用IntStream类似的方法获取元素的索引:

int index = IntStream.range(0, entries.size())
                     .filter(i -> "2".equals(entries.get(i)))
                     .findFirst().orElse(-1);
Run Code Online (Sandbox Code Playgroud)

但是你应该使用List::indexOf首选的方法,因为它更简洁,更具表现力并计算相同的结果.

  • `List.indexOf`和使用`filter`和`findFirst`的流的关键区别在于`indexOf`使用列表元素类的`equals`方法,而流方法允许你搜索基于与元素*等式*无关的潜在复杂谓词. (7认同)

Boh*_*ian 6

您不能以直接的方式-流处理元素而没有上下文在流中的位置。

但是,如果您准备脱下手套...

int[] position = {-1};

String firstNotHiddenItem = entries.stream()
        .peek(x -> position[0]++)  // increment every element encounter
        .filter("2"::equals)
        .findFirst()
        .get();

System.out.println(position[0]); // 2
Run Code Online (Sandbox Code Playgroud)

使用int[],而不是简单int,是为了规避“有效最终”的要求;对数组的引用常量,仅其内容会更改。

还请注意使用的方法的参考"2"::equals,而不是一个拉姆达e -> e.equals("2"),这不仅避免了可能NPE(如果流元件是null),更重要的看起来的方式冷却器。


一个更可口(较少hackalicious)的版本:

AtomicInteger position = new AtomicInteger(-1);

String firstNotHiddenItem = entries.stream()
        .peek(x -> position.incrementAndGet())  // increment every element encounter
        .filter("2"::equals)
        .findFirst()
        .get();

position.get(); // 2
Run Code Online (Sandbox Code Playgroud)