Trying to find all occurrences of an object in Arraylist, in java
Asked Answered
P

6

21

I have an ArrayList in Java, and I need to find all occurrences of a specific object in it. The method ArrayList.indexOf(Object) just finds one occurrence, so it seems that I need something else.

Perugia answered 16/12, 2012 at 10:54 Comment(9)
By "specific object" do you mean the references should be equals or ==Annis
In my case it's an ArrayList of integers, so both of them can be used. But actually are there cases that only one of them can be used?Perugia
@missrg.. Always use equals to compare object contents. Whether Integer, or any other objects.Gripper
@Rohit Thanks for the advice :) Can you please explain why it is better?Perugia
@missrg.. == operator only compares the value of reference, and not the actual content of the objects. Thus you compare references to two different object with same value, you would get false result with == and true result with equals method. You can get immense resource on this topic on internet. just google - "equals v/s =="Gripper
Not really an answer since I don't know if you can use Guava, but it's quite straightforward with it: Iterables.filter(list, Predicates.equalTo(object))Husbandry
@Rohit Thanks soo much, I hadn't figure out this difference :)Perugia
" I need to find all occurances of a specific object in it. " it clearly says what he want!Tanhya
'equals' may look at the contents of two objects and compare the values in those objects. If you == then they are the same specific object, not just two objects which happen to contain the same values. This means that while new Integer(1234).equals(new Integer(1234)) it is the case that new Integer(1234) != new Integer(1234) as they are not the same object.Annis
W
23

I don't think you need to be too fancy about it. The following should work fine:

static <T> List<Integer> indexOfAll(T obj, List<T> list) {
    final List<Integer> indexList = new ArrayList<>();
    for (int i = 0; i < list.size(); i++) {
        if (obj.equals(list.get(i))) {
            indexList.add(i);
        }
    }
    return indexList;
}
Wallasey answered 16/12, 2012 at 11:39 Comment(2)
This means you will have a list of values which are all the equal. indexOf return the location (not the value)Annis
The code I wrote will give you the indices of the equal objects, as indicated by the variable name "indexList".Execratory
P
6

I suppose you need to get all indices of the ArrayList where the object on that slot is the same as the given object.

The following method might do what you want it to do:

public static <T> int[] indexOfMultiple(List<T> list, T object) {
    List<Integer> indices = new ArrayList<>();
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i).equals(object)) {
            indices.add(i);
        }
    }
    // ArrayList<Integer> to int[] conversion
    int[] result = new int[indices.size()];
    for (int i = 0; i < indices.size(); i++) {
        result[i] = indices.get(i);
    }
    return result;
}

It searches for the object using the equals method, and saves the current array index to the list with indices. You're referring to indexOf in your question, which uses the equals method to test for equality, as said in the Java documentation:

Searches for the first occurence of the given argument, testing for equality using the equals method.


Update

Using Java 8 streams it'll become much easier:

public static <T> int[] indexOfMultiple(List<T> list, T object) {
    return IntStream.range(0, list.size())
        .filter(i -> Objects.equals(object, list.get(i)))
        .toArray();
}
Prurigo answered 16/12, 2012 at 11:18 Comment(1)
Well, I mentioned indexOf method because I was hoping there may be a similar method appropriate for my case, like it is indexOf(char,int) for Strings. Thanks for the answer and the explanation :)Perugia
B
4

This is similar to this answer, just uses stream API instead.

List<String> words = Arrays.asList("lorem","ipsum","lorem","amet","lorem");
String str = "lorem";
List<Integer> allIndexes =
        IntStream.range(0, words.size()).boxed()
                .filter(i -> words.get(i).equals(str))
                .collect(Collectors.toList());
System.out.println(allIndexes); // [0,2,4]
Breakable answered 2/3, 2017 at 14:13 Comment(0)
T
2

iterate over all elements, don't break the loop

each element of the ArrayList compare with your object ( arrayList.get(i).equals(yourObject) )

if match than the index ( i ) should be stored into a separate ArrayList ( arraListMatchingIndexes).

Sometimes in this way I do a "remove all", when I need the positions too.

I hope it helps!

Tanhya answered 16/12, 2012 at 10:58 Comment(0)
O
2

Do

for (int i=0; i<arrList.size(); i++){
    if (arrList.get(i).equals(obj)){
        // It's an occurance, add to another list
    }
}

Hope this helps.

Octahedral answered 16/12, 2012 at 10:59 Comment(1)
@Tanhya depends. Sometimes, you need to check if the certain instance of an object does not occur multiple times in an array, then you will use ==, if equal object means "contain the same data", then it"s the .equals() versionIncreasing
R
0

Java 8+

If you want to precompute the indexes of every value in the List, Collectors.groupingBy can be used on an IntStream of indexes.

import java.util.stream.Collectors;
import java.util.stream.IntStream;
//...
List<Integer> list = Arrays.asList(1, 2, 2, 1, 4, 5, 4, 3, 4, 5, 0);
final Map<Integer, List<Integer>> indexMap = IntStream.range(0, list.size()).boxed()
        .collect(Collectors.groupingBy(list::get));
//Map of item value to List of indexes at which it occurs in the original List

Then, to find all the indexes of a specific value, use get on the Map in constant time.

List<Integer> indexes = indexMap.get(value);

Demo

Rina answered 13/3, 2021 at 23:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.