projections example ejemplos ejemplo java sql collections

example - ¿Cómo consulta colecciones de objetos en Java(Criteria/similar a SQL)?



hibernate projections (7)

Supongamos que tiene una colección de unos pocos cientos de objetos en memoria y necesita consultar esta Lista para devolver objetos que coincidan con alguna consulta de SQL o Criterios. Por ejemplo, puede tener objetos de la Lista de vehículos y desea devolver todos los automóviles fabricados durante la década de 1960, con una matrícula que comience con AZ, ordenada por el nombre del modelo de automóvil.

Sé acerca de JoSQL , ¿alguien lo usó o tiene alguna experiencia con otras soluciones locales?


Continuando con el tema de Comparator , es posible que también desee echarle un vistazo a la API de Google Collections . En particular, tienen una interfaz llamada Predicado , que cumple una función similar a la de Comparator , ya que es una interfaz simple que puede usarse mediante un método de filtrado, como Sets.filter . Incluyen un montón de implementaciones de predicados compuestos, para hacer AND, OR, etc.

Dependiendo del tamaño de su conjunto de datos, puede tener más sentido utilizar este enfoque que un enfoque de base de datos relacional externo o SQL.


He usado Apache Commons JXPath en una aplicación de producción. Le permite aplicar expresiones XPath a gráficos de objetos en Java.


La opción Comparator no está mal, especialmente si usa clases anónimas (para no crear clases redundantes en el proyecto), pero finalmente, cuando mira el flujo de comparaciones, es como recorrer la colección completa por sí mismo, especificando exactamente las condiciones para hacer coincidir los artículos:

if (Car car : cars) { if (1959 < car.getYear() && 1970 > car.getYear() && car.getLicense().startsWith("AZ")) { result.add(car); } }

Luego está la clasificación ... que podría ser un dolor en la parte trasera, pero afortunadamente hay Collections clase y sus métodos de sort , uno de los cuales recibe un Comparator ...


Si necesita una única coincidencia concreta, puede hacer que la clase implemente Comparator, luego cree un objeto independiente con todos los campos hash incluidos y utilícelo para devolver el índice de la coincidencia. Cuando desee encontrar más de un objeto (potencialmente) en la colección, tendrá que recurrir a una biblioteca como JoSQL (que funcionó bien en los casos triviales en que la he usado).

En general, tiendo a incrustar Derby incluso en mis aplicaciones pequeñas, uso las anotaciones de Hibernate para definir mis clases modelo y dejo que Hibernate maneje los esquemas de caché para mantener todo rápido.


Yo usaría un Comparador que toma un rango de años y un patrón de matrícula como parámetros de entrada. Luego solo itere a través de su colección y copie los objetos que coincidan. Es probable que termine haciendo un paquete completo de comparadores personalizados con este enfoque.


sí, sé que es una publicación anterior, pero las tecnologías aparecen todos los días y la respuesta cambiará en el tiempo.

Creo que este es un buen problema para resolverlo con LambdaJ. Puede encontrarlo aquí: http://code.google.com/p/lambdaj/

Aquí tienes un ejemplo:

BUSCA CLIENTES ACTIVOS // (Versión Iterable)

List<Customer> activeCustomers = new ArrayList<Customer>(); for (Customer customer : customers) { if (customer.isActive()) { activeCusomers.add(customer); } }

La versión LambdaJ

List<Customer> activeCustomers = select(customers, having(on(Customer.class).isActive()));

Por supuesto, tener este tipo de belleza impacta en el rendimiento (un poco ... un promedio de 2 veces), pero ¿puedes encontrar un código más legible?

Tiene muchas características, otro ejemplo podría ser la clasificación:

Sort Iterative

List<Person> sortedByAgePersons = new ArrayList<Person>(persons); Collections.sort(sortedByAgePersons, new Comparator<Person>() { public int compare(Person p1, Person p2) { return Integer.valueOf(p1.getAge()).compareTo(p2.getAge()); } });

Clasificar con lambda

List<Person> sortedByAgePersons = sort(persons, on(Person.class).getAge());


El filtrado es una forma de hacerlo, como se discutió en otras respuestas.

Sin embargo, el filtrado no es escalable. En la superficie, la complejidad del tiempo parece ser O ( n ) (es decir, ya no es escalable si crece el número de objetos en la colección), pero en realidad porque una o más pruebas deben aplicarse a cada objeto dependiendo de la consulta, el tiempo la complejidad más precisa es O ( nt ) donde t es el número de pruebas para aplicar a cada objeto.

Por lo tanto, el rendimiento se degradará a medida que se agreguen objetos adicionales a la colección y / o a medida que aumente el número de pruebas en la consulta.

Hay otra forma de hacerlo, usando indexación y teoría de conjuntos.

Un enfoque es crear índices en los campos dentro de los objetos almacenados en su colección y que luego probará en su consulta.

Supongamos que tiene una colección de objetos del Car y que cada objeto del Car tiene un color campo. Supongamos que su consulta es equivalente a " SELECT * FROM cars WHERE Car.color = ''blue'' ". Podrías construir un índice en Car.color , que básicamente se vería así:

''blue'' -> {Car{name=blue_car_1, color=''blue''}, Car{name=blue_car_2, color=''blue''}} ''red'' -> {Car{name=red_car_1, color=''red''}, Car{name=red_car_2, color=''red''}}

Luego, con una consulta WHERE Car.color = ''blue'' , el conjunto de coches azules podría recuperarse en O ( 1 ) complejidad de tiempo. Si hubiera pruebas adicionales en su consulta, podría probar cada auto en ese conjunto de candidatos para verificar si coincide con las pruebas restantes en su consulta. Dado que es probable que el conjunto candidato sea significativamente más pequeño que toda la colección, la complejidad del tiempo es menor que O ( n ) (en el sentido de la ingeniería, consulte los comentarios a continuación). El rendimiento no se degrada tanto cuando se agregan objetos adicionales a la colección. Pero esto aún no es perfecto, sigue leyendo.

Otro enfoque, es a lo que me referiría como un índice permanente de consultas . Explicar: con la iteración y el filtrado convencionales, la colección se itera y cada objeto se prueba para ver si coincide con la consulta. Entonces, filtrar es como ejecutar una consulta sobre una colección. Un índice de consulta permanente sería al revés, donde la colección se ejecuta en lugar de la consulta, pero solo una vez para cada objeto de la colección, aunque la colección podría consultarse varias veces.

Un índice de consulta permanente sería como registrar una consulta con algún tipo de colección inteligente , de modo que a medida que los objetos se agreguen y eliminen de la colección, la colección probará automáticamente cada objeto contra todas las consultas permanentes que se hayan registrado con ella. Si un objeto coincide con una consulta permanente, la colección podría agregarlo / eliminarlo a / desde un conjunto dedicado a almacenar objetos que coincidan con esa consulta. Posteriormente, los objetos que coincidan con cualquiera de las consultas registradas podrían recuperarse en O ( 1 ) complejidad de tiempo.

La información anterior está tomada de CQEngine (Collection Query Engine) . Básicamente, este es un motor de consulta NoSQL para recuperar objetos de las colecciones de Java mediante consultas tipo SQL, sin la sobrecarga de iterar a través de la colección. Se basa en las ideas anteriores, más algunas más. Descargo de responsabilidad: soy el autor. Es de código abierto y en maven central. Si lo encuentras útil, ¡vota por favor esta respuesta!