usuario1343585
Digamos que tengo una lista de objetos con dos campos field1
y field2
ambos de tipo String.
¿Cómo obtengo una lista de todos field1
valores sin tener que iterar sobre la lista, si es posible?
Afortunadamente, puedes hacer esto usando Java 8 – Flujos
Suponga que tiene una entidad llamada TuEntidad
public class YourEntity {
private String field1;
private String field2;
public YourEntity(String field1, String field2) {
this.field1 = field1;
this.field2 = field2;
}
public void setField1(String field1) {
this.field1 = field1;
}
public void setField2(String field2) {
this.field2 = field2;
}
public String getField1() {
return field1;
}
public String getField2() {
return field2;
}
}
Declara tu lista de TuEntidad usando:
List<YourEntity> entities = Arrays.asList(new YourEntity("text1", "text2"), new YourEntity("text3", "text4"));
Puede extraer la lista de campo1 de una sola vez de esta manera:
import java.util.stream.Collectors;
List<String> field1List = entities.stream().map(YourEntity::getField1).collect(Collectors.toList());
O de esta manera
import java.util.stream.Collectors;
List<String> field1List = entities.stream().map(urEntity -> urEntity.getField1()).collect(Collectors.toList());
Puede imprimir todos los artículos también usando Java 8 🙂
field1List.forEach(System.out::println);
Producción
text1
text3
-
¿Cómo se puede lograr esto para cualquier número de campos en una clase de entidad? Digamos que estoy escribiendo un método común para lograr esto en cualquier cantidad de campos en una sola clase de entidad o cualquier clase de entidad que envíe como argumento en el método.
– Harshit
20 de julio de 2018 a las 8:59
Euclides Mulemwè
prueba esto:
List<Entity> entities = getEntities();
List<Integer> listIntegerEntities = Lambda.extract(entities, Lambda.on(Entity.class).getFielf1());
LambdaJ permite acceder a colecciones sin bucles explícitos, por lo que en lugar de tener más líneas de código para iterar la lista usted mismo, deje que LambdaJ lo haga.
-
Esta respuesta definitivamente debería actualizarse con una breve descripción de lo que se usa aquí (¿LambdaJ?)
– toniedzwiedz
12 de junio de 2012 a las 13:04
Un objeto es una referencia hacia una dirección de memoria. Entonces, los campos de estos objetos son otras referencias hacia otras direcciones de memoria. Por lo tanto, una lista de objetos es una lista de referencias. Por lo tanto, es imposible que la lista acceda directamente a los campos del objeto (referencias dadas por las referencias). La respuesta corta es no.
Nota: de todos modos, encontrará una API que hace lo que quiere, aún se repite en el interior.
-
Tenga en cuenta necesariamente. Podría implementar una colección que, al insertarla, agregue elementos a una lista, que indexe en función de los criterios de búsqueda, y luego devuelva la lista directamente. De esta manera, la inserción sería algo ineficiente, pero la recuperación permitiría hacer lo que quiere el OP.
– Haylem
12 de junio de 2012 a las 13:19
-
Eso es cierto, pero dicha colección sería muy específica para el tipo de objetos que contiene, en lugar de ser genérica.
– dounyy
12 de junio de 2012 a las 13:25
-
en parte, sí, para no hacer que sea completamente “fijo”, necesitaría usar interfaces de límite o reflexión, por lo que debe imponer una ligera rigidez a los tipos que puede insertar, o un impacto en el rendimiento y la complejidad del indexador. Pero eso es perfectamente factible, sin embargo. De hecho, no me sorprendería si algunas de las bibliotecas y extensiones de lenguaje que se han implementado para proporcionar capacidades de consulta a las colecciones de Java y los objetos compuestos estuvieran usando algo similar al segundo enfoque.
– Haylem
12 de junio de 2012 a las 14:25
-
No estoy de acuerdo aquí; es cierto que, lógicamente, una lista debe ser la lista de referencias, pero una lista es solo una interfaz: si devuelve lo correcto, no es necesario que tenga una tienda de respaldo. Vea mi respuesta a continuación para una versión que no se repite y cumple con los requisitos.
– usuario295691
21/01/2014 a las 21:55
Haylem
Depende…
… si sus preguntas se refieren a avoiding iterating over the collection
cualquiera:
- en términos de facilidad de implementación en puntos de llamada
- o en términos de la complejidad algorítmica.
Concretamente, quiere decir:
- no desea escribir una construcción iterativa usted mismo (simplemente use una biblioteca de conveniencia),
- o realmente quiere algo que devuelva elementos automáticamente en O (1) sin necesidad de procesarlos (y tener acceso perfecto)?
Vea a continuación las soluciones y opciones.
Uso de bibliotecas de conveniencia
Si es el primero, busque Google Guava, LambdaJ, FunctionalJava u otras bibliotecas que implementen construcciones funcionales básicas y le permitirán hacer lo que quiera en unas pocas llamadas expresivas. Pero tenga en cuenta que estos hacen lo que dice en la lata: filtrarán, recopilarán o transformarán una colección, e iterarán a través de sus elementos para hacer esto.
Por ejemplo:
-
Set<String> strings = buildSetStrings(); Collection<String> filteredStrings = Collections2.filter(strings, Predicates.containsPattern("^J"));
-
Array<Integer> a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); Array<Integer> b = a.filter(even);
-
List<Integer> biggerThan3 = filter(greaterThan(3), asList(1, 2, 3, 4, 5));
Acceso perfecto
Si es el segundo, esto no es posible tal cual, excepto si diseñaras todo desde el principio para que sus objetos deben ser administrados por una clase de colección personalizada que indexaría sus objetos en función de sus valores de campo en la inserción.
Los mantendría en cubos indexados por dicho valor para que estén fácilmente disponibles para que los recupere como una lista o conjunto a pedido.
Como se menciona en los comentarios debajo de la respuesta de dounyy, el diseño de una colección personalizada de este tipo probablemente tendría un impacto en la API de los elementos que aceptaría (muy probablemente al definir una superinterfaz para usar con los tipos de elementos), o requeriría una implementación bastante compleja. para resolver los miembros dinámicamente (muy probablemente mediante el uso de la reflexión), si alguna vez quiso que esta colección fuera genérica.
Ni Java como lenguaje ni las bibliotecas JDK aún no hacen lo que quieres. Puedes usar LambdaJ o espere a Java 8 que se espera que incluya expresiones lambda.
-
¿Cómo evitaría eso la iteración? Lambda J todavía lo haría por ti. de lo contrario, ya podría usar Google Guava para eso, o LambdaJ, o FunctionalJava, o muchos otros. Pero todos iteran a través de las estructuras, por supuesto.
– Haylem
12 de junio de 2012 a las 13:04
-
Tienes razón, @haylem. Obviamente, alguien debe iterar sobre la colección. No hay forma de evitarlo. Cuando los cierres se introduzcan en Java, harán lo mismo detrás de escena. Las herramientas que mencionó solo nos ayudan a escribir código más corto.
– AlexR
13 de junio de 2012 a las 6:21
usuario295691
Pregunta antigua, pero me encontré con ella mientras buscaba para ver si podía mejorar una solución similar.
Puede implementar el List<String>
interfaz sin crear un desarrollado ArrayList<String>
y por lo tanto no itera sobre el objeto principal.
final List<Entity> entities = getEntities()
final List<String> field1 = new AbstractList() {
public String get(int index) {
return entities.get(index).getField1();
}
public int size() {
return entities.size();
}
}
Eso le da una Lista sin iterar sobre el objeto principal.
Acceso aleatorio a la derivada List<String>
será tan costoso como el acceso aleatorio al subyacente List<Entity>
; si está utilizando una implementación de List<Entity>
que no proporciona un acceso aleatorio rápido, es posible que deba pasar por un par de aros (es decir, implementar más métodos de List<String>
. Pero esto debería funcionar en el 99 % de los casos en los que necesite un adaptador ligero.
-
¿Cómo evitaría eso la iteración? Lambda J todavía lo haría por ti. de lo contrario, ya podría usar Google Guava para eso, o LambdaJ, o FunctionalJava, o muchos otros. Pero todos iteran a través de las estructuras, por supuesto.
– Haylem
12 de junio de 2012 a las 13:04
-
Tienes razón, @haylem. Obviamente, alguien debe iterar sobre la colección. No hay forma de evitarlo. Cuando los cierres se introduzcan en Java, harán lo mismo detrás de escena. Las herramientas que mencionó solo nos ayudan a escribir código más corto.
– AlexR
13 de junio de 2012 a las 6:21
manasbvss
Sea el objeto de la siguiente clase.
public class Bike {
String bikeModel;
Int price;
}
Y ahora hay una lista de bicicletas llamada bikeList de tipo List
Así que ahora queremos una lista de modelos de bicicletas de todas las bicicletas en la lista anterior.
bikeList.map{ Bike b -> b.bikeModel }.toCollection(arrayListOf())
devuelve una lista de matriz del primer campo de todos los objetos de bicicleta en bikeList
No, no lo hay, en el caso común. O tienes mas detalles?
– kan
12 de junio de 2012 a las 12:59
“sin tener que iterar”, en absoluto, supongo.
– Umesh Aawte
12/06/2012 a las 13:00
without having to iterate through the list
¿Quiere decir que no iteraría a través de la lista, o incluso una biblioteca no lo haría? Básicamente, ¿solo quiere algo fácil de escribir, o realmente acceso O (1) a un subconjunto de objetos según las condiciones? Son 2 preguntas completamente diferentes.– Haylem
12 de junio de 2012 a las 13:13