2012-06-11 19 views
43

Imagínese que tengo una lista de ciertos objetos:Cómo hacer una nueva lista con una propiedad de un objeto que está en otra lista

List<Student> 

y tengo que generar otra lista que incluye los identificadores de estudiantes en la lista anterior:

List<Integer> 

evitar el uso de un bucle, es posible lograr esto utilizando colecciones Apache o guayaba? ¿Qué métodos deberían ser útiles para mi caso?

Cualquier ayuda sería apreciada, gracias.

+0

Hey, lo encontré justo ahora: http://stackoverflow.com/questions/737244/java-map-a-list-of-objects-to-a-list-with-values-of-the-property-attributes – Javatar

+0

La respuesta de Jon es genial, pero si la miras, también usa un ciclo. Cualquier solución usará un bucle, aunque puede que no sea visible para usted, pero internamente se – hage

+0

alguien tiene que aplicar bucle para hacerlo. usted o alguna lib que pueda usar. – sudmong

Respuesta

86

Java 8 manera de hacerlo: -

List<Integer> idList = students.stream().map(Student::getId).collect(Collectors.toList()); 
+1

buena característica ... –

36

Con guayaba se puede utilizar la función como -

private enum StudentToId implements Function<Student, Integer> { 
     INSTANCE; 

     @Override 
     public Integer apply(Student input) { 
      return input.getId(); 
     } 
    } 

y se puede usar esta función para convertir la lista de los estudiantes a los identificadores como -

Lists.transform(studentList, StudentToId.INSTANCE); 

Seguramente se hará en bucle con el fin de extraer todo ids, pero recuerde que los métodos guava devuelven la vista y la función solo se aplicará cuando intente iterar sobre List<Integer>
Si no itera, nunca aplicará el ciclo.

Nota: Recuerde que esta es la vista y si quieres repetir varias veces será mejor para copiar el contenido de alguna otra List<Integer> como

ImmutableList.copyOf(Iterables.transform(students, StudentToId.INSTANCE)); 
+0

@eneveu - ¡Gracias! – Premraj

+0

Creo que es poco elegante tener que definir una función por separado. Creo que esto también se puede hacer de forma anónima y en un proceso de un solo paso – Marc

+0

¿cómo se extraen los miembros de cadena (flotante, etc.) de la lista? – sepehr

-5

es matemáticamente imposible hacer esto sin lazo. Para crear una asignación, F, de un conjunto discreto de valores a otro conjunto discreto de valores, F debe operar en cada elemento en el conjunto de origen. (Se requiere un bucle para hacer esto, básicamente.)

Dicho esto:

¿Por qué necesita una nueva lista? Podrías acercarte a cualquier problema que estés resolviendo de forma incorrecta.

Si tiene una lista de Student, entonces está a solo un paso o dos de distancia, al iterar a través de esta lista, de iterar sobre el I.D. números de los estudiantes.

for(Student s : list) 
{ 
    int current_id = s.getID(); 
    // Do something with current_id 
} 

Si tiene un tipo diferente de problema, entonces comente/actualice la pregunta e intentaremos ayudarlo.

+0

Al principio gracias por su respuesta. Sin embargo, es dramático que hayas dicho que necesitar una nueva lista es incorrecto. Porque depende de la capacidad y el rango de la necesidad. Por lo tanto, su enfoque es incorrecto :) Una vez más, mi mención sobre la "capacidad de lograr eso sin bucle" es una forma más conveniente para no hacer que el código sea ilegible y de bajo rendimiento. De todos modos, ya he encontrado una manera de lograrlo, voy a compartirlo un poco. – Javatar

+0

No he dicho que ** está ** en la dirección incorrecta, pero ** podría ser ** incorrectamente, según el problema que intente resolver. –

18

Gracias a Premraj para la opción de refrigeración alternativa, upvoted.

He usado apache CollectionUtils y BeanUtils. En consecuencia, estoy satisfecho con el rendimiento del código siguiente:

List<Long> idList = (List<Long>) CollectionUtils.collect(objectList, 
            new BeanToPropertyValueTransformer("id")); 

Vale la pena mencionar que, voy a comparar el rendimiento de la guayaba (Premraj proporcionado) y collectionUtils he usado anteriormente, y decidir el más rápido.

+3

Preferiré las colecciones de guayaba por encima de apache independientemente del rendimiento por razones como: más genéricas, modernas, no utiliza la reflexión para transformaciones, etc. En general, la guayaba es mucho más moderna que las colecciones de apache, lea más [aquí] (http: // stackoverflow .com/questions/1444437/apache-commons-vs-guava-formerly-google-collections) – Premraj

+1

Sí, pero en realidad no me parece una buena idea restringir el uso de la misma por una necesidad obligatoria de declaración enum adicional para cada tipo de objeto que quiero transformar – Javatar

+0

Bueno, depende de su diseño. Puede hacer que la interfaz diga 'Identificable' que define el método' getId() 'y luego puede usar este patrón de singleton de enum único para extraer Id. – Premraj

2

Si alguien llegar aquí después de unos años:

List<String> stringProperty = (List<String>) CollectionUtils.collect(listOfBeans, TransformerUtils.invokerTransformer("getProperty")); 
+0

Y me acabas de salvar :) – Behrad3d

2

Java 8 lambda solución de expresión:

List<Integer> iDList = students.stream().map((student) -> student.getId()).collect(Collectors.toList()); 
Cuestiones relacionadas