Find all indexes of a value in a List

11,704

Solution 1

Explanation

The method List#indexOf only returns the index of the first found matching element. From its documentation:

Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. [...]

But you want all, therefore you also need to iterate all elements.

Also note that calling List#contains is not necessary since List#indexOf also answers this question, it returns -1 if not found. In fact in an ArrayList both calls are very expensive (they iterate from left to right until found) so you shouldn't use unnecessary statements if they are such expensive.


Solution

Instead just iterate all elements and collect the ones that match:

ArrayList<String> author = ...
String needle = ...

// Collect matches
List<Integer> matchingIndices = new ArrayList<>();
for (int i = 0; i < author.size(); i++) {
    String element = author.get(i);

    if (needle.equals(element)) {
        matchingIndices.add(i);
    }
}

// Print matches
matchingIndices.forEach(System.out::println);

Or you may use some of the very convenient methods of the Stream API. Stream#filter (documentation) for example:

List<Integer> matchingIndices = IntStream.range(0, author.size())
    .filter(i -> needle.equals(author.get(i))) // Only keep those indices
    .collect(Collectors.toList());

Solution 2

You could go over the entire list and save all the indexes that match the search term. Java 8's steams give you a pretty elegant way of doing this:

int[] indexes =
    IntStream.range(0, names.size())
             .filter(i -> names.get(i).equals(search))
             .toArray();
Share:
11,704

Related videos on Youtube

PeterSchmit
Author by

PeterSchmit

Updated on June 04, 2022

Comments

  • PeterSchmit
    PeterSchmit almost 2 years

    I'm trying to search an ArrayList for a user input. I've managed to create a search that prints the index of the first occurrence from within the list.

    I'm having trouble trying to get the rest of the indexes that the item are stored.

    Here is the code I have got so far to print the first index of search:

    if (names.contains(search)) {
        System.out.println("name found!");
        System.out.println(names.indexOf(search));
    }
    

    I understand that a loop needs to be added. But I am having trouble trying to formulate it.

    Example

    ArrayList<String> names = new ArrayList<String>();
    names.add("Bob");
    names.add("Jerry");
    names.add("Bob"); 
    names.add("Mick");
    

    Say search = "Bob". My expected result would be {0,2}. Instead, I am only able to get the index of the first occurrence (0).

    assert allIndexesOf(names, "Bob").equals(List.of(0, 2));
    
    [...]
    
    private List<Integer> allIndexesOf(List<?> list, Object o) {
      // How can this be implemented?
    }
    

    How can I get all indexes that match the search string?

    • JB Nizet
      JB Nizet over 6 years
      Forget programming for a while. Imagine you have 10 drawers, numbered from 0 to 9, and want to find all the drawers containing a blue sheet of paper, and write their number on a sheet of paper. How do you do?
    • ollie
      ollie over 6 years
      Okay - seems like a school assignment, so I will be very high level to help with the logic. for all items in the list, if the item at the current index is what I'm looking for, then add to a different list the index, else don't do anything and move on
    • Zabuzard
      Zabuzard over 6 years
      Questions asking for homework help must include a summary of the work you've done so far to solve the problem, and a description of the difficulty you are having solving it (help center, How to Ask). - You have done all that, nice!
    • M. Justin
      M. Justin about 3 years
      Voting to reopen. The "duplicate" question is about characters within a string, not elements within a list. While they have similar APIs, they are not identical. Further, there are other solutions (e.g. streams) that may be more appropriate than indexOf for Lists.
  • Zabuzard
    Zabuzard over 6 years
    But then he looses the indices. I think he wants to collect the indices, not the elements (since they are equal).
  • Mureinik
    Mureinik over 6 years
    @Zabuza you should read my solution again - it does collect the indexes.
  • S.R.I
    S.R.I over 6 years
    In the present form, I think this is a poor question. As JB Nizet said, there's a bigger question to be tackled here.
  • Zabuzard
    Zabuzard over 6 years
    Ah indeed, thought you had done a map and thus loosing track of the indices.
  • Zabuzard
    Zabuzard over 6 years
    Avoid comparing String with ==. The result is probably not what you expected. Exchange it with String#equals and it will be fine.
  • Zabuzard
    Zabuzard over 6 years
  • Silvan
    Silvan over 6 years
    Thanks for the hint. I edited my post.
  • M. Justin
    M. Justin about 3 years
    @S.R.I I think it's a fine question. I actually had this come up today in a decidedly non-homework problem.
  • Delrius Euphoria
    Delrius Euphoria over 2 years
    Wouldn't it be better to start from first index of occurrence of item rather than from 0th position?
  • Zabuzard
    Zabuzard over 2 years
    @CoolCloud Sure, if you know that index beforehand already... but if your suggesting to use something like indexOf, you are not really gaining anything. Since that method will also just simply iterate.