La respuesta simple
En Java 9 o posterior, después List.of()
se agregó:
List<String> strings = List.of("foo", "bar", "baz");
Con Java 10 o posterior, esto se puede acortar con la var
palabra clave.
var strings = List.of("foo", "bar", "baz");
Esto le dará un inmutable List
, por lo que no se puede cambiar.
Que es lo que quieres en la mayoría de los casos donde lo estás rellenando.
Java 8 o anterior:
List<String> strings = Arrays.asList("foo", "bar", "baz");
Esto le dará un List
respaldo de una matriz, por lo que no puede cambiar la longitud.
Pero puedes llamar List.set
, así que todavía es mutable .
Puede Arrays.asList
acortar aún más con una importación estática:
List<String> strings = asList("foo", "bar", "baz");
La importación estática:
import static java.util.Arrays.asList;
Lo que cualquier IDE moderno sugerirá y hará automáticamente por usted.
Por ejemplo, en IntelliJ IDEA, presiona Alt+Enter
y selecciona Static import method...
.
Sin embargo, no recomiendo acortar el List.of
método of
, porque eso se vuelve confuso.
List.of
ya es lo suficientemente corto y se lee bien.
Usando Stream
s
¿Por qué tiene que ser un List
?
Con Java 8 o posterior, puede usar uno Stream
que sea más flexible:
Stream<String> strings = Stream.of("foo", "bar", "baz");
Puedes concatenar Stream
s:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
O puedes ir de un Stream
a un List
:
import static java.util.stream.Collectors.toList;
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
Pero preferiblemente, solo use el Stream
sin recogerlo a List
.
Si realmente necesitas unjava.util.ArrayList
(Probablemente no.)
Para citar JEP 269 (el énfasis es mío):
Hay un pequeño conjunto de casos de uso para inicializar una instancia de colección mutable con un conjunto predefinido de valores. Por lo general, es preferible tener esos valores predefinidos en una colección inmutable, y luego inicializar la colección mutable a través de un constructor de copia.
Si desea tanto una rellenar previamente ArrayList
y agregar a ella después (¿por qué?), El uso
ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
o en Java 8 o anterior:
ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
o usando Stream
:
import static java.util.stream.Collectors.toCollection;
ArrayList<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
Pero, de nuevo, es mejor usar Stream
directamente en lugar de recopilarlo en a List
.
Programa para interfaces, no para implementaciones
Dijiste que declaraste la lista como ArrayList
en tu código, pero solo deberías hacerlo si estás usando algún miembro ArrayList
que no está en List
.
Lo que probablemente no estés haciendo.
Por lo general, sólo debe declarar variables por la interfaz más general que se va a utilizar (por ejemplo Iterable
, Collection
o List
), e inicializar con la aplicación específica (por ejemplo ArrayList
, LinkedList
o Arrays.asList()
).
De lo contrario, está limitando su código a ese tipo específico, y será más difícil cambiarlo cuando lo desee.
Por ejemplo, si está pasando un ArrayList
a un void method(...)
:
// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) {
for (String s : strings) { ... }
}
// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
if (!strings.isEmpty()) { strings.stream()... }
}
// List if you also need .get(index):
void method(List<String> strings) {
strings.get(...)
}
// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
??? // You don't want to limit yourself to just ArrayList
}
Otro ejemplo sería siempre declarar una variable InputStream
a pesar de que generalmente es a FileInputStream
o a BufferedInputStream
, porque un día pronto usted u otra persona querrán usar otro tipo de InputStream
.
ArrasyList<String> places = ["Buenos Aires", "Córdoba", "La Plata"]