Wo ist Javas Array indexOf?

198

Ich muss etwas sehr Offensichtliches vermissen, aber ich habe überall gesucht und kann diese Methode nicht finden.

Jamie
quelle

Antworten:

234

Es gibt verschiedene Möglichkeiten, dies mithilfe der ArraysUtility-Klasse zu erreichen.

Wenn das Array nicht sortiert ist und kein Array von Grundelementen ist:

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

Wenn das Array ist Primitiven und nicht sortiert, sollte man eine Lösung , die durch eine der anderen Antworten wie angeboten verwenden Kerem Baydoğan des , Andrew McKinlay der oder Mishax ist . Der obige Code wird auch dann kompiliert, wenn er theArrayprimitiv ist (möglicherweise eine Warnung ausgibt), aber Sie erhalten trotzdem völlig falsche Ergebnisse.

Wenn das Array sortiert ist, können Sie eine binäre Suche nach Leistung verwenden:

java.util.Arrays.binarySearch(theArray, o)
Jeffrey Hantin
quelle
3
Ich bin mir ziemlich sicher, dass diese Antwort zumindest für Java 1.6 falsch ist: download.oracle.com/javase/6/docs/api/java/util/… asList wandelt die Liste der Argumente in eine Liste um, nicht das Argument selbst.
Alexandru
11
@Alexandru Ellipsenbehandlung ist syntaktischer Zucker. Wenn Sie ein Argument eingegeben haben T..., lautet der tatsächliche Laufzeit-Typ des Arguments. Wenn Sie T[]null oder mehr Parameter vom Typ übergeben, werden Tdiese in ein neu erstelltes Array eingeschlossen und übergeben. Wenn der übergebene Parameter bereits vom Typ ist T[], wird der syntaktische Zucker umgangen.
Jeffrey Hantin
7
Ich weiß, worauf du hinauswillst. Die Lösung ( .indexOf) gilt jedoch nicht für Grundelemente.
Alexandru
53
Da niemand erwähnt hat: Arrays.asList verwendet das bereits vorhandene Array als Hintergrund. (Dh es gibt keine Bedenken, dass eine Kopie erstellt wird.)
Joshua Goldberg
4
@Notinlist Die Java-Leute haben auch daran gedacht. Verwenden Sie Arrays.toList(list).sublist(from,to).indexOf(o)diese Option , um nach einem Element innerhalb des Bereichs zu suchen [from, to).
Mario Carneiro
62

Array hat keine indexOf()Methode.

Vielleicht ist diese Apache Commons Lang- ArrayUtilsMethode genau das, wonach Sie suchen

import org.apache.commons.lang3.ArrayUtils;

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

int indexOfYellow = ArrayUtils.indexOf(colours, "Yellow");
Kerem Baydoğan
quelle
Eclipse findet diese Importbibliothek nicht.
Omore
21

Wenn Sie für Primitive das Boxen vermeiden möchten, verfügt Guava über Helfer für primitive Arrays, z. B. Ints.indexOf (int [] array, int target).

Andrew McKinlay
quelle
Die anderen Lösungen erstellen alle neue Zeichenfolgen oder Listen oder verarbeiten nur einzelne Elemente. Mit Chars.indexOf von Guava können Sie den Index eines Arrays in einem Array abrufen. Dies ist die richtige Lösung.
HappyEngineer
18

Da ist gar nichts. Verwenden java.util.ListSie entweder ein * oder schreiben Sie Ihr eigenes 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;
}

* Sie können eine aus Ihrem Array mit erstellen Arrays#asList()

Matt Ball
quelle
2
Die Verwendung Tist irreführend. Es bietet keine Typensicherheit, leicht zu verwechseln, es ist typsicher ... besser verwenden Objekt
Venkata Raju
4
@VenkataRaju, bei Verwendung von T werden beide Methodenparameter vom gleichen Typ. Das ist nützlich.
Gonadarian
5
@gonadarian Nicht wirklich. Beide kompilieren ganz gut : indexOf("str", new Object[] {});,indexOf(new Object(), new String[] {});
Venkata Raju
1
@ VenkataRaju Ja wirklich. Ihr Beispiel beweist nichts, da ein String ein Objekt ist. Offensichtlich könnte ein Object-Array einen String enthalten, dessen Index Sie möglicherweise finden möchten.
1
@ ghert85 Ein weiteres Beispiel: indexOf("str", new Date[] {}),indexOf(new Date(), new String[] {})
Venkata Raju
15

Anders als in C #, wo Sie die Array.IndexOf- Methode haben, und in JavaScript, wo Sie die indexOf- Methode haben, hat die Java-API (insbesondere die Arrayund- ArraysKlassen) keine solche Methode.

Diese Methode indexOf (zusammen mit ihrem Komplement lastIndexOf) wird in der Schnittstelle java.util.List definiert. Beachten Sie, dass indexOf und lastIndexOf nicht überladen sind und nur ein Objekt als Parameter verwenden.

Wenn Ihr Array sortiert ist , haben Sie Glück, denn die Arrays-Klasse definiert eine Reihe von Überladungen der binarySearch-Methode, die den Index des gesuchten Elements mit der bestmöglichen Leistung (O (log n) anstelle von O (n) finden ), wobei letzteres das ist, was Sie von einer sequentiellen Suche durch indexOf) erwarten können. Es gibt vier Überlegungen:

  1. Das Array muss entweder in natürlicher Reihenfolge oder in der Reihenfolge eines Komparators sortiert sein, den Sie als Argument angeben, oder zumindest müssen alle Elemente, die "kleiner als" der Schlüssel sind, vor diesem Element im Array und allen Elementen stehen, die sind "größer als", muss der Schlüssel nach diesem Element im Array kommen;

  2. Der Test, den Sie normalerweise mit indexOf durchführen, um festzustellen, ob sich ein Schlüssel im Array befindet (überprüfen Sie, ob der Rückgabewert nicht -1 ist), gilt nicht für binarySearch. Sie müssen sicherstellen, dass der Rückgabewert nicht kleiner als Null ist, da der zurückgegebene Wert angibt, dass der Schlüssel nicht vorhanden ist, sondern der Index, bei dem er erwartet würde, wenn er vorhanden wäre.

  3. Wenn Ihr Array mehrere Elemente enthält, die dem Schlüssel entsprechen, ist das, was Sie von binarySearch erhalten, undefiniert. Dies unterscheidet sich von indexOf, das das erste Vorkommen zurückgibt, und lastIndexOf, das das letzte Vorkommen zurückgibt.

  4. Ein Array von Booleschen Werten scheint sortiert zu sein, wenn es zuerst alle Fehler und dann alle Wahrheiten enthält, dies zählt jedoch nicht. Es gibt keine Überschreibung der binarySearch-Methode, die ein Array von Booleschen Werten akzeptiert, und Sie müssen dort etwas Kluges tun, wenn Sie eine O (log n) -Leistung wünschen, wenn Sie erkennen, wo das erste true in einem Array angezeigt wird, z. B. mithilfe eines Arrays von Boolesche Werte und die Konstanten Boolean.FALSE und Boolean.TRUE.

Wenn Ihr Array nicht sortiert und nicht primitiv ist , können Sie die Methoden indexOf und lastIndexOf von List verwenden, indem Sie die asList- Methode von java.util.Arrays aufrufen . Diese Methode gibt einen AbstractList-Schnittstellen-Wrapper um Ihr Array zurück. Der Aufwand ist minimal, da keine Kopie des Arrays erstellt wird. Wie bereits erwähnt, ist diese Methode nicht überladen, sodass dies nur für Arrays von Referenztypen funktioniert.

Wenn Ihr Array nicht sortiert ist und die Art der Anordnung ist primitiv , sind Sie mit der Java API kein Glück. Schreiben Sie Ihre eigene for-Schleife oder Ihre eigene statische Dienstprogrammmethode, die sicherlich Leistungsvorteile gegenüber dem asList-Ansatz bietet, der einen gewissen Aufwand für die Objektinstanziierung mit sich bringt. Wenn Sie befürchten, dass das Schreiben einer Brute-Force-for-Schleife, die alle Elemente des Arrays durchläuft, keine elegante Lösung darstellt, akzeptieren Sie, dass die Java-API genau dies tut, wenn Sie indexOf aufrufen. Sie können so etwas machen:

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

Wenn Sie vermeiden möchten, hier eine eigene Methode zu schreiben, sollten Sie eine aus einem Entwicklungsframework wie Guava verwenden. Dort finden Sie eine Implementierung von indexOf und lastIndexOf .

Mishax
quelle
11

Java ArrayListhat eine indexOfMethode. Java-Arrays haben keine solche Methode.

James
quelle
26
Nicht nur ArrayList- jeder Java Listhat indexOf().
Matt Ball
6

Ich erinnere mich nicht an ein "indexOf" für Arrays, außer es für sich selbst zu codieren ... obwohl Sie wahrscheinlich eine der vielen java.util.Arrays#binarySearch(...)Methoden verwenden könnten (siehe Arrays javadoc ), wenn Ihr Array primitive Typen enthält

Kellindil
quelle
5

Die List-Schnittstelle verfügt über eine indexOf () -Methode, und Sie können mit der asList () -Methode von Array eine Liste aus Ihrem Array abrufen. Davon abgesehen hat Array selbst keine solche Methode. Es gibt eine binarySearch () -Methode für sortierte Arrays.

Mike Yockey
quelle
4

Arrays selbst haben diese Methode nicht. Eine Liste führt jedoch Folgendes aus : indexOf

Igor
quelle
2
Nicht nur ArrayList- jeder Java Listhat indexOf().
Matt Ball
Ja, ich habe gerade ArrayList angegeben, weil dies dem, was das OP suchte, am nächsten kommt :)
Igor
3

Sie denken wahrscheinlich an die java.util.ArrayList , nicht an das Array.

Duffymo
quelle
2

In Java-Arrays gibt es keine direkte indexOf-Funktion.

Gambo
quelle
0

Jeffrey Hantins Antwort ist gut, aber es gibt einige Einschränkungen, wenn dies dies oder das tut ...

Sie können Ihre eigene Erweiterungsmethode schreiben, die immer so funktioniert, wie Sie es möchten.

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

Und hier ist deine Erweiterung

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
quelle
-4
int findIndex(int myElement, int[] someArray){
 int index = 0;
 for(int n: someArray){
   if(myElement == n) return index;
   else index++;
 }
}

Hinweis: Sie können diese Methode für Arrays vom Typ int verwenden. Sie können diesen Algorithmus auch für andere Typen mit geringfügigen Änderungen verwenden

Vivek Gupta
quelle
1
-1: Zuerst mutiert dies das zu sortierende ursprüngliche Array, das wir möglicherweise nicht möchten. Zweitens gibt es die Antwort für das sortierte Array, nicht das ursprüngliche Array, was wahrscheinlich das ist, was wir wollen (wenn wir die Antwort für das sortierte Array wollten, wäre es bereits sortiert). Drittens, da die Sortierung O (n log n) ist, ist dies langsamer als nur linear durch das Array zu gehen. Diese Antwort ist also sowohl falsch als auch ineffizient.
Jamie
Der ursprüngliche Index ging verloren, wenn eine direkte Sortierung verwendet wurde.
Downhillski