¿Dónde está Java's Array indexOf?

198

Debo estar perdiendo algo muy obvio, pero he buscado por todas partes y no puedo encontrar este método.

Jamie
fuente

Respuestas:

234

Hay un par de formas de lograr esto usando la Arraysclase de utilidad.

Si la matriz no está ordenada y no es una matriz de primitivas:

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

Si la matriz es primitiva y no está ordenada, se debe usar una solución ofrecida por una de las otras respuestas, como la de Kerem Baydogan , Andrew McKinlay o Mishax . El código anterior se compilará incluso si theArrayes primitivo (posiblemente emitiendo una advertencia) pero de todos modos obtendrá resultados totalmente incorrectos.

Si la matriz está ordenada, puede hacer uso de una búsqueda binaria de rendimiento:

java.util.Arrays.binarySearch(theArray, o)
Jeffrey Hantin
fuente
3
Estoy bastante seguro de que esta respuesta es incorrecta al menos para java 1.6: download.oracle.com/javase/6/docs/api/java/util/… asList transforma la lista de argumentos en una lista, no el argumento en sí.
Alexandru
11
El manejo de @Alexandru Ellipsis es azúcar sintáctica. Si tiene un argumento escrito T..., el tipo de argumento en tiempo de ejecución real es T[], y pasar cero o más parámetros de tipo Thace que se envuelvan en una matriz recién construida y se pasen. Si el parámetro que se pasa ya es de tipo T[], se omite el azúcar sintáctico.
Jeffrey Hantin
77
Entiendo tu argumento. Sin .indexOfembargo, la solución ( ) no es válida para primitivas.
Alexandru
53
Como nadie mencionó: Arrays.asList usa la matriz ya existente como respaldo. (Es decir, no hay preocupación por la creación de una copia).
Joshua Goldberg
44
@Notinlist Los chicos de Java también pensaron en eso. Use Arrays.toList(list).sublist(from,to).indexOf(o)para buscar un elemento dentro del rango [from, to).
Mario Carneiro
62

La matriz no tiene indexOf()método.

Tal vez este ArrayUtilsmétodo Lang de Apache Commons es lo que estás buscando

import org.apache.commons.lang3.ArrayUtils;

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

int indexOfYellow = ArrayUtils.indexOf(colours, "Yellow");
Kerem Baydoğan
fuente
Eclipse no encuentra esta biblioteca de importación.
Omore
21

Para las primitivas, si desea evitar el boxeo, Guava tiene ayudantes para matrices primitivas, por ejemplo, Ints.indexOf (int [] array, int target)

Andrew McKinlay
fuente
Todas las otras soluciones crean nuevas cadenas o listas o simplemente manejan elementos individuales. Chars.indexOf de Guava le permite obtener el índice de una matriz en una matriz. Esta es la solución correcta.
HappyEngineer
18

No hay ninguno. Utilice un java.util.List* o puede escribir el suyo propio 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;
}

* puedes hacer uno de tu matriz usando Arrays#asList()

Matt Ball
fuente
2
Usar Tes engañoso. No proporciona ningún tipo de seguridad, es fácil de confundir, es de tipo seguro ... mejor uso Objeto
Venkata Raju
44
@VenkataRaju, el uso de T aquí obliga a que ambos parámetros del método sean del mismo tipo. Eso es útil
Gonadarian
55
@gonadarian No realmente. Ambas compila bien: indexOf("str", new Object[] {});,indexOf(new Object(), new String[] {});
Venkata Raju
1
@VenkataRaju Sí, de verdad. Su ejemplo no prueba nada ya que una Cadena es un Objeto ... por lo que, obviamente, una matriz de Objetos podría contener una Cadena de la que quizás desee encontrar el índice.
1
@ ghert85 Otro ejemplo: indexOf("str", new Date[] {}),indexOf(new Date(), new String[] {})
Venkata Raju
15

A diferencia de C # donde tiene el método Array.IndexOf , y JavaScript donde tiene el método indexOf , la API de Java (la ArrayyArrays clases en particular) no tienen dicho método.

Este método indexOf (junto con su complemento lastIndexOf) se define en la interfaz java.util.List . Tenga en cuenta que indexOf y lastIndexOf no están sobrecargados y solo toman un objeto como parámetro.

Si su matriz está ordenada , tiene suerte porque la clase Arrays define una serie de sobrecargas del método binarySearch que encontrará el índice del elemento que está buscando con el mejor rendimiento posible (O (log n) en lugar de O (n ), este último es lo que puede esperar de una búsqueda secuencial realizada por indexOf). Hay cuatro consideraciones:

  1. La matriz se debe ordenar en orden natural o en el orden de un comparador que proporcione como argumento, o al menos todos los elementos que son "menores que" la clave debe aparecer antes de ese elemento en la matriz y todos los elementos que son "mayores que" la clave debe venir después de ese elemento en la matriz;

  2. La prueba que normalmente realiza con indexOf para determinar si una clave está en la matriz (verificar si el valor de retorno no es -1) no se cumple con binarySearch. Debe verificar que el valor de retorno no sea menor que cero, ya que el valor devuelto indicará que la clave no está presente, pero el índice en el que se esperaría si existiera;

  3. Si su matriz contiene múltiples elementos que son iguales a la clave, lo que obtiene de binarySearch no está definido; Esto es diferente de indexOf que devolverá la primera aparición y lastIndexOf que devolverá la última aparición.

  4. Una matriz de booleanos puede parecer ordenada si primero contiene todos los falsos y luego todas las verdades, pero esto no cuenta. No hay anulación del método binarySearch que acepta una matriz de booleanos y tendrá que hacer algo inteligente allí si desea un rendimiento O (log n) al detectar dónde aparece la primera verdad en una matriz, por ejemplo, utilizando una matriz de Booleanos y las constantes Boolean.FALSE y Boolean.TRUE.

Si su matriz no está ordenada y no es de tipo primitivo , puede usar los métodos indexOf y lastIndexOf de List invocando asList método de java.util.Arrays. Este método devolverá un contenedor de interfaz AbstractList alrededor de su matriz. Implica una sobrecarga mínima ya que no crea una copia de la matriz. Como se mencionó, este método no está sobrecargado, por lo que solo funcionará en matrices de tipos de referencia.

Si su matriz no está ordenada y el tipo de matriz es primitiva , no tiene suerte con la API de Java. Escriba su propio bucle for, o su propio método de utilidad estática, que sin duda tendrá ventajas de rendimiento sobre el enfoque asList que implica cierta sobrecarga de una instanciación de objeto. En caso de que le preocupe que escribir una fuerza bruta para el bucle que itera sobre todos los elementos de la matriz no sea una solución elegante, acepte que eso es exactamente lo que hace la API de Java cuando llama a indexOf. Puedes hacer algo como esto:

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 desea evitar escribir su propio método aquí, considere usar uno de un marco de desarrollo como Guava. Allí puede encontrar una implementación de indexOf y lastIndexOf .

Mishax
fuente
11

Java ArrayListtiene un indexOfmétodo. Las matrices Java no tienen tal método.

James
fuente
26
No solo ArrayList, cada Java Listtiene indexOf().
Matt Ball
6

No recuerdo un "indexOf" en matrices que no sea codificarlo usted mismo ... aunque probablemente podría usar uno de los muchos java.util.Arrays#binarySearch(...)métodos (consulte el javadoc de matrices ) si su matriz contiene tipos primitivos

Kellindil
fuente
5

La interfaz de Lista tiene un método indexOf (), y puede obtener una Lista de su matriz con el método asList () de Array. Aparte de eso, Array en sí no tiene tal método. Tiene un método binarySearch () para matrices ordenadas.

Mike Yockey
fuente
4

Las matrices mismas no tienen ese método. Una lista, sin embargo, sí: indexOf

Igor
fuente
2
No solo ArrayList, cada Java Listtiene indexOf().
Matt Ball
Sí, acabo de especificar ArrayList porque eso puede ser lo más parecido a lo que estaba buscando el OP :)
Igor
2

No hay una función indexOf directa en las matrices java.

gambo
fuente
0

La respuesta de Jeffrey Hantin es buena, pero tiene algunas limitaciones, si es esto lo que hace o no a eso ...

Puede escribir su propio método de extensión y siempre funciona de la manera que desee.

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

Y aquí está tu extensión

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

Nota: puede usar este método para matrices de tipo int, también puede usar este algoritmo para otros tipos con cambios menores

vivek gupta
fuente
1
-1: Primero, esto muta la matriz original que se va a ordenar, lo que quizás no queramos. En segundo lugar, le da a la respuesta wrt la matriz ordenada, no la matriz original que probablemente sea lo que queremos (si quisiéramos la respuesta ordenada wrt, ya estaría ordenada). Tercero, dado que la ordenación es O (n log n), esto es más lento que simplemente recorrer la matriz linealmente. Entonces esta respuesta es incorrecta e ineficiente.
Jamie
el índice original se perdió cuando se usa una clasificación in situ.
Downhillski