Introducción: por qué combinar listas en Java y cómo no confundirse
Imagine: tiene dos listas de tareas — «urgentes» e «importantes». O dos listas de clientes — de la base de datos del mes pasado y del mes actual. Para trabajar con ellas como un todo único, necesita combinarlas. En Java, esta tarea es tan común que la pregunta «How do I join two lists in Java?» en Stack Overflow acumula miles de visitas. Y no es casualidad: para los principiantes, combinar listas a menudo causa confusión — ya sea un error de compilación, una lista que resulta inmutable o la pérdida de datos.
En este artículo, analizaremos 5 formas probadas de combinar dos listas en Java — desde el clásico addAll hasta el elegante Stream API. Aprenderá qué método elegir para diferentes situaciones, cómo evitar trampas y escribir código que funcione de manera rápida y predecible. ¡Allá vamos!
Forma 1: El clásico addAll — simple y confiable
La forma más directa es usar el método addAll() de la interfaz Collection. Agrega todos los elementos de una colección a otra. Suena ideal, pero hay un detalle: modifica la lista original. Si necesita mantener las listas originales intactas, cree una nueva.
Ejemplo: combinación conservando los originales
import java.util.ArrayList;import java.util.List;
public class JoinListsExample { public static void main(String[] args) { List<String> listA = new ArrayList<>(List.of("Java", "Python", "C++")); List<String> listB = new ArrayList<>(List.of("JavaScript", "Go", "Rust"));
// Creamos una nueva lista y agregamos ambas listas List<String> mergedList = new ArrayList<>(listA); mergedList.addAll(listB);
System.out.println(mergedList); // [Java, Python, C++, JavaScript, Go, Rust] // Las listas originales no han cambiado }}Ventajas: intuitivo, funciona con cualquier tipo de List, no requiere Java 8+.
Desventajas: modifica la lista original si no se crea una nueva; no admite evaluación perezosa.
Forma 2: Stream API — moderno y flexible
Si usa Java 8 o superior, Stream API ofrece una forma elegante de combinar listas. No modifica los datos originales y se combina fácilmente con otras operaciones — filtrado, ordenamiento, transformación.
Combinación básica con Stream.concat
import java.util.List;import java.util.stream.Collectors;import java.util.stream.Stream;
public class StreamJoinExample { public static void main(String[] args) { List<String> listA = List.of("Rojo", "Verde", "Azul"); List<String> listB = List.of("Amarillo", "Violeta");
List<String> mergedList = Stream.concat(listA.stream(), listB.stream()) .collect(Collectors.toList());
System.out.println(mergedList); // [Rojo, Verde, Azul, Amarillo, Violeta] }}Combinación con filtrado y ordenamiento
Supongamos que necesita combinar dos listas de números, conservar solo los pares y ordenarlos de forma descendente:
import java.util.List;import java.util.Comparator;import java.util.stream.Collectors;import java.util.stream.Stream;
public class StreamAdvancedJoin { public static void main(String[] args) { List<Integer> listA = List.of(5, 2, 8, 1); List<Integer> listB = List.of(7, 4, 9, 3);
List<Integer> result = Stream.concat(listA.stream(), listB.stream()) .filter(n -> n % 2 == 0) // solo pares .sorted(Comparator.reverseOrder()) .collect(C