3

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?

M. Justin
  • 14,487
  • 7
  • 91
  • 130
PeterSchmit
  • 49
  • 1
  • 1
  • 4
  • 1
    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? – JB Nizet Dec 03 '17 at 20:08
  • 1
    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 – ollie Dec 03 '17 at 20:10
  • 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], [ask]). - You have done all that, nice! – Zabuzard Dec 03 '17 at 20:24
  • 1
    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. – M. Justin Feb 09 '21 at 18:20

3 Answers3

2

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());
Zabuzard
  • 25,064
  • 8
  • 58
  • 82
  • Wouldn't it be better to start from first index of occurrence of item rather than from 0th position? – Delrius Euphoria Dec 03 '21 at 12:59
  • @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. – Zabuzard Dec 03 '21 at 19:05
1

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();
M. Justin
  • 14,487
  • 7
  • 91
  • 130
Mureinik
  • 297,002
  • 52
  • 306
  • 350
0
for (int i = 0;i<author.size();i++){
  if(author.get(i).equals(searchTerm)) {
    System.out.println("Author found!");
    System.out.println(i);
  }
}
Silvan
  • 93
  • 1
  • 8
  • Avoid comparing `String` with `==`. The result is probably not what you expected. Exchange it with `String#equals` and it will be fine. – Zabuzard Dec 03 '17 at 20:23
  • More on this [SO: How do I compare strings in Java?](https://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) – Zabuzard Dec 03 '17 at 20:28
  • 1
    Thanks for the hint. I edited my post. – Silvan Dec 03 '17 at 22:48