Dov'è l'indice Array di Java?


198

Mi manca qualcosa di molto ovvio, ma ho cercato dappertutto e non riesco a trovare questo metodo.

Risposte:


234

Ci sono un paio di modi per farlo usando la Arraysclasse utility.

Se l'array non è ordinato e non è un array di primitive:

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

Se la matrice è primitiva e non ordinata, si dovrebbe usare una soluzione offerta da una delle altre risposte come quella di Kerem Baydoğan , Andrew McKinlay o Mishax . Il codice sopra verrà compilato anche se theArrayè primitivo (eventualmente emettendo un avviso) ma otterrai comunque risultati totalmente errati.

Se l'array è ordinato, è possibile utilizzare una ricerca binaria per le prestazioni:

java.util.Arrays.binarySearch(theArray, o)

3
Sono abbastanza sicuro che questa risposta sia sbagliata almeno per java 1.6: download.oracle.com/javase/6/docs/api/java/util/… asList trasforma l'elenco di argomenti in un elenco e non l'argomento stesso.
Alexandru,

11
@Alexandru Il trattamento con ellissi è zucchero sintattico. Se è stato digitato un argomento T..., il tipo di runtime effettivo dell'argomento è T[]e il passaggio di zero o più parametri di tipo Tcomporta il loro avvolgimento in un array appena costruito e passato. Se il parametro che viene passato è già di tipo T[], lo zucchero sintattico viene ignorato.
Jeffrey Hantin,

7
Vedo il tuo punto. Tuttavia, la soluzione ( .indexOf) non è valida per i primitivi.
Alexandru,

53
Poiché nessuno ha menzionato: Arrays.asList utilizza l'array già esistente come supporto. (Vale a dire non c'è preoccupazione per la creazione di una copia.)
Joshua Goldberg,

4
@Notinlist Anche i ragazzi di Java ci hanno pensato. Utilizzare Arrays.toList(list).sublist(from,to).indexOf(o)per cercare un elemento all'interno dell'intervallo [from, to).
Mario Carneiro,

62

La matrice non ha indexOf()metodo.

Forse questo ArrayUtilsmetodo Apache Commons Lang è quello che stai cercando

import org.apache.commons.lang3.ArrayUtils;

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

int indexOfYellow = ArrayUtils.indexOf(colours, "Yellow");

Eclipse non trova questa libreria di importazione.
Omore,

21

Per le primitive, se si desidera evitare il pugilato, Guava dispone di helper per array primitivi, ad esempio Ints.indexOf (int [] array, int target)


Le altre soluzioni creano tutte nuove stringhe o elenchi o gestiscono semplicemente singoli elementi. Guava's Chars.indexOf ti consente di ottenere l'indice di un array in un array. Questa è la soluzione corretta
Happy Engineer

18

Non c'è nessuno. O usa un java.util.List*, oppure puoi scrivere il tuo 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;
}

* puoi crearne uno dal tuo array usando Arrays#asList()


2
L'uso Tè fuorviante. Non fornisce alcun tipo di sicurezza, facile da confondere, è di tipo sicuro ... uso migliore Oggetto
Venkata Raju

4
@VenkataRaju, usando T qui forza entrambi i parametri del metodo ad essere dello stesso tipo. Questo è utile
gonadarian,

5
@gonadarian Non proprio. Entrambe queste compilazioni bene: indexOf("str", new Object[] {});,indexOf(new Object(), new String[] {});
Venkata Raju

1
@VenkataRaju Sì davvero. Il tuo esempio non dimostra nulla poiché una stringa è un oggetto ... quindi ovviamente un array di oggetti potrebbe contenere una stringa di cui potresti voler trovare l'indice.

1
@ ghert85 Un altro esempio: indexOf("str", new Date[] {}),indexOf(new Date(), new String[] {})
Venkata Raju

15

A differenza di C # in cui si dispone del metodo Array.IndexOf e di JavaScript in cui si dispone del metodo indexOf , l'API di Java ( in particolare le classi Arraye Arrays) non dispone di tale metodo.

Questo metodo indexOf (insieme al suo complemento lastIndexOf) è definito nell'interfaccia java.util.List . Si noti che indexOf e lastIndexOf non sono sovraccarichi e accettano solo un oggetto come parametro.

Se il tuo array è ordinato , sei fortunato perché la classe Arrays definisce una serie di sovraccarichi del metodo binarySearch che troverà l'indice dell'elemento che stai cercando con le migliori prestazioni possibili (O (log n) invece di O (n ), quest'ultimo è quello che ci si può aspettare da una ricerca sequenziale eseguita da indexOf). Vi sono quattro considerazioni:

  1. L'array deve essere ordinato in ordine naturale o nell'ordine di un Comparatore fornito come argomento, o almeno tutti gli elementi che sono "inferiori a" la chiave devono precedere quell'elemento nell'array e tutti gli elementi che sono "maggiori di" la chiave deve venire dopo quell'elemento nella matrice;

  2. Il test che si esegue normalmente con indexOf per determinare se una chiave si trova nell'array (verificare se il valore restituito non è -1) non è valido con binarySearch. È necessario verificare che il valore restituito non sia inferiore a zero poiché il valore restituito indicherà che la chiave non è presente ma l'indice a cui ci si aspetterebbe se esistesse;

  3. Se l'array contiene più elementi uguali alla chiave, ciò che ottieni da binarySearch non è definito; questo è diverso da indexOf che restituirà la prima occorrenza e lastIndexOf che restituirà l'ultima occorrenza.

  4. Un array di booleani potrebbe sembrare ordinato se contiene prima tutti i falsi e poi tutti i veri, ma questo non conta. Non esiste una sostituzione del metodo binarySearch che accetta una matrice di valori booleani e dovrai fare qualcosa di intelligente lì se vuoi prestazioni O (log n) quando rilevi dove appare il primo vero in una matrice, ad esempio usando una matrice di Booleani e le costanti Boolean.FALSE e Boolean.TRUE.

Se l'array non è ordinato e non di tipo primitivo , è possibile utilizzare i metodi indexOf e lastIndexOf di List invocando il metodo asList di java.util.Arrays. Questo metodo restituirà un wrapper di interfaccia AbstractList attorno all'array. Implica un sovraccarico minimo poiché non crea una copia dell'array. Come accennato, questo metodo non è sovraccarico, quindi funzionerà solo su array di tipi di riferimento.

Se il tuo array non è ordinato e il tipo di array è primitivo , sei sfortunato con l'API Java. Scrivi il tuo per il ciclo, o il tuo metodo di utilità statica, che avrà sicuramente vantaggi prestazionali rispetto all'approccio asList che comporta un sovraccarico di un'istanza di oggetto. Nel caso in cui ti preoccupi che scrivere una forza bruta per il ciclo che scorre su tutti gli elementi dell'array non sia una soluzione elegante, accetta che sia esattamente ciò che l'API Java sta facendo quando chiami indexOf. Puoi fare qualcosa del genere:

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

Se vuoi evitare di scrivere il tuo metodo qui, considera di usarne uno da un framework di sviluppo come Guava. Vi si possono trovare un'implementazione di indexOf e lastIndexOf .


11

Java ArrayListha un indexOfmetodo. Le matrici Java non hanno tale metodo.


26
Non solo ArrayList- ogni Java Listha indexOf().
Matt Ball,

6

Non ricordo di un "indexOf" su matrici diverse dalla codifica per te stesso ... anche se probabilmente potresti usare uno dei molti java.util.Arrays#binarySearch(...)metodi (vedi Array javadoc ) se la tua matrice contiene tipi primitivi


5

L'interfaccia Elenco ha un metodo indexOf () ed è possibile ottenere un elenco dall'array con il metodo asList () di Array. A parte questo, l'array stesso non ha tale metodo. Ha un metodo binarySearch () per le matrici ordinate.


4

Gli array stessi non hanno questo metodo. Una lista, tuttavia, fa: indexOf


2
Non solo ArrayList- ogni Java Listha indexOf().
Matt Ball,

Sì, ho appena specificato ArrayList perché potrebbe essere la cosa più vicina a ciò che l'OP stava cercando :)
Igor,


2

Non esiste una funzione indexOf diretta negli array Java.


0

La risposta di Jeffrey Hantin è buona ma ha alcuni vincoli, se questo fa questo o altro ...

Puoi scrivere il tuo metodo di estensione e funziona sempre nel modo desiderato.

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

Ed ecco la tua estensione

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

Nota: è possibile utilizzare questo metodo per matrici di tipo int, è inoltre possibile utilizzare questo algoritmo per altri tipi con modifiche minori


1
-1: In primo luogo, questo muta l'array originale da ordinare, che potremmo non volere. In secondo luogo fornisce la risposta alla matrice ordinata, non alla matrice originale che è probabilmente ciò che vogliamo (se volessimo la risposta alla matrice ordinata, sarebbe già ordinata). Terzo poiché l'ordinamento è O (n log n), questo è più lento del semplice passaggio lineare dell'array. Quindi questa risposta è sia sbagliata che inefficiente.
Jamie,

l'indice originale è stato perso quando si utilizza un ordinamento sul posto.
Downhillski
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.