Gdzie jest indeks Java Array indexOf?

198

Muszę przegapić coś bardzo oczywistego, ale przeszukałem wszystko i nie mogę znaleźć tej metody.

Jamie
źródło

Odpowiedzi:

234

Istnieje kilka sposobów na osiągnięcie tego celu Arrays klasy narzędziowej.

Jeśli tablica nie jest posortowana i nie jest tablicą operacji podstawowych:

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

Jeśli tablica jest prymitywna i nie jest posortowana, należy skorzystać z rozwiązania oferowanego przez jedną z pozostałych odpowiedzi, takich jak Kerem Baydoğan , Andrew McKinlay lub Mishax . Powyższy kod zostanie skompilowany, nawet jeślitheArray jest prymitywny (prawdopodobnie emituje ostrzeżenie), ale mimo to otrzymasz całkowicie niepoprawne wyniki.

Jeśli tablica jest posortowana, możesz skorzystać z binarnego wyszukiwania wydajności:

java.util.Arrays.binarySearch(theArray, o)
Jeffrey Hantin
źródło
3
Jestem prawie pewien, że ta odpowiedź jest błędna przynajmniej dla java 1.6: download.oracle.com/javase/6/docs/api/java/util/... asList przekształca listę argumentów w listę, a nie w sam argument.
Alexandru
11
@Alexandru Ellipsis obsługuje cukier syntaktyczny. Jeśli masz wpisany argument T..., rzeczywistym typem argumentu w czasie wykonywania jest T[], a przekazanie zera lub więcej parametrów typu Tpowoduje, że są one pakowane w nowo zbudowaną tablicę i przekazywane. Jeśli przekazywany parametr jest już typu T[], cukier syntaktyczny jest pomijany.
Jeffrey Hantin
7
Rozumiem co masz na myśli. Rozwiązanie ( .indexOf) nie jest jednak poprawne dla prymitywów.
Alexandru
53
Ponieważ nikt nie wspomniał: Arrays.asList używa już istniejącej tablicy jako podkładu. (Tj. Nie ma obaw, że powstanie kopia).
Joshua Goldberg
4
@Notinlist Chłopaki z Javy też o tym pomyśleli. Służy Arrays.toList(list).sublist(from,to).indexOf(o)do wyszukiwania elementu w zakresie [from, to).
Mario Carneiro
62

Tablica nie ma indexOf()metody.

Może ta ArrayUtilsmetoda Apache Commons Lang jest tym, czego szukasz

import org.apache.commons.lang3.ArrayUtils;

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

int indexOfYellow = ArrayUtils.indexOf(colours, "Yellow");
Kerem Baydoğan
źródło
Eclipse nie znajduje tej biblioteki importu.
Omore
21

W przypadku prymitywów, jeśli chcesz uniknąć boksowania, Guava ma pomocniki dla prymitywnych tablic, np. Ints.indexOf (int [] tablica, int cel)

Andrew McKinlay
źródło
Wszystkie pozostałe rozwiązania tworzą nowe ciągi znaków lub listy lub obsługują pojedyncze elementy. Chars.indexOf Guava pozwala uzyskać indeks tablicy w tablicy. To jest właściwe rozwiązanie.
HappyEngineer
18

Nie ma żadnego. Albo użyj java.util.List*, albo możesz napisać własny 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;
}

* możesz zrobić jeden z tablicy za pomocą Arrays#asList()

Matt Ball
źródło
2
Używanie Tjest mylące. Nie zapewnia żadnego rodzaju bezpieczeństwa, łatwo pomylić, jest bezpieczny typu ... lepsze wykorzystanie Obiekt
Venkata Raju
4
@VenkataRaju, użycie T tutaj wymusza, aby oba parametry metody były tego samego typu. To się przydaje.
gonadarian
5
@ Gonadarian Nie bardzo. Oba te kompilacji dobrze: indexOf("str", new Object[] {});,indexOf(new Object(), new String[] {});
Venkata Raju
1
@VenkataRaju Tak naprawdę. Twój przykład niczego nie dowodzi, ponieważ łańcuch znaków jest obiektem ... więc tablica obiektów może oczywiście zawierać łańcuch znaków, którego indeks możesz chcieć znaleźć.
1
@ ghert85 Inny przykład: indexOf("str", new Date[] {}),indexOf(new Date(), new String[] {})
Venkata Raju
15

W przeciwieństwie do C #, w którym masz metodę Array.IndexOf , i JavaScript, w którym masz metodę indexOf , interfejs API Java ( ArrayiArrays w szczególności klasy) nie ma takiej metody.

Ta metoda indexOf (wraz z uzupełnieniem lastIndexOf) jest zdefiniowana w interfejsie java.util.List . Zauważ, że indexOf i lastIndexOf nie są przeciążone i przyjmują obiekt jako parametr.

Jeśli twoja tablica jest posortowana , masz szczęście, ponieważ klasa Arrays definiuje serię przeciążeń metody binarySearch, która znajdzie indeks poszukiwanego elementu z najlepszą możliwą wydajnością (O (log n) zamiast O (n ), przy czym ten ostatni jest tym, czego można oczekiwać od wyszukiwania sekwencyjnego przeprowadzonego przez indexOf). Istnieją cztery kwestie:

  1. Tablica musi być posortowana albo w naturalnej kolejności, albo w kolejności komparatora, który podasz jako argument, lub przynajmniej wszystkie elementy, które są „mniejsze niż” klucz, muszą znajdować się przed tym elementem w tablicy i wszystkimi elementami, które są „większe niż” klucz musi wystąpić po tym elemencie w tablicy;

  2. Test normalnie wykonywany za pomocą indexOf w celu ustalenia, czy klucz znajduje się w tablicy (sprawdź, czy zwracana wartość nie jest równa -1) nie zachowuje się w binarySearch. Musisz sprawdzić, czy zwracana wartość jest nie mniejsza niż zero, ponieważ zwrócona wartość wskaże, że klucz nie jest obecny, ale indeks, w którym można by się spodziewać, gdyby istniał;

  3. Jeśli tablica zawiera wiele elementów równych kluczowi, to, co otrzymujesz z binarySearch, jest niezdefiniowane; różni się to od indexOf, który zwróci pierwsze wystąpienie, i lastIndexOf, który zwróci ostatnie wystąpienie.

  4. Tablica booleanów może wydawać się posortowana, jeśli najpierw zawiera wszystkie falały, a następnie wszystkie prawdy, ale to się nie liczy. Nie ma przesłonięcia metody binarySearch, która akceptuje tablicę boolanów, i musisz tam zrobić coś sprytnego, jeśli chcesz wydajności O (log n) podczas wykrywania, gdzie pojawia się pierwsza prawda w tablicy, na przykład używając tablicy Booleany i stałe Boolean.FALSE i Boolean.TRUE.

Jeśli twoja tablica nie jest posortowana i nie jest pierwotna , możesz użyć metod indexOf i lastIndexOf List, wywołując asList metodę z java.util.Arrays. Ta metoda zwróci opakowanie interfejsu AbstractList wokół tablicy. Obejmuje minimalny narzut, ponieważ nie tworzy kopii tablicy. Jak wspomniano, ta metoda nie jest przeciążona, więc będzie działać tylko na tablicach typów referencyjnych.

Jeśli twoja tablica nie jest posortowana, a jej typ jest prymitywny , nie masz szczęścia z interfejsem API Java. Napisz własną pętlę for lub własną statyczną metodę użyteczności, która z pewnością będzie miała przewagę wydajności nad podejściem asList, które wiąże się z pewnym nakładem na tworzenie instancji obiektu. Jeśli obawiasz się, że napisanie brutalnej siły dla pętli iterującej wszystkie elementy tablicy nie jest eleganckim rozwiązaniem, zaakceptuj to, co dokładnie robi Java API, gdy wywołujesz indexOf. Możesz zrobić coś takiego:

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;
}

Jeśli chcesz uniknąć pisania tutaj własnej metody, zastanów się nad użyciem jej z platformy programistycznej, takiej jak Guava. Tam możesz znaleźć implementację indexOf i lastIndexOf .

Mishax
źródło
11

Java ArrayListma indexOfmetodę. Macierze Java nie mają takiej metody.

James
źródło
26
Nie tylko ArrayList- każda Java Listma indexOf().
Matt Ball
6

Nie przypominam sobie „indexOf” na tablicach innych niż kodowanie go dla siebie ... chociaż prawdopodobnie możesz użyć jednej z wielu java.util.Arrays#binarySearch(...)metod (zobacz Array javadoc ), jeśli twoja tablica zawiera prymitywne typy

Kellindil
źródło
5

Interfejs List ma metodę indexOf (), a Listę można uzyskać ze swojej tablicy za pomocą metody asList () Array. Poza tym sam Array nie ma takiej metody. Ma metodę binarySearch () dla posortowanych tablic.

Mike Yockey
źródło
4

Same tablice nie mają tej metody. Lista jednak robi: indexOf

Igor
źródło
2
Nie tylko ArrayList- każda Java Listma indexOf().
Matt Ball
Tak, właśnie podałem ArrayList, ponieważ może to być najbliższa temu, czego szukał OP :)
Igor
2

W tablicach Java nie ma bezpośredniej funkcji indexOf.

gambo
źródło
0

Odpowiedź Jeffreya Hantina jest dobra, ale wiąże się z pewnymi ograniczeniami, jeśli to zrób to, albo zrób to ...

Możesz napisać własną metodę rozszerzenia i zawsze działa ona tak, jak chcesz.

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

A oto twoje rozszerzenie

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);
    }
}
M.kazem Akhgary
źródło
-4
int findIndex(int myElement, int[] someArray){
 int index = 0;
 for(int n: someArray){
   if(myElement == n) return index;
   else index++;
 }
}

Uwaga: możesz użyć tej metody dla tablic typu int, możesz także użyć tego algorytmu dla innych typów z niewielkimi zmianami

Vivek Gupta
źródło
1
-1: Najpierw mutuje to oryginalną tablicę, która ma zostać posortowana, co może nie być potrzebne. Po drugie, daje odpowiedź wrt posortowaną tablicę, a nie oryginalną tablicę, która prawdopodobnie jest tym, czego chcemy (jeśli chcielibyśmy odpowiedzi wrt posortowana tablica, byłaby już posortowana). Po trzecie, ponieważ sortowanie odbywa się przez O (n log n), jest to wolniejsze niż przechodzenie przez tablicę liniowo. Ta odpowiedź jest więc zarówno błędna, jak i nieefektywna.
Jamie,
oryginalny indeks został utracony, gdy użyto sortowania lokalnego.
Downhillski