Где Java Array indexOf?

198

Я, должно быть, упускаю что-то очень очевидное, но я искал повсюду и не могу найти этот метод.

Джейми
источник

Ответы:

234

Есть несколько способов сделать это с помощью Arraysслужебного класса.

Если массив не отсортирован и не является массивом примитивов:

java.util.Arrays.asList(theArray).indexOf(o)

Если массив является примитивом и не отсортирован, следует использовать решение, предложенное одним из других ответов, например, ответами Керема Байдогана , Эндрю МакКинлея или Мишакса . Приведенный выше код будет компилироваться, даже если theArrayон примитивен (возможно, выдает предупреждение), но, тем не менее, вы получите совершенно неверные результаты.

Если массив отсортирован, вы можете использовать бинарный поиск производительности:

java.util.Arrays.binarySearch(theArray, o)
Джеффри Хантин
источник
3
Я почти уверен, что этот ответ неверен по крайней мере для Java 1.6: download.oracle.com/javase/6/docs/api/java/util/… asList преобразует список аргументов в список, а не сам аргумент.
Александру
11
@Alexandru Ellipsis - это синтаксический сахар. Если у вас есть типизированный аргумент T..., фактический тип времени выполнения аргумента равен T[], и передача ноля или более параметров типа Tприводит к тому, что они помещаются во вновь созданный массив и передаются. Если передаваемый параметр уже имеет тип T[], синтаксический сахар игнорируется.
Джеффри Хантин
7
Я понимаю вашу точку зрения. Однако решение ( .indexOf) недопустимо для примитивов.
Александру
53
Поскольку никто не упомянул: Arrays.asList использует уже существующий массив в качестве основы. (То есть не стоит беспокоиться о создании копии.)
Джошуа Голдберг,
4
@Notinlist Об этом тоже думали парни из Java. Используйте Arrays.toList(list).sublist(from,to).indexOf(o)для поиска элемента в диапазоне [from, to).
Марио Карнейро
62

У массива нет indexOf()метода.

Может быть, этот ArrayUtilsметод Apache Commons Lang - это то, что вы ищете

import org.apache.commons.lang3.ArrayUtils;

String[] colours = { "Red", "Orange", "Yellow", "Green" };

int indexOfYellow = ArrayUtils.indexOf(colours, "Yellow");
Керем Байдоган
источник
Затмение не найти эту библиотеку импорта.
Больше
21

Для примитивов, если вы хотите избежать упаковки , у Guava есть помощники для массивов примитивов, например, Ints.indexOf (массив int [], int target)

Эндрю Маккинли
источник
Все остальные решения создают новые строки или списки или просто обрабатывают отдельные элементы. Chars.indexOf в Guava позволяет получить индекс массива в массиве. Это правильное решение.
HappyEngineer
18

Здесь ничего нет. Либо используйте java.util.List*, либо вы можете написать свой собственный indexOf():

public static <T> int indexOf(T needle, T[] haystack)
{
    for (int i=0; i<haystack.length; i++)
    {
        if (haystack[i] != null && haystack[i].equals(needle)
            || needle == null && haystack[i] == null) return i;
    }

    return -1;
}

* Вы можете сделать один из вашего массива, используя Arrays#asList()

Мэтт Болл
источник
2
Использование Tвводит в заблуждение. Он не обеспечивает никакой безопасности типов, легко ошибиться, это безопасный тип ... лучше использовать Объект
Venkata Raju
4
@VenkataRaju, использование T здесь заставляет оба параметра метода быть одного типа. Это полезно
гонадарский
5
@gonadarian Не совсем. Оба этих компиляций просто отлично: indexOf("str", new Object[] {});,indexOf(new Object(), new String[] {});
Venkata Раджу
1
@VenkataRaju Да, действительно. Ваш пример ничего не доказывает, так как String - это Object ... так что, очевидно, массив Object может содержать String, индекс которой вы можете захотеть найти.
1
@ ghert85 Другой пример: indexOf("str", new Date[] {}),indexOf(new Date(), new String[] {})
Venkata Раджу
15

В отличие от C #, где у вас есть метод Array.IndexOf , и JavaScript, где у вас есть метод indexOf , у API Java ( в частности, Arrayи Arraysклассов) такого метода нет.

Этот метод indexOf (вместе с его дополнением lastIndexOf) определен в интерфейсе java.util.List . Обратите внимание, что indexOf и lastIndexOf не перегружены и принимают только объект в качестве параметра.

Если ваш массив отсортирован , вам повезло, потому что класс Arrays определяет серию перегрузок метода binarySearch, который найдет индекс искомого элемента с наилучшей возможной производительностью (O (log n) вместо O (n) ), последнее является тем, что вы можете ожидать от последовательного поиска, выполняемого indexOf). Есть четыре соображения:

  1. Массив должен быть отсортирован либо в естественном порядке, либо в порядке компаратора, который вы предоставляете в качестве аргумента, или, по крайней мере, все элементы, которые «меньше», должны находиться перед этим элементом в массиве и всеми элементами, которые «больше» чем ключ должен идти после этого элемента в массиве;

  2. Тест, который вы обычно делаете с indexOf, чтобы определить, находится ли ключ в массиве (проверьте, не является ли возвращаемое значение -1), не выполняется с двоичным поиском. Вам необходимо убедиться, что возвращаемое значение не меньше нуля, поскольку возвращаемое значение будет указывать на то, что ключ отсутствует, но индекс, по которому его можно было бы ожидать, если бы он существовал;

  3. Если ваш массив содержит несколько элементов, которые равны ключу, то, что вы получаете из binarySearch, не определено; это отличается от indexOf, который будет возвращать первое вхождение, и lastIndexOf, который будет возвращать последнее вхождение.

  4. Массив логических значений может показаться отсортированным, если он сначала содержит все ложные значения, а затем все истины, но это не считается. Нет переопределения метода binarySearch, который принимает массив логических значений, и вам придется делать что-то умное там, если вы хотите производительность O (log n) при обнаружении, где в массиве появляется первое значение true, например, с использованием массива Boolean и константы Boolean.FALSE и Boolean.TRUE.

Если ваш массив не отсортирован и не является примитивным типом , вы можете использовать методы ListOf и lastIndexOf в List, вызывая метод asList из java.util.Arrays. Этот метод возвращает интерфейсную оболочку AbstractList вокруг вашего массива. Это требует минимальных накладных расходов, поскольку не создает копию массива. Как уже упоминалось, этот метод не перегружен, поэтому он будет работать только с массивами ссылочных типов.

Если массив не отсортирован и тип массива является примитивным , вы не повезло с API Java. Напишите собственный цикл for или собственный метод статической утилиты, который, безусловно, будет иметь преимущества в производительности по сравнению с подходом asList, который включает в себя некоторые накладные расходы на создание экземпляра объекта. В случае, если вы обеспокоены тем, что написание перебора для цикла, который повторяется по всем элементам массива, не является элегантным решением, примите, что это именно то, что делает Java API, когда вы вызываете indexOf. Вы можете сделать что-то вроде этого:

public static int indexOfIntArray(int[] array, int key) {
    int returnvalue = -1;
    for (int i = 0; i < array.length; ++i) {
        if (key == array[i]) {
            returnvalue = i;
            break;
        }
    }
    return returnvalue;
}

Если вы хотите избежать написания своего собственного метода, рассмотрите возможность его использования из среды разработки, такой как Guava. Там вы можете найти реализацию indexOf и lastIndexOf .

Mishax
источник
11

У Java ArrayListесть indexOfметод. У Java-массивов такого метода нет.

Джеймс
источник
26
Не только ArrayList- каждая Java Listимеет indexOf().
Мэтт Болл
6

Я не помню "indexOf" для массивов, кроме как для его кодирования ... хотя вы, вероятно, могли бы использовать один из многих java.util.Arrays#binarySearch(...)методов (см. Javadoc для массивов ), если ваш массив содержит примитивные типы

Kellindil
источник
5

Интерфейс List имеет метод indexOf (), и вы можете получить List из вашего массива с помощью метода asList () Array. Кроме этого, у самого массива нет такого метода. У него есть метод binarySearch () для отсортированных массивов.

Майк Йокей
источник
4

Сами массивы не имеют этого метода. Список, однако, делает: indexOf

Игорь
источник
2
Не только ArrayList- каждая Java Listимеет indexOf().
Мэтт Болл
Да, я только что указал ArrayList, потому что это может быть ближе всего к тому, что искал ОП :)
Игорь
2

В java-массивах нет прямой функции indexOf.

Гамбо
источник
0

Ответ Джеффри Хантина хорош, но у него есть некоторые ограничения, если это делает то или иное к этому ...

Вы можете написать свой собственный метод расширения, и он всегда работает так, как вы хотите.

Lists.indexOf(array, x -> item == x); // compare in the way you want

И вот ваше расширение

public final class Lists {
    private Lists() {
    }

    public static <T> int indexOf(T[] array, Predicate<T> predicate) {
        for (int i = 0; i < array.length; i++) {
            if (predicate.test(array[i])) return i;
        }
        return -1;
    }

    public static <T> int indexOf(List<T> list, Predicate<T> predicate) {
        for (int i = 0; i < list.size(); i++) {
            if (predicate.test(list.get(i))) return i;
        }
        return -1;
    }

    public interface Predicate<T> {
        boolean test(T t);
    }
}
М.Казем Ахгари
источник
-4
int findIndex(int myElement, int[] someArray){
 int index = 0;
 for(int n: someArray){
   if(myElement == n) return index;
   else index++;
 }
}

Примечание: вы можете использовать этот метод для массивов типа int, вы также можете использовать этот алгоритм для других типов с небольшими изменениями

Вивек Гупта
источник
1
-1: Сначала это изменяет исходный массив для сортировки, который мы можем не хотеть. Во-вторых, он дает ответ по отсортированному массиву, а не по исходному массиву, который, скорее всего, нам нужен (если бы мы хотели получить ответ по отсортированному массиву, он уже был бы отсортирован). В-третьих, поскольку сортировка - это O (n log n), это медленнее, чем просто проходить массив линейно. Так что этот ответ и неправильный, и неэффективный.
Джейми
исходный индекс был утерян при использовании сортировки на месте.
Даунхиллски,