Search code examples
javajava-8java-stream

How to get index of findFirst() in java 8?


I have the following code:

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();

I need to know what is the index of that first returned element, since I need to edit it inside of entries ArrayList. As far as I know get() returns the value of the element, not a reference. Should I just use

int indexOf(Object o)

instead?


Solution

  • You can't in a straightforward way - streams process elements without context of where they are in the stream.

    However, if you're prepared to take the gloves off...

    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
    

    The use of an int[], instead of a simple int, is to circumvent the "effectively final" requirement; the reference to the array is constant, only its contents change.

    Note also the use of a method reference "2"::equals instead of a lambda e -> e.equals("2"), which not only avoids a possible NPE (if a stream element is null) and more importantly looks way cooler.


    A more palatable (less hackalicious) version:

    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