indexOf()
Finds the position of the first (or, with lastIndexOf, the last) equal element, returning -1 when there is none.
int indexOf(Object o)- Added in Java Java 1.2
Parameters
| Parameter | Type | Description |
|---|---|---|
$o | Object | The value to search for, compared with equals. |
Return value
intThe index of the first element equal to o, or -1 if no element matches. lastIndexOf returns the index of the last match.
Errors
ClassCastException if the type is incompatible and the list checks it (optional). NullPointerException if o is null and the list does not allow nulls, as with List.of.
indexOf(o) walks the list from the front and returns the index of the first element equal to o. lastIndexOf(o) walks from the back and returns the last match. When nothing matches, both return -1. Like contains, they compare with equals and run in linear time.
Always handle -1
The return value is an int, not an Optional, so a missing element is easy to overlook. Passing -1 straight to get, set or remove throws IndexOutOfBoundsException, often far from where the lookup happened. Check the result before you use it, and turn a missing value into a clear error, such as a 400 response that names the missing CSV column.
If you only need to know whether the element is there, call contains. Use indexOf when the position itself matters: which column holds a field, where to insert next to an element, or which slot to update.
Duplicates
Lists allow duplicates, so indexOf and lastIndexOf can differ. If they return different values for the same argument, the element appears at least twice. That is a cheap duplicate check for small lists, for example a CSV header that names the same column twice.
Equality rules apply
- Objects without
equalsonly match the exact same instance. List<Long>.indexOf(5)searches for anIntegerand returns -1. Write5L.indexOf(null)works onArrayListbut throwsNullPointerExceptiononList.oflists.
To find the first element matching a condition rather than an exact value, indexOf cannot help. Use a loop, or IntStream.range(0, list.size()).filter(i -> ...).findFirst(), which returns an OptionalInt.
If you look up positions by name many times, for example for every row of a large import, build a Map from name to index once from the header and read from that.
Example
When to use it
- Mapping CSV or spreadsheet header names to column positions during an import.
- Rejecting an upload whose header names the same column twice.
- Keeping a short most-recently-used list of pages or searches per user.
Frequently asked questions
What does indexOf return if the element is not in the list?
It returns -1. Check for that before using the result as an index, because get(-1) throws IndexOutOfBoundsException.
How do I find the index of an element matching a condition?
indexOf only matches by equals. Loop with an index, or use IntStream.range(0, list.size()).filter(i -> condition(list.get(i))).findFirst(), which gives an OptionalInt.
More examples
Finding CSV columns by header name
The header decides which position holds each field, so imports keep working when columns are reordered. The -1 check turns a missing column into a readable error.
void main() {
List<String> header = List.of("id,name,email".split(","));
String row = "7,Ada,[email protected]";
List<String> cells = List.of(row.split(","));
for (String column : List.of("email", "phone")) {
int i = header.indexOf(column);
if (i < 0) {
IO.println("missing column: " + column);
} else {
IO.println(column + " = " + cells.get(i));
}
}
}
// Output:
// email = [email protected]
// missing column: phoneSpotting duplicates
An element whose first and last positions differ appears more than once. This is quadratic, so keep it for short lists such as headers.
void main() {
List<String> fields = List.of("id", "email", "name", "email");
List<String> dupes = new ArrayList<>();
for (String f : fields) {
if (fields.indexOf(f) != fields.lastIndexOf(f) && !dupes.contains(f)) {
dupes.add(f);
}
}
IO.println("duplicated: " + dupes);
}
// Output:
// duplicated: [email]Moving a recent item to the front
indexOf finds the existing entry so it can be removed by position before being added again at the front. A missing item gives -1 and is simply added.
void touch(List<String> recent, String item) {
int i = recent.indexOf(item);
if (i >= 0) {
recent.remove(i);
}
recent.addFirst(item);
}
void main() {
List<String> recent = new ArrayList<>(List.of("/home", "/orders", "/profile"));
touch(recent, "/orders");
IO.println(recent);
touch(recent, "/help");
IO.println(recent);
}
// Output:
// [/orders, /home, /profile]
// [/help, /orders, /home, /profile]
Discussion