Edward Peters
Edward Peters

Reputation: 4062

Stream Way to get index of first element matching boolean

I have a List<Users>. I want to get the index of the (first) user in the stream with a particular username. I don't want to actually require the User to be .equals() to some described User, just to have the same username.

I can think of ugly ways to do this (iterate and count), but it feels like there should be a nice way to do this, probably by using Streams. So far the best I have is:

int index = users.stream()
    .map(user -> user.getName())
    .collect(Collectors.toList())
    .indexOf(username);

Which isn't the worst code I've ever written, but it's not great. It's also not that flexible, as it relies on there being a mapping function to a type with a .equals() function that describes the property you're looking for; I'd much rather have something that could work for arbitrary Function<T, Boolean>

Anyone know how?

Upvotes: 101

Views: 156616

Answers (8)

Shivani
Shivani

Reputation: 1

Ways to all the index Iterate over the index and get all the index

IntStream.range(0, list.size())
                .filter(i -> Objects.equals(list.get(i), target)).forEach(System.out::println);

Upvotes: -1

Shivam
Shivam

Reputation: 11

Find If present then Return result based on that.

  1. Find out if element is present or not.
  2. If present return index else return -1
    AtomicInteger index = new AtomicInteger();
    int result =  Arrays.stream(nums)
                         .peek((num) -> index.incrementAndGet())
                         .filter(num -> num == target)
                         .findFirst()
                         .orElse(-1);
    return result == -1 ? result : index.get()-1;
AtomicInteger index = new AtomicInteger();

Is starting from 1 so we want to get index so we are subtracting 1 from index

More Shorter

return Arrays.stream(nums)
                     .peek((num) -> index.incrementAndGet())
                     .filter(num -> num == target)
                     .findFirst()
                     .orElse(-1) == -1 ? -1 : index.get()-1;

Upvotes: 1

AmanSinghal
AmanSinghal

Reputation: 2504

Try This:

IntStream.range(0, users.size())
    .filter(userInd-> users.get(userInd).getName().equals(username))
    .findFirst()
    .getAsInt();

Upvotes: 29

Donald Raab
Donald Raab

Reputation: 6686

There is the detectIndex method in the Eclipse Collections library which takes a Predicate.

int index = ListIterate.detectIndex(users, user -> username.equals(user.getName()));

If you have a method on User class which returns boolean if username matches you can use the following:

int index = ListIterate.detectIndexWith(users, User::named, username);

Note: I a committer for Eclipse Collections

Upvotes: 3

karmakaze
karmakaze

Reputation: 36154

Using Guava library: int index = Iterables.indexOf(users, u -> searchName.equals(u.getName()))

Upvotes: 23

hibour
hibour

Reputation: 61

A solution without any external library

AtomicInteger i = new AtomicInteger(); // any mutable integer wrapper
int index = users.stream()
    .peek(v -> i.incrementAndGet())
    .anyMatch(user -> user.getName().equals(username)) ? // your predicate
    i.get() - 1 : -1;

peek increment index i while predicate is false hence when predicate is true i is 1 more than matched predicate => i.get() -1

Upvotes: 6

vsminkov
vsminkov

Reputation: 11250

Occasionally there is no pythonic zipWithIndex in java. So I came across something like that:

OptionalInt indexOpt = IntStream.range(0, users.size())
     .filter(i -> searchName.equals(users.get(i)))
     .findFirst();

Alternatively you can use zipWithIndex from protonpack library

Note

That solution may be time-consuming if users.get is not constant time operation.

Upvotes: 133

Sergey Tselovalnikov
Sergey Tselovalnikov

Reputation: 6036

You can try StreamEx library made by Tagir Valeev. That library has a convenient #indexOf method.

This is a simple example:

List<User> users = asList(new User("Vas"), new User("Innokenty"), new User("WAT"));
long index = StreamEx.of(users)
        .indexOf(user -> user.name.equals("Innokenty"))
        .getAsLong();
System.out.println(index);

Upvotes: 11

Related Questions