Де індекс масиву Java's Array?


199

Я, мабуть, пропускаю щось дуже очевидне, але я шукав у всьому і не можу знайти цей метод.

Відповіді:


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");

Eclipse не знайде цю бібліотеку імпорту.
Омор

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 може містити рядок, в якій, можливо, ви хочете знайти індекс.

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 не перевантажуються і приймають лише параметр Object як параметр.

Якщо ваш масив відсортований , вам пощастило, тому що клас Arrays визначає серію перевантажень методу binarySearch, який знайде індекс шуканого елемента з найкращою можливою продуктивністю (O (log n) замість O (n ), останнє - те, чого можна очікувати від послідовного пошуку, здійсненого indexOf). Є чотири міркування:

  1. Масив повинен бути відсортований або в природному порядку, або в порядку порівняння, який ви надаєте в якості аргументу, або, принаймні, всі елементи, які є "меншими за", повинні надходити перед цим елементом у масиві та всіма елементами, які "ключ більше", ключ повинен надходити після цього елемента в масиві;

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

  3. Якщо ваш масив містить кілька елементів, рівних ключу, те, що ви отримуєте від binarySearch, не визначене; це відрізняється від indexOf, який поверне перше виникнення, і lastIndexOf, який поверне останнє явище.

  4. Мабуть, може здатися, що масив булевих сортується, якщо спочатку він містить усі помилки, а потім усі істини, але це не враховується. Немає переопрацювання методу binarySearch, який приймає масив булевих, і вам доведеться там зробити щось розумне, якщо ви хочете, щоб продуктивність O (log n) виявляла, де в масиві з’являється перша правда, наприклад, використовуючи масив Булеві та константи Булеві. ФАЛЬСІ та Булеві. TRUE.

Якщо ваш масив не є сортованим та не примітивним типом , ви можете використовувати методи indexOf та lastIndexOf Список, використовуючи метод asList java.util.Arrays. Цей метод поверне обгортку інтерфейсу AbstractList навколо вашого масиву. Він передбачає мінімальні накладні витрати, оскільки не створює копію масиву. Як уже згадувалося, цей метод не перевантажений, тому він буде працювати лише на масивах посилальних типів.

Якщо маса не впорядкований і тип масиву є примітивним , ви не пощастило з API Java. Напишіть свій власний цикл або власний метод статичної корисності, який, безумовно, матиме переваги у виконанні порівняно з підходом 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 .


11

У Java ArrayListє indexOfметод. Масиви Java не мають такого методу.


26
Не просто ArrayList- у кожної Java Listє indexOf().
Метт Бал

6

Я не пригадую "indexOf" на масивах, окрім кодування його для себе ... хоча ви, ймовірно, можете використовувати один із багатьох java.util.Arrays#binarySearch(...)методів (див. Масиви javadoc ), якщо ваш масив містить примітивні типи


5

Інтерфейс списку має метод indexOf (), і ви можете отримати Список зі свого масиву методом ArL's asList (). Крім того, сам Array не має такого методу. Він має метод binarySearch () для відсортованих масивів.


4

Самі масиви не мають такого методу. Список, однак, робить: indexOf


2
Не просто ArrayList- у кожної Java Listє indexOf().
Метт Бал

Так, я щойно вказав ArrayList, тому що це може бути найближче до того, що шукала ОП :)
Ігор



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: Спочатку це мутує вихідний масив для сортування, який ми можемо не хотіти. По-друге, він дає відповідь wrt відсортованому масиву, а не оригінальний масив, який, ймовірно, те, що ми хочемо (якби ми хотіли, щоб відповідь wrt відсортувала масив, він би вже був відсортований). По-третє, оскільки сортування є O (n log n), це повільніше, ніж просто проходження масиву лінійно. Тож ця відповідь є і неправильною, і неефективною.
Джеймі

початковий індекс був втрачений при використанні на місці сортування.
Downhillski
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.