Pregunta

Suponga que tiene una colección de unos cientos de objetos en memoria y necesita consultar esta Lista para devolver objetos que coincidan con alguna consulta tipo SQL o Criterio.Por ejemplo, es posible que tenga una Lista de objetos de automóviles y desee devolver todos los automóviles fabricados durante la década de 1960, con una placa que comience con AZ, ordenados por el nombre del modelo de automóvil.

Se acerca de JoSQL, ¿Alguien ha usado esto o tiene alguna experiencia con otras soluciones locales?

¿Fue útil?

Solución

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

Otros consejos

El filtrado es una forma de hacer esto, como se analiza en otras respuestas.

Sin embargo, el filtrado no es escalable.A primera vista, la complejidad del tiempo parecería ser O(norte) (es decir.ya no es escalable si el número de objetos en la colección crece), pero en realidad porque uno o más Las pruebas deben aplicarse a cada objeto según la consulta, la complejidad del tiempo con mayor precisión es O (norte t) dónde t es el número de pruebas a 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 aumenta el número de pruebas en la consulta.

Hay otra forma de hacer esto, utilizando indexación y teoría de conjuntos.

Un enfoque es construir índices sobre el campos dentro de los objetos almacenados en su colección y que posteriormente probará en su consulta.

Digamos que tienes una colección de Car objetos y cada Car El objeto tiene un campo. color.Digamos que su consulta es el equivalente a "SELECT * FROM cars WHERE Car.color = 'blue'".Podrías crear un índice sobre 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 se le hizo una consulta WHERE Car.color = 'blue', el conjunto de autos azules podría recuperarse en O(1) complejidad del tiempo.Si hubiera pruebas adicionales en su consulta, podría probar cada automóvil en ese conjunto de candidatos para verificar si coincidió con las pruebas restantes en su consulta.Dado que es probable que el conjunto de candidatos sea significativamente más pequeño que toda la colección, la complejidad del tiempo es menos que o(norte) (en el sentido de ingeniería, ver los comentarios a continuación).El rendimiento no se degrada como mucho, cuando se agregan objetos adicionales a la colección.Pero esto todavía no es perfecto, sigue leyendo.

Otro enfoque es lo que yo llamaría un índice de consulta permanente.Para 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 sobre la consulta, pero solo una vez para cada objeto de la colección, aunque la colección podría consultarse cualquier número de veces.

A índice de consulta permanente Sería como registrar una consulta con algún tipo de colección inteligente, de modo que a medida que se agregan y eliminan objetos de la colección, la colección probará automáticamente cada objeto con todas las consultas permanentes que se hayan registrado en ella.Si un objeto coincide con una consulta permanente, la colección podría agregarlo o eliminarlo de 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 del tiempo.

La información anterior está tomada de CQEngine (motor de consulta de recopilación).Básicamente, se trata de un motor de consultas NoSQL para recuperar objetos de colecciones de Java mediante consultas similares a SQL, sin la sobrecarga de iterar a través de la colección.Se basa en las ideas anteriores y algunas más.Descargo de responsabilidad:Yo soy el autor.Es de código abierto y está en maven central. Si lo encuentra útil, ¡vote esta respuesta!

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

Creo que este es un buen problema para resolverlo con LambdaJ.Lo puedes encontrar 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);  
  }  
}  

Versión LambdaJ

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

Por supuesto, tener este tipo de belleza impacta en la actuación (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 ordenar:

Ordenar iterativo

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());
        }
}); 

Ordenar con lambda

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

Continuando con el Comparator tema, es posible que también quieras echar un vistazo a Colecciones de Google API.En particular, tienen una interfaz llamada Predicado, que cumple una función similar a Comparator, en el sentido de que es una interfaz simple que puede ser utilizada por un método de filtrado, como Conjuntos.filtro.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 SQL o de base de datos relacional externa.

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

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

Usaría un Comparador que toma un rango de años y un patrón de matrícula como parámetros de entrada.Luego simplemente recorra su colección y copie los objetos que coincidan.Probablemente terminarás creando un paquete completo de comparadores personalizados con este enfoque.

El Comparator La opción no es mala, especialmente si usa clases anónimas (para no crear clases redundantes en el proyecto), pero eventualmente, cuando observa el flujo de comparaciones, es más o menos como recorrer la colección completa usted mismo, especificando exactamente el Condiciones para combinar 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...Eso puede ser un dolor en el trasero, pero afortunadamente hay clase. Collections y es sort métodos, uno de los cuales recibe un Comparator...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top