2010-02-01 40 views
6

¿Cuál es la mejor manera de devolver una colección en Java?java: devolver una colección

¿Debo permitir que la persona que llama proporcione una colección para agregar? O simplemente devuelva List<> o Set<> de los artículos? ¿O ambos?

public class Item { ... } 

public class SomeOtherClass 
{ 
    private List<Item> myItems; 

    public List<Item> getItems() 
    { 
    return Collections.unmodifiableList(this.myItems); 
    } 
    public void collectItems(Collection<? super Item> target) 
    { 
    target.addAll(myItems); 
    } 
} 

nota: el ejemplo anterior se supone la existencia previa de una lista que se puede devolver al instante. También estoy interesado en la respuesta adecuada cuando dicha lista no existe previamente y debe generarse cuando la persona que llama llama a getItems() o collectItems(). (He renombrado collectItems basado en el punto planteado por Mykola.)

+0

+1 por presentar Collections.unmodifiableList. Justo lo que estaba buscando. – Adam

Respuesta

6

Prefiero el método List<Item> getItems(). No hay una ventaja real de void getItems(Collection<? super Item> target) sobre la persona que llama simplemente haciendo myCollection.addAll(foo.getItems()) rendimiento o de lo contrario. Collections.unmodifiableXYZ solo crea un contenedor, no una copia completa de la colección, por lo que si el contenedor se usa inmediatamente y se descarta, nunca saldrá de la primera generación y se recolectará rápidamente con poca carga.

Si la recopilación de artículos no siempre se realiza, puede considerar que getItems devuelva Iterable<Item> cuando no sepa cuántos artículos hay. Si conoce el número de elementos y puede escribir un iterador para ellos, entonces es fácil escribir una subclase personalizada de AbstractCollection y devolverla.

+1

+1 para mencionar iteradores –

12

Es mejor (a menos que algunos problemas de rendimiento) para devolver el resultado en una funciones a través de return. De esa manera, es más claro lo que está sucediendo.

Si elige la segunda opción (llenar la colección del cliente) que sería mejor cambiar el nombre de la función de getItems a algo como fillWithItems para evitar el código ambiguo.

Además, no se olvide de JavaBeans y sus convenciones.

+0

+1 por sugerir un cambio de nombre. –

0

Debe devolver una colección. Es un enfoque más común en Java que usar parámetros de entrada/salida. No veo ninguna razón por la que haya una penalización en el rendimiento por devolver una gran colección y será un código mucho más limpio.

+2

Las multas son para hacer que la colección que devuelve sea inmutable. –

+0

Por lo tanto, devuelva una copia o clon de la colección. No menos de una multa que copiar la colección en una creada por el usuario. – Casey

0

Dada la forma en que funciona Java, en general, se espera la versión de devolución.

Sin embargo, si necesita control sobre qué tipo de colección se crea, entonces haría la versión donde la pasa como argumento.

Por lo general, nada debería importar qué tipo de colección se crea, por lo que generalmente debe ir con la versión de devolución. Buen uso de la lista no modificable por cierto.

0

Nota: Devolver un conjunto y devolver una lista tienen implicaciones diferentes.

Un conjunto no tiene duplicados y no hay pedido indicado. Agregar un elemento a un conjunto puede dar como resultado un orden diferente de los elementos.

Una lista puede contener duplicados y agregar un elemento no cambiará (generalmente) el orden general de la lista.

En cuanto a la forma en que regrese la lista, me gustaría utilizar la primera forma:

public List<Item> getItems() 
{ 
    return Collections.unmodifiableList(this.myItems); 
} 

No puedo pensar en una situación en la que esta última forma sería de ningún beneficio. Una lista no es como una matriz donde el espacio puede ser preasignado. Por lo tanto, no hay ahorros de rendimiento al pasar una Lista.

+0

Si estoy reuniendo varias colecciones juntas, y cada una de ellas podría tener 10,000 elementos, preferiría pasar una colección de destino en su lugar. O si el tipo de colección importa (conjunto vs. lista) y hay # grandes de artículos. –

0

La única razón por la que se me ocurre completar una colección existente en lugar de crear una nueva es cuando tiene problemas con el tipo de objeto de la colección. Al igual que la biblioteca Java a la función Array (Object [] a), donde el programa no sabe en tiempo de compilación cuál será el tipo apropiado de los elementos de la matriz, por lo que no puede simplemente devolver, p. una cuerda[]. Entonces, en lugar de eso, hacen que la persona que llama pase una matriz con el tipo de elementos apropiado y lo llenan.

El 90% de las veces sabe exactamente qué tipos de objetos desea devolver, para que pueda hacerlo.

0

Podría cambiar su firma para devolver una Colección o Iterable. Para devolver Iterable, puede devolver algo nuevo -Iterable (myItems.iterator()) en lugar de myItems directamente para evitar que el cliente posiblemente intente convertirlo en una Lista (y modificarlo). Si no desea que modifiquen la Lista, también considere la posibilidad de devolver un Iterador, pero tenga en cuenta que Iterable es mejor ya que puede usar directamente esos para cada bucle.

Devolver un Iterable hace que su intención sea clara y en el ejemplo anterior, evita modificaciones. La única implicación es que ha perdido el acceso aleatorio, lo que puede o no ser un problema para sus necesidades.

+0

Dado que Iterable es una interfaz, 'new Iterable (myItems.iterator())' no es legal; ¿Querías decir otra cosa? –

+0

Sí, whoops, tendrías que devolver una nueva clase anónima (o Iterable por defecto) que la implemente. – GreenieMeanie

Cuestiones relacionadas