2011-01-26 22 views
7

Supongamos que tengo un objeto que se parece a:Cómo Obtener la lista de atributos de ArrayList de objetos

public class Obj { 
String foo; 
String bar; 
} 

Si creo un ArrayList de tipo obj y poblarlo, ¿hay alguna manera de devolver una lista de todos los objetos en el atributo foo de la matriz de ArrayList?

EDIT: que debería haber sido más claro, yo no quería hacer esto a través de iteración

+0

Tienes Lista objs y desea crear una segunda lista de esa lista que contiene el atributo foo de todos los Obj de objs? – Ralph

Respuesta

7

Vas a tener que recorrer a través de su List<Obj> y cotejar las entradas foo en una nueva List

por ejemplo,

List<String> foos = new ArrayList<String>(); 
for (Obj obj : objs) { 
    foos.add(obj.foo) 
} 

o para Java 8 y más allá, el uso de corrientes de este modo:

objs.stream().map(o -> o.foo).collect(toList()); 
+3

mi primera versión fue para ser esto: 'var foos = objs.Select (x => x.foo);' hasta que me di cuenta de que era una pregunta de Java. ¡Maldita seas, LINQ! ¡Dios mío! –

+0

Puedes hacer el equivalente de 'map' en Java simple usando algo como Guava. Obviamente (hay un poco) más trabajo involucrado, pero tiene ventajas sobre la asignación de memoria para una copia de todos los valores 'foo' en la lista original. – ColinD

+1

¿Java 8 Lambda proporciona alguna nueva inteligencia para esto? Ala el truco scala-LINQ. – ken

0

iterar a través de la lista y crear un conjunto de todas las propiedades del foo.

0

algo como esto?

List<String> foos = new ArrayList<String>(); 
for (Obj obj : objList) 
{ 
    foos.addElement(obj.foo); 
} 
4

Usando Guava se podría crear una vista de la propiedad foo de los objetos en el List usando Lists.transform así:

public class Obj { 
    String foo; 
    String bar; 

    public static final Function<Obj, String> FOO = new Function<Obj, String>() { 
    public String apply(Obj input) { 
     return input.foo; 
    } 
    }; 
} 

public void someMethod(List<Obj> objs) { 
    List<String> foos = Lists.transform(objs, Obj.FOO); 
    ... 
} 

A diferencia de otras soluciones, esto es puramente una vista del List<Obj> y como tal, no asigna un conjunto separado ArrayList o algo así en la memoria y se puede crear en muy poco tiempo, independientemente del tamaño de su List<Obj>. Además, si cambia el List<Obj> original, la lista foos reflejará ese cambio.

En Java 8 (debido en algún momento en 2012), esto se convertirá en mucho más fácil con las expresiones lambda y referencias de métodos. Usted será capaz de hacer algo como esto:

List<Obj> objs = ... 
List<String> foos = objs.map(#Obj.getFoo); 
10

Prueba esto:

Collection<String> names = CollectionUtils.collect(personList, TransformerUtils.invokerTransformer("getName")); 

uso apache commons colección API.

+0

Gracias, este método es simple y rápido – Vito

1

La respuesta de @Surodip utiliza una solución compacta basada en Apache Commons Collections. Pero esa solución no es typesafe, ya que el Transfomer referencia a la propiedad a través de expresión de cadena: TransformerUtils.invokerTransformer("getName")

Aquí está una más prolija, pero typesafe solución usando Apache Commons Colecciones:

Collection<String> values = CollectionUtils.collect(messages, new Transformer<Obj, String>(){ 

      @Override 
      public String transform(Obj input) { 
       return input.getFoo(); 
      } 

     }); 

Las soluciones anteriores utiliza Apache Commons Versión de colección> = 4, que admite genéricos para seguridad de tipo.

A continuación se muestra la versión menos typesafe para Apache Colecciones Versión < 4, que no utiliza los genéricos:

Collection values = CollectionUtils.collect(messages, new Transformer(){ 

      @Override 
      public Object transform(Object input) { 
       Obj obj = (Obj) input; 
       return obj.getFoo(); 
      } 

     }); 
Cuestiones relacionadas