java - ¿Cómo refactorizo este bucle?
refactoring (4)
Debería lograrlo pasando Lista después de convertirlo en matriz.
Conserva esto como tu único método,
public void something(Item... items) {
for (Item i : items) {
doStuff();
}
}
y cuando quiera pasar un List<Item>
, pase así:
something(listItem.toArray(new Item[listItem.size()]))
Tengo una aplicación donde uso matrices y listas primitivas para una clase llamada Item . Estos se usan indistintamente por razones de legado (también me gustaría que este fuera solo un tipo, pero así es).
Ahora tengo que agregar un nuevo método como este que funciona a través de un bucle para cada uno:
public void something(Item... items) {
for (Item i : items) {
doStuff();
}
}
public void something(List<Item> items) {
for (Item i : items) {
doStuff();
}
}
En otras palabras, exactamente el mismo método dos veces para ambos Arrays y Listas primitivos. ¿Hay alguna manera de refactorizar esto en un solo método?
No puedes no (*) hacer esto en un solo método. Item[]
y la List<Item>
son tipos no relacionados.
Debería hacer que una de las sobrecargas llame a la otra: something(Item... items)
llama something(List<Item>)
o something(List<Item>)
llama something(Item... items)
.
De las dos opciones, es mejor que la sobrecarga de la matriz llame a la sobrecarga de la lista:
public void something(Item... items) {
something(Arrays.asList(item));
}
Esto es barato, porque no copia la matriz, sino que la envuelve: crear la List
es O(1)
.
Si tuviera que invocar la sobrecarga de matriz desde la sobrecarga de lista:
public void something(List<Item> items) {
something(items.toArray(new Item[0]));
}
Esto sería más costoso, ya que la llamada toArray
tiene que crear y completar una matriz: es una operación O(n)
, donde n
es el tamaño de la lista. Sin embargo, tiene la ligera ventaja de que something
no podría reemplazar el contenido de la List
, ya que cualquier actualización de la matriz simplemente se descarta después de la ejecución.
(*) Puede, pero sería realmente grave, y no seguro para el tipo, ya que tendría que aceptar un parámetro de Object
, ya que no hay otro super tipo común de List<Item>
y Item[]
; y aún tendrías que repetir los bucles para los dos tipos; y tendría que manejar la posibilidad de que se pase un tipo completamente no relacionado (en tiempo de ejecución):
public void something(Object obj) {
if (obj instanceof List) {
for (Object element : (List<?>) obj) {
Item item = (Item) element; // Potential ClassCastException.
doStuff();
}
} else if (obj instanceof Item[]) {
for (Item item : (Item[]) obj) {
doStuff();
}
} else {
throw new IllegalArgumentException();
}
}
Que desastre. Gracias al fabricante por las sobrecargas.
Puede implementar un solo método, en este caso, el segundo porque tiene una lista como parámetro. En lugar del primer método, puede convertir la matriz en una lista con Arrays.asList(items)
y luego, puede llamar al primer método. Entonces, al final, tendrá un solo método (que tiene una lista como parámetro).
Además, si la lista de elementos tiene pocos elementos, puede usar las expresiones lambda de Java 8:
items.foreach(item -> doStuff(item));
Por lo tanto, no tendrá un método que contenga solo un bucle y el código será más fácil de leer.
Si usa Java 8, también puede llamar a forEach
o map
en su Stream
y listo, por ejemplo.
yourStream.forEach(doStuff());
donde doStuff()
es el consumer yourStream.forEach(s -> doStuff())
la Cadena o usa yourStream.forEach(s -> doStuff())
si no quieres manejar la cadena y simplemente do stuff
.
Puede obtener un flujo de la siguiente manera:
Stream.of(yourArray) // or Arrays.stream(yourArray)
.forEach(doStuff());
y para tu lista:
list.stream()
.forEach(doStuff());
El principal beneficio de usar los flujos es probablemente la legibilidad. Puede perder con respecto al rendimiento y también puede perder si no desea llamar a Stream.of/Arrays.stream
o Collection.stream()
solo para obtener la transmisión.
Si realmente desea mantener el método de something(...)
(pudiendo lidiar con ambos: los varargs y la lista) todavía necesita un método sobrecargado o use la propuesta de Andy Turner con el método de parámetro de Object
.