1. Información general
Encontrar un elemento en una lista es una tarea muy común con la que nos encontramos como desarrolladores.
En este tutorial rápido, cubriremos diferentes formas en las que podemos hacer esto con Java.
2. Configuración
Primero comencemos definiendo un POJO de cliente :
public class Customer { private int id; private String name; // getters/setters, custom hashcode/equals }
Luego, una ArrayList de clientes:
List customers = new ArrayList(); customers.add(new Customer(1, "Jack")); customers.add(new Customer(2, "James")); customers.add(new Customer(3, "Kelly"));
Tenga en cuenta que hemos anulado hashCode y equals en nuestra clase Customer .
Según nuestra implementación actual de iguales , dos objetos Cliente con la misma identificación se considerarán iguales.
Usaremos esta lista de clientes en el camino.
3. Usando la API de Java
El propio Java proporciona varias formas de encontrar un elemento en una lista:
- El método contiene
- El método indexOf
- Un bucle for ad-hoc
- La API Stream
3.1. contiene ()
La lista expone un método llamado contiene :
boolean contains(Object element)
Como sugiere el nombre, este método devuelve verdadero si la lista contiene el elemento especificado y devuelve falso en caso contrario.
Entonces, cuando necesitamos verificar si existe un elemento específico en nuestra lista, podemos:
Customer james = new Customer(2, "James"); if (customers.contains(james)) { // ... }
3.2. índice de()
indexOf es otro método útil para encontrar elementos:
int indexOf(Object element)
Este método devuelve el índice de la primera aparición del elemento especificado en la lista dada, o -1 si la lista no contiene el elemento .
Entonces, lógicamente, si este método devuelve algo diferente a -1, sabemos que la lista contiene el elemento:
if(customers.indexOf(james) != -1) { // ... }
La principal ventaja de usar este método es que puede decirnos la posición del elemento especificado en la lista dada.
3.3. Bucle básico
Ahora, ¿qué pasa si queremos hacer una búsqueda basada en campos para un elemento? Por ejemplo, digamos que estamos anunciando una lotería y necesitamos declarar a un Cliente con un nombre específico como ganador.
Para tales búsquedas basadas en campos, podemos recurrir a la iteración.
Una forma tradicional de iterar a través de una lista es utilizar una de las construcciones de bucle de Java. En cada iteración, comparamos el elemento actual en la lista con el elemento que estamos buscando para ver si coincide:
public Customer findUsingEnhancedForLoop( String name, List customers) { for (Customer customer : customers) { if (customer.getName().equals(name)) { return customer; } } return null; }
Aquí el nombre se refiere al nombre que estamos buscando en la lista de clientes dada . Este método devuelve el primer objeto Cliente de la lista con un nombre coincidente , o nulo si no existe tal Cliente .
3.4. Bucle con un iterador
El iterador es otra forma en que podemos recorrer una lista de elementos.
Simplemente podemos tomar nuestro ejemplo anterior y modificarlo un poco:
public Customer findUsingIterator( String name, List customers) { Iterator iterator = customers.iterator(); while (iterator.hasNext()) { Customer customer = iterator.next(); if (customer.getName().equals(name)) { return customer; } } return null; }
En consecuencia, el comportamiento es el mismo que antes.
3.5. API de Java 8 Stream
A partir de Java 8, también podemos usar la API Stream para encontrar un elemento en una lista.
Para encontrar un elemento que coincida con criterios específicos en una lista dada, nosotros:
- invocar stream () en la lista
- llamar al método f ilter () con un predicado adecuado
- llamar a la construcción findAny () , que devuelve el primer elemento que coincide con el predicado de filtro envuelto en un Opcional si tal elemento existe
Customer james = customers.stream() .filter(customer -> "James".equals(customer.getName())) .findAny() .orElse(null);
Por conveniencia, por defecto es nulo en caso de que un Opcional esté vacío, pero es posible que esta no siempre sea la mejor opción para cada escenario.
4. Bibliotecas de terceros
Now, while the Stream API is more than sufficient, what should we do if we're stuck on an earlier version of Java?
Fortunately, there are many third-party libraries like Google Guava and Apache Commons which we can use.
4.1. Google Guava
Google Guava provides functionality that is similar to what we can do with streams:
Customer james = Iterables.tryFind(customers, new Predicate() { public boolean apply(Customer customer) { return "James".equals(customer.getName()); } }).orNull();
Just like with Stream API, we can optionally choose to return a default value instead of null:
Customer james = Iterables.tryFind(customers, new Predicate() { public boolean apply(Customer customer) { return "James".equals(customer.getName()); } }).or(customers.get(0));
The above code will pick the first element in the list if no match is found.
Also, don't forget that Guava throws a NullPointerException if either the list or the predicate is null.
4.2. Apache Commons
We can find an element in almost the exact same way using Apache Commons:
Customer james = IterableUtils.find(customers, new Predicate() { public boolean evaluate(Customer customer) { return "James".equals(customer.getName()); } });
Sin embargo, hay un par de diferencias importantes:
- Apache Commons simplemente devuelve nulo si pasamos una lista nula .
- Esono proporciona la funcionalidad de valor predeterminado como tryFind de Guava .
5. Conclusión
En este artículo, aprendimos diferentes formas de encontrar un elemento en una Lista, comenzando con verificaciones rápidas de existencia y terminando con búsquedas basadas en campos.
También analizamos las bibliotecas de terceros Google Guava y Apache Commons como alternativas a la API de Java 8 Streams .
Gracias por visitarnos, y recuerde consultar todas las fuentes de estos ejemplos en GitHub.