Où est l'index de tableau de Java?

198

Je dois manquer quelque chose de très évident, mais j'ai cherché partout et je ne trouve pas cette méthode.

Jamie
la source

Réponses:

234

Il y a deux façons d'accomplir cela en utilisant la Arraysclasse utilitaire.

Si le tableau n'est pas trié et n'est pas un tableau de primitives:

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

Si le tableau est primitif et non trié, il convient d'utiliser une solution proposée par l'une des autres réponses telles que Kerem Baydoğan , Andrew McKinlay ou Mishax . Le code ci-dessus se compilera même sitheArray est primitif (émettant éventuellement un avertissement) mais vous obtiendrez néanmoins des résultats totalement incorrects.

Si le tableau est trié, vous pouvez utiliser une recherche binaire de performances:

java.util.Arrays.binarySearch(theArray, o)
Jeffrey Hantin
la source
3
Je suis sûr que cette réponse est fausse au moins pour java 1.6: download.oracle.com/javase/6/docs/api/java/util/… asList transforme la liste des arguments en une liste et non l'argument lui-même.
Alexandru
11
@Alexandru Ellipsis manipulation est du sucre syntaxique. Si vous avez un argument tapé T..., le type d'exécution réel de l'argument est T[]et si vous passez zéro ou plusieurs paramètres de type, Tils sont enveloppés dans un tableau nouvellement construit et transmis. Si le paramètre transmis est déjà de type T[], le sucre syntaxique est contourné.
Jeffrey Hantin
7
Je vois ce que tu veux dire. La solution ( .indexOf) n'est cependant pas valide pour les primitives.
Alexandru
53
Puisque personne n'a mentionné: Arrays.asList utilise le tableau déjà existant comme support. (C'est-à-dire qu'il n'y a aucune inquiétude quant à la création d'une copie.)
Joshua Goldberg
4
@Notinlist Les gars de Java ont pensé à cela aussi. Utilisez Arrays.toList(list).sublist(from,to).indexOf(o)pour rechercher un élément dans la plage [from, to).
Mario Carneiro
62

Le tableau n'a pas de indexOf()méthode.

Peut-être que cette ArrayUtilsméthode Apache Commons Lang est ce que vous recherchez

import org.apache.commons.lang3.ArrayUtils;

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

int indexOfYellow = ArrayUtils.indexOf(colours, "Yellow");
Kerem Baydoğan
la source
Eclipse ne trouve pas cette bibliothèque d'importation.
Omore
21

Pour les primitives, si vous voulez éviter la boxe, Guava a des aides pour les tableaux primitifs, par exemple Ints.indexOf (int [] array, int target)

Andrew McKinlay
la source
Les autres solutions créent toutes de nouvelles chaînes ou listes ou gèrent simplement des éléments uniques. Chars.indexOf de Guava vous permet d'obtenir l'index d'un tableau dans un tableau. Ceci est la bonne solution.
HappyEngineer
18

Il n'y en a pas. Soit utilisez un java.util.List*, soit vous pouvez écrire le vôtre 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;
}

* vous pouvez en créer un à partir de votre tableau en utilisant Arrays#asList()

Matt Ball
la source
2
L'utilisation Test trompeuse. Il ne fournit aucune sécurité de type, facile à confondre, il est sûr de type ... mieux utiliser Objet
Venkata Raju
4
@VenkataRaju, l'utilisation de T ici force les deux paramètres de méthode à être du même type. C'est utile.
gonadaire
5
@gonadarian Pas vraiment. Ces deux compiles très bien: indexOf("str", new Object[] {});,indexOf(new Object(), new String[] {});
Venkata Raju
1
@VenkataRaju Oui vraiment. Votre exemple ne prouve rien car une chaîne est un objet ... donc évidemment un tableau d'objets pourrait contenir une chaîne dont vous voudrez peut-être trouver l'index.
1
@ ghert85 Autre exemple: indexOf("str", new Date[] {}),indexOf(new Date(), new String[] {})
Venkata Raju
15

Contrairement à C # où vous avez la méthode Array.IndexOf et JavaScript où vous avez la méthode indexOf , l'API Java ( Arrayet les Arraysclasses en particulier) n'ont pas une telle méthode.

Cette méthode indexOf (avec son complément lastIndexOf) est définie dans l' interface java.util.List . Notez que indexOf et lastIndexOf ne sont pas surchargés et prennent uniquement un objet comme paramètre.

Si votre tableau est trié , vous avez de la chance car la classe Arrays définit une série de surcharges de la méthode binarySearch qui trouvera l'index de l'élément que vous recherchez avec les meilleures performances possibles (O (log n) au lieu de O (n ), ce dernier étant ce que vous pouvez attendre d'une recherche séquentielle effectuée par indexOf). Il y a quatre considérations:

  1. Le tableau doit être trié dans l'ordre naturel ou dans l'ordre d'un comparateur que vous fournissez comme argument, ou au moins tous les éléments qui sont "inférieurs à" la clé doivent précéder cet élément du tableau et tous les éléments qui sont "supérieurs à" la clé doit venir après cet élément dans le tableau;

  2. Le test que vous faites normalement avec indexOf pour déterminer si une clé se trouve dans le tableau (vérifiez si la valeur de retour n'est pas -1) ne se vérifie pas avec binarySearch. Vous devez vérifier que la valeur de retour n'est pas inférieure à zéro car la valeur renvoyée indiquera que la clé n'est pas présente mais l'index auquel elle serait attendue si elle existait;

  3. Si votre tableau contient plusieurs éléments égaux à la clé, ce que vous obtenez de binarySearch n'est pas défini; ceci est différent de indexOf qui renverra la première occurrence et lastIndexOf qui renverra la dernière occurrence.

  4. Un tableau de booléens peut sembler être trié s'il contient d'abord toutes les fausses et toutes les vraies, mais cela ne compte pas. Il n'y a pas de substitution de la méthode binarySearch qui accepte un tableau de booléens et vous devrez faire quelque chose d'intelligent si vous voulez des performances O (log n) lors de la détection de l'endroit où le premier vrai apparaît dans un tableau, par exemple en utilisant un tableau de Les booléens et les constantes Boolean.FALSE et Boolean.TRUE.

Si votre tableau n'est pas trié et n'est pas de type primitif , vous pouvez utiliser les méthodes indexOf et lastIndexOf de List en appelant asList méthode de java.util.Arrays. Cette méthode renvoie un wrapper d'interface AbstractList autour de votre tableau. Cela implique une surcharge minimale car il ne crée pas de copie du tableau. Comme mentionné, cette méthode n'est pas surchargée, donc cela ne fonctionnera que sur des tableaux de types de référence.

Si votre tableau n'est pas trié et que le type du tableau est primitif , vous n'avez pas de chance avec l'API Java. Écrivez votre propre boucle for, ou votre propre méthode utilitaire statique, qui aura certainement des avantages en termes de performances par rapport à l'approche asList qui implique une surcharge d'une instanciation d'objet. Dans le cas où vous craignez que l'écriture d'une force brute pour boucle qui itère sur tous les éléments du tableau ne soit pas une solution élégante, acceptez que c'est exactement ce que fait l'API Java lorsque vous appelez indexOf. Vous pouvez faire quelque chose comme ça:

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

Si vous voulez éviter d'écrire votre propre méthode ici, envisagez d'en utiliser une à partir d'un cadre de développement comme Guava. Vous pouvez y trouver une implémentation de indexOf et lastIndexOf .

Mishax
la source
11

Java ArrayLista une indexOfméthode. Les tableaux Java n'ont pas une telle méthode.

James
la source
26
Pas seulement ArrayList- chaque Java en Lista indexOf().
Matt Ball
6

Je ne me souviens pas d'un "indexOf" sur des tableaux autres que de le coder pour vous-même ... bien que vous puissiez probablement utiliser l'une des nombreuses java.util.Arrays#binarySearch(...)méthodes (voir le javadoc Arrays ) si votre tableau contient des types primitifs

Kellindil
la source
5

L'interface List possède une méthode indexOf (), et vous pouvez obtenir une liste à partir de votre tableau avec la méthode asList () de Array. En dehors de cela, Array lui-même n'a pas une telle méthode. Il a une méthode binarySearch () pour les tableaux triés.

Mike Yockey
la source
4

Les tableaux eux-mêmes n'ont pas cette méthode. Une liste, cependant, fait: indexOf

Igor
la source
2
Pas seulement ArrayList- chaque Java en Lista indexOf().
Matt Ball
Ouais, je viens de spécifier ArrayList parce que c'est peut-être la chose la plus proche de ce que le PO recherchait :)
Igor
2

Il n'y a pas de fonction indexOf directe dans les tableaux Java.

gambo
la source
0

La réponse de Jeffrey Hantin est bonne mais elle a quelques contraintes, si c'est ceci faire ceci ou bien cela ...

Vous pouvez écrire votre propre méthode d'extension et cela fonctionne toujours comme vous le souhaitez.

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

Et voici votre extension

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

Remarque: vous pouvez utiliser cette méthode pour les tableaux de type int, vous pouvez également utiliser cet algorithme pour d'autres types avec des modifications mineures

vivek gupta
la source
1
-1: Tout d'abord, cela mute le tableau d'origine à trier, ce que nous ne voulons peut-être pas. Deuxièmement, il donne la réponse par rapport au tableau trié, pas le tableau d'origine qui est probablement ce que nous voulons (si nous voulions la réponse par tableau trié, il serait déjà trié). Troisièmement, puisque le tri est O (n log n), cela est plus lent que de simplement parcourir le tableau de façon linéaire. Cette réponse est donc à la fois fausse et inefficace.
Jamie
l'index d'origine a été perdu lorsqu'un tri sur place est utilisé.
Downhillski