Frage

Angenommen, Sie eine Sammlung von ein paar hundert in-memory Objekte haben, und Sie müssen diese Liste abfragen Objekte zurückzukehren einige SQL oder Kriterien wie Suche entsprechen. Zum Beispiel könnten Sie eine Liste der Auto-Objekte haben, und Sie wollen alle Fahrzeuge in den 1960er Jahren zurück, mit einem Nummernschild, die mit AZ beginnt, durch den Namen des Automodell bestellt.

Ich weiß, über JoSQL hat dies jemand verwendet oder keine Erfahrung mit anderen / homegrown Lösungen

War es hilfreich?

Lösung

habe ich Apache Commons JXPath in einer Produktionsanwendung verwendet. Es ermöglicht Ihnen, XPath-Ausdrücke, um grafische Darstellungen von Objekten in Java anzuwenden.

Andere Tipps

Das Filtern ist ein Weg, dies zu tun, wie in anderen Antworten diskutiert.

Das Filtern ist jedoch nicht skalierbar. Auf der Oberfläche scheint Zeitkomplexität O ( n ) (dh bereits nicht skalierbar, wenn die Anzahl der Objekte in der Sammlung wachsen), aber eigentlich, weil man oder mehr zu sein Tests müssen mehr auf jedes Objekt angewendet werden, abhängig von der Abfrage, Zeitkomplexität genau ist O ( nt ) wobei t ist die Anzahl der Tests zu jedem Objekt anzuwenden.

So Leistung als weitere Objekte der Sammlung hinzugefügt wird abgebaut wird, und / oder wie die Anzahl der Tests in der Abfrage erhöht.

Es gibt einen anderen Weg, dies zu tun, mit Indexieren und settheorie.

Ein Ansatz ist die bauen Indizes auf den Feldern innerhalb der Objekte in Ihrer Sammlung gespeichert und mit dem Sie anschließend Test in Ihrer Anfrage.

Angenommen, Sie haben eine Sammlung von Car Objekte und jedes Car Objekt ein Feld color hat. Sagen Sie Ihre Anfrage das Äquivalent von „SELECT * FROM cars WHERE Car.color = 'blue'“ ist. Sie könnten einen Index für Car.color bauen, die wie dies im Grunde aussehen:

'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'}}

Dann eine Abfrage WHERE Car.color = 'blue' gegeben, könnte der Satz von blauen Autos in O abgerufen werden ( 1 ) Zeitkomplexität. Wenn es in der Abfrage zusätzliche Tests sind, konnte man dann jedes Auto testen, dass Kandidatensatz zu überprüfen, ob es die verbleibenden Tests in Ihrer Abfrage abgestimmt. Da der Kandidatensatz deutlich kleiner sein dürfte als die gesamte Sammlung, Zeitkomplexität ist weniger als O ( n ) (im Engineering Sinne siehe Kommentar unten). Performance nicht abbaut so viel , wenn zusätzliche Objekte der Sammlung hinzugefügt. Aber dies immer noch nicht perfekt ist, lesen Sie weiter.

Ein weiterer Ansatz ist, was ich als ein verweist stehen Abfrage Index . Um zu erklären: mit herkömmlicher Iteration und Filterung, ist die Sammlung iterative und jedes Objekt getestet, um zu sehen, ob es die Abfrage übereinstimmt. So Filterung ist wie eine Abfrage über eine Sammlung ausgeführt wird. Ein stehende Abfrage Index würde die umgekehrt sein, wo die Sammlung statt über die Abfrage ausführen, aber nur einmal für jedes Objekt in der Sammlung, obwohl die Sammlung beliebig oft abgefragt werden kann.

A stand Abfrage Index wäre wie eine Abfrage mit irgendeiner Art von Registrierung intelligente Sammlung , so dass, wenn Objekte hinzugefügt werden, und aus der Sammlung entfernt, die Sammlung würde testen automatisch jedes Objekt gegen alle der ständigen Anfragen, die bei ihm registriert wurden. Wenn ein Objekt eine stehende Abfrage übereinstimmt, dann könnte die Sammlung hinzufügen / entfernen sie zu / von einem Satz zum Speichern von Objekten gewidmet, dass die Suche entsprechen. Anschließend Objekte eine der eingetragenen Abfragen passend in O abgerufen werden können ( 1 ) Zeitkomplexität.

Die oben genannten Informationen genommen wird von CQEngine (Sammlung Query Engine) . Dies ist im Grunde eine NoSQL-Abfrage-Engine für Objekte aus Java Sammlungen mit SQL-ähnlichen Abfragen, ohne den Overhead von Iterieren durch die Sammlung abruft. Es ist oben rund um die Ideen gebaut, plus einige mehr. Disclaimer: Ich bin der Autor. Es ist Open-Source und in Maven von zentraler Bedeutung. Wenn Sie es hilfreich finden Sie diese Antwort upvote!

ja, ich weiß, es ist eine alte Post, aber Technologien erscheinen jeden Tag und die Antwort wird in der Zeit ändern.

Ich denke, das ein gutes Problem ist es mit LambdaJ zu lösen. Sie können es hier finden: http://code.google.com/p/lambdaj/

Hier haben Sie ein Beispiel:

LOOK FÜR AKTIVE KUNDEN // (Iterable Version)

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

LambdaJ Version

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

Natürlich hat diese Art von Schönheit Auswirkungen in der Leistung (ein wenig ... durchschnittlich 2 mal), aber können Sie einen lesbaren Code finden?

Es hat viele viele Funktionen, könnte ein weiteres Beispiel wird Sortierung:

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

Sortieren mit Lambda

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

das Comparator Thema Weiterbildung haben, können Sie auch einen Blick auf die Google Kollektionen nehmen API. Insbesondere haben sie eine Schnittstelle namens predicate , die eine ähnliche Rolle dient in an Comparator, dass es eine einfache Schnittstelle ist, die durch ein Filterverfahren verwendet werden kann, wie Sets.filter . Dazu gehört eine ganze Reihe von Verbund Prädikat Implementierungen zu tun ANDs, RUP, etc.

Abhängig von der Größe Ihres Datensatzes kann es Sinn machen, diesen Ansatz zu verwenden als eine SQL oder externen relationalen Datenbank-Ansatz.

Wenn Sie ein einzelnes konkretes Spiel benötigen, können Sie die Klasse haben Vergleicher implementieren, dann ein eigenständiges Objekt erstellen mit allen gehasht Felder enthalten und es verwenden, um den Index des Spiels zurückzukehren. Wenn Sie mehr als ein (potentiell) Objekt in der Sammlung finden wollen, werden Sie zu einer Bibliothek wie JoSQL drehen müssen (die auch in den trivialen Fällen gearbeitet hat, die ich verwendet habe es).

Generell neige ich Derby in noch meine kleine Anwendungen einzubetten, verwenden Hibernate Annotations mein Modellklassen zu definieren und lassen Hibernate mit Caching-Systeme beschäftigen alles schnell zu halten.

Ich möchte einen Komparator verwenden, die eine Reihe von Jahren und Kennzeichenmuster als Eingabeparameter nimmt. Dann durchlaufen gerade durch Ihre Sammlung und die Objekte kopieren, die übereinstimmen. Sie würden wahrscheinlich ein ganzes Paket von benutzerdefinierten Komparatoren mit diesem Ansatz am Ende machen.

Die Comparator Option ist nicht schlecht, vor allem, wenn Sie anonyme Klassen verwenden (um nicht redundante Klassen in dem Projekt zu erstellen), aber schließlich, wenn Sie an dem Fluss der Vergleiche sehen, es ist so ziemlich genau wie über die gesamte Kollektion looping selbst unter Angabe Elemente genau die Bedingungen für die Anpassung:

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

Dann gibt es noch die Sortierung ... das könnte ein Schmerz im Hintern sein, aber zum Glück gibt es Klasse Collections und seine sort Methoden, von denen eine Comparator empfängt ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top