Encontrar un elemento en una lista en Java
Cuando estamos creando una aplicación, realizar la operación de encontrar un elemento en una lista en Java es de lo más común. En este artículo vamos a ver diferentes aproximaciones con el API de Java y con librerías de terceros para encontrar un elemento concreto de una lista.
Si quieres más información sobre ArrayList en Java puedes echar un ojo a este artículo.
Introducción
Una de las tareas más comunes en la programación es obtener un elemento de una lista, en función de nuestra necesidad utilizaremos un método u otro. En esta entrada vamos a ver como obtener un elemento de una lista con las siguientes aproximaciones:
- IndexOf()
- Bucle For
- Iterator
- Streams de Java
- Guava
- Apache Commons
Encontrar un elemento en una Lista haciendo uso de IndexOf()
Para obtener un elemento de una lista en Java lo hacemos a través del método get(int position). Pero primero necesitamos saber en que posición se encuentra, para ello nos va a ser de gran utilidad el método IndexOf():
int indexOf(Object element)
El método IndexOf() devuelve el índice de la primera aparición del elemento pasado por parámetro. En caso en el que el elemento no exista devuelve -1.
@Test public void given_a_string_list_when_find_amarillo_then_return_element() { List listA = Arrays.asList("Amarillo", "Rojo", "Azul", "Verde", "Gris"); int index = listA.indexOf("Amarillo"); assertEquals("Amarillo",listA.get(index)); }
Utilizar un bucle For para encontrar un elemento en una Lista en Java
Una de las maneras más tradicionales de realizar búsquedas en Java es iterar haciendo uso de un bucle FOR. En cada iteración analizamos el elemento a buscar. Por ejemplo si tenemos un objeto con varios campos, y queremos buscar por un campo en concreto:
@ParameterizedTest @ValueSource(strings = {"Pepe"}) public void given_a_name_when_find_name_in_list_then_return_user(String userName) { List<User> users = Arrays.asList( User.builder().name("Pepe").build(), User.builder().name("Josh").build(), User.builder().name("Sarah").build() ); User userFound = null; for (User user : users) { if (user.getName().equalsIgnoreCase(userName)) { userFound = user; return; } } assertEquals(userFound, users.get(0)); }
En el ejemplo anterior nos hemos apoyado en la funcionalidad de ParametizedTest de JUnit 5 para bucar por un nombre.
Hacer uso de Iterator para encontrar un elemento
Al igual que con un bucle for, otra de las maneras más convencionales de encontrar un elemento en una lista es haciendo uso de un iterator.
@ParameterizedTest @ValueSource(strings = {"Pepe"}) public void given_a_name_when_find_name_in_list_with_iterator_then_return_user(String userName) { List<User> users = Arrays.asList( User.builder().name("Pepe").build(), User.builder().name("Josh").build(), User.builder().name("Sarah").build() ); User userFound = null; Iterator<User> iterator = users.iterator(); boolean cont = true; while (iterator.hasNext() && cont) { User user = iterator.next(); if (user.getName().equals(userName)) { userFound = user; cont = false; } } assertEquals(userFound, users.get(0)); }
Uso del API de Java Stream para encontrar un elemento en una lista
Con la aparición de Java 8 apareció la programación funcional en Java y el API de Stream. Los Stream de Java nos permite encontrar elementos en una lista haciendo uso de las funciones filter(), findFirst() y findAny().
Vamos a ver una solución haciendo uso de findAny():
@ParameterizedTest @ValueSource(strings = {"Pepe"}) public void given_a_name_when_find_name_in_list_with_java_stream_find_any_then_return_user( String userName) { List<User> users = Arrays.asList( User.builder().name("Pepe").build(), User.builder().name("Josh").build(), User.builder().name("Sarah").build() ); User userFound = users.stream() .filter(user -> user.getName().equalsIgnoreCase(userName)) .findAny() .orElseThrow(() -> new IllegalArgumentException()); assertEquals(userFound, users.get(0)); }
Y otra solución haciendo uso de findFirst()
@ParameterizedTest @ValueSource(strings = {"Sarah"}) public void given_a_name_when_find_name_in_list_with_java_stream_then_return_user( String userName) { List<User> users = Arrays.asList( User.builder().name("Pepe").build(), User.builder().name("Josh").build(), User.builder().name("Sarah").build() ); User userFound = users.stream() .filter(user -> user.getName().equalsIgnoreCase(userName)) .findFirst() .orElseThrow(() -> new IllegalArgumentException()); assertEquals(userFound, users.get(2)); }
Hay que tener en cuenta que ambas aproximaciones devuelven un Optional el cual podemos tratar de diferentes maneras, en este caso lanzaríamos una excepción.
Uso de Apache Commons
La librería de Apache Commons nos ofrece la clase IterableUtils la cual nos permite obtener un elemento de una lista en Java.
@ParameterizedTest @ValueSource(strings = {"Pepe"}) public void given_a_name_when_find_name_in_list_with_apache_commons_then_return_user( String userName) { List<User> users = Arrays.asList( User.builder().name("Pepe").build(), User.builder().name("Josh").build(), User.builder().name("Sarah").build() ); User userFound = IterableUtils.find(users, user -> userName.equals(user.getName())); assertEquals(userFound, users.get(0)); }
Hay que tener en cuenta que el objeto Predicate pertenece a org.apache.commons.collections4.Predicate en lugar de a Java.
Uso de Librería de Google Guava para encontrar un elemento
La librería de Google Guava, de una manera bastante similar a Apache Commons, nos ofrece la clase Iterables con el método tryFind para encontrar elementos en una lista.
@ParameterizedTest @ValueSource(strings = {"Pepe"}) public void given_a_name_when_find_name_in_list_with_guava_then_return_user( String userName) { User userFound = Iterables.tryFind(users, user -> userName.equals(user.getName())).get(); assertEquals(userFound, users.get(0)); }
Conclusión
En esta entrada hemos visto las diferentes aproximaciones que tenemos en Java para encontrar un elemento en una lista. En función de nuestras necesidades aplicaremos un método u otro.
Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com o también nos puedes contactar por nuestras redes sociales Facebook o twitter y te ayudaremos encantados!