Onde está o Array indexOf do Java?

198

Devo estar faltando algo muito óbvio, mas procurei por todo o lado e não consigo encontrar esse método.

Jamie
fonte

Respostas:

234

Existem algumas maneiras de fazer isso usando a Arraysclasse utilitário.

Se a matriz não estiver classificada e não for uma matriz de primitivas:

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

Se o array for primitivo e não classificado, deve-se usar uma solução oferecida por uma das outras respostas, como as de Kerem Baydoğan , Andrew McKinlay ou Mishax . O código acima será compilado mesmo setheArray seja primitivo (possivelmente emitindo um aviso), mas você obterá resultados totalmente incorretos.

Se a matriz estiver classificada, você poderá fazer uso de uma pesquisa binária de desempenho:

java.util.Arrays.binarySearch(theArray, o)
Jeffrey Hantin
fonte
3
Tenho certeza de que esta resposta está errada, pelo menos para o java 1.6: download.oracle.com/javase/6/docs/api/java/util/… asList transforma a lista de argumentos em uma lista e não no próprio argumento.
Alexandru
11
@Alexandru O manuseio da elipse é um açúcar sintático. Se você digitou um argumento T..., o tipo de argumento de tempo de execução real é T[]e a passagem de zero ou mais parâmetros do tipo faz Tcom que eles sejam agrupados em uma matriz recém-construída e passados. Se o parâmetro que está sendo passado já é do tipo T[], o açúcar sintático é ignorado.
Jeffrey Hantin
7
Eu entendo o seu ponto. A solução ( .indexOf) não é válida para primitivas, no entanto.
Alexandru
53
Como ninguém mencionou: Arrays.asList usa a matriz já existente como suporte. (Ie não há nenhuma preocupação sobre uma cópia que está sendo criado.)
Joshua Goldberg
4
@ Notinlist Os caras do java pensaram nisso também. Use Arrays.toList(list).sublist(from,to).indexOf(o)para procurar um elemento dentro do intervalo [from, to).
Mario Carneiro
62

A matriz não tem indexOf() método.

Talvez este ArrayUtilsmétodo Apache Commons Lang seja o que você está procurando

import org.apache.commons.lang3.ArrayUtils;

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

int indexOfYellow = ArrayUtils.indexOf(colours, "Yellow");
Kerem Baydoğan
fonte
O Eclipse não encontra esta biblioteca de importação.
omore
21

Para primitivos, se você deseja evitar o boxe, o Guava possui auxiliares para matrizes primitivas, por exemplo, Ints.indexOf (int [] array, int target)

Andrew McKinlay
fonte
Todas as outras soluções criam novas strings ou listas ou apenas manipulam elementos únicos. O Chars.indexOf do Guava permite obter o índice de uma matriz em uma matriz. Esta é a solução correta.
HappyEngineer 26/01
18

Não há nenhum. Use um java.util.List* ou você pode escrever o seu 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;
}

* você pode criar um do seu array usando Arrays#asList()

Matt Ball
fonte
2
Usar Té enganoso. Ele não fornece nenhum tipo de segurança, fácil de confundir, é do tipo seguro ... melhor usar o Object
Venkata Raju
4
@VenkataRaju, usar T aqui força os dois parâmetros do método a serem do mesmo tipo. Isso é útil.
Gonadarian
5
@gonadarian Na verdade não. Ambos os compila bem: indexOf("str", new Object[] {});,indexOf(new Object(), new String[] {});
Venkata Raju
1
@VenkataRaju Sim, sério. Seu exemplo não prova nada, já que uma String é um Objeto ... portanto, obviamente, uma matriz de Objetos pode conter uma String da qual você deseja encontrar o índice.
1
@ ghert85 Outro exemplo: indexOf("str", new Date[] {}),indexOf(new Date(), new String[] {})
Venkata Raju
15

Diferente do C #, onde você tem o método Array.IndexOf , e do JavaScript, onde você tem o indexOf método , a API do Java (the ArrayeArrays em particular as classes ) não possui esse método.

Este método indexOf (junto com seu complemento lastIndexOf) é definido no java.util.List interface . Observe que indexOf e lastIndexOf não estão sobrecarregados e usam apenas um objeto como parâmetro.

Se sua matriz é classificada , você tem sorte porque a classe Arrays define uma série de sobrecargas do método binarySearch que encontrará o índice do elemento que você está procurando com o melhor desempenho possível (O (log n) em vez de O (n ), sendo o último o que você pode esperar de uma pesquisa seqüencial feita por indexOf). Há quatro considerações:

  1. A matriz deve ser classificada em ordem natural ou na ordem de um comparador que você fornece como argumento ou, no mínimo, todos os elementos "inferiores a" a chave devem vir antes desse elemento na matriz e todos os elementos que são "maiores que" a chave deve vir depois desse elemento na matriz;

  2. O teste que você normalmente faz com indexOf para determinar se uma chave está na matriz (verifique se o valor de retorno não é -1) não se aplica ao binarySearch. Você precisa verificar se o valor de retorno não é menor que zero, pois o valor retornado indicará que a chave não está presente, mas o índice no qual seria esperado se existisse;

  3. Se sua matriz contiver vários elementos iguais à chave, o que você obtém do binarySearch é indefinido; isso é diferente de indexOf que retornará a primeira ocorrência e lastIndexOf que retornará a última ocorrência.

  4. Uma matriz de booleanos pode parecer classificada se contiver primeiro todas as falsas e depois todas as verdades, mas isso não conta. Não há substituição do método binarySearch que aceita uma matriz de booleanos e você terá que fazer algo inteligente lá se desejar desempenho O (log n) ao detectar onde a primeira verdade verdadeira aparece em uma matriz, por exemplo, usando uma matriz de Booleanos e as constantes Boolean.FALSE e Boolean.TRUE.

Se sua matriz não for classificada e não for do tipo primitivo , você poderá usar os métodos indexOf e lastIndexOf da List invocando o método asList de java.util.Arrays. Este método retornará um wrapper de interface AbstractList em torno de sua matriz. Envolve uma sobrecarga mínima, pois não cria uma cópia da matriz. Como mencionado, esse método não está sobrecarregado, portanto, ele funcionará apenas em matrizes de tipos de referência.

Se sua matriz não estiver classificada e o tipo da matriz for primitivo , você não terá sorte com a API Java. Escreva seu próprio loop for ou seu próprio método de utilitário estático, que certamente terá vantagens de desempenho em relação à abordagem asList que envolve alguma sobrecarga na instanciação de um objeto. Caso você esteja preocupado com o fato de que escrever uma força bruta para loop que itere sobre todos os elementos da matriz não seja uma solução elegante, aceite que é exatamente isso que a API Java está fazendo quando você chama indexOf. Você pode fazer algo assim:

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 você quiser evitar escrever seu próprio método aqui, considere usar um de uma estrutura de desenvolvimento como o Guava. Lá você pode encontrar uma implementação de indexOf e lastIndexOf .

Mishax
fonte
11

Java ArrayListtem um indexOfmétodo As matrizes Java não têm esse método.

James
fonte
26
Não apenas ArrayList- todo Java Listtem indexOf().
Matt Ball
6

Não me lembro de um "indexOf" em matrizes além de codificá-lo para você ... embora você provavelmente possa usar um dos muitos java.util.Arrays#binarySearch(...)métodos (consulte o javadoc Arrays ) se sua matriz contiver tipos primitivos

Kellindil
fonte
5

A interface List possui um método indexOf () e você pode obter uma List da sua matriz com o método asList () da matriz. Fora isso, a própria matriz não possui esse método. Ele possui um método binarySearch () para matrizes classificadas.

Mike Yockey
fonte
4

As próprias matrizes não possuem esse método. Uma lista, no entanto, faz: indexOf

Igor
fonte
2
Não apenas ArrayList- todo Java Listtem indexOf().
Matt Ball
Sim, acabei de especificar ArrayList porque essa pode ser a coisa mais próxima do que o OP estava procurando :)
Igor
3

Você provavelmente está pensando no java.util.ArrayList , não na matriz.

duffymo
fonte
2

Não há função indexOf direta em matrizes java.

gambo
fonte
0

Jeffrey HantinA resposta de é boa, mas tem algumas restrições, se é isso que faz isso ou aquilo ...

Você pode escrever seu próprio método de extensão e ele sempre funciona da maneira que você deseja.

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

E aqui está a sua extensão

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

Nota: você pode usar esse método para matrizes do tipo int, também pode usar esse algoritmo para outros tipos com pequenas alterações

vivek gupta
fonte
1
-1: Primeiro, isso altera a matriz original a ser classificada, o que talvez não desejemos. Segundo, fornece a resposta por meio da matriz classificada, e não a matriz original que é provavelmente o que queremos (se desejássemos a resposta por meio da matriz classificada, ela já seria classificada). Terceiro, uma vez que a classificação é O (n log n), isso é mais lento do que apenas passar pela matriz linearmente. Portanto, essa resposta é errada e ineficiente.
21717 Jamie
o índice original foi perdido quando uma classificação no local é usada.
Downhillski