Java collection, több kulcs, keresés

Fórumok

Adott a következő probléma.

Van egy osztály

class A {
  String a;
  String b;
  String c;
  float d;
  float e;
}

 

Ebből lenne példányosítva úgy 80-100 ezer példány, amit egy collectionben kellene összefogni, és ebben keresni (nagyon gyorsan!!!), mind az a, b, c mezőkre.

Az "a" mezőre úgy mint pl. az IntelliJ-ben mikor egy osztályra keresek (Ctrl +N)

pl. ha kereső kifejezés az "alm"

akkor megtalálja az

ALMa

AngoL Marha

ÁLMos

ÁLdozatos Munka

Állami Láblógató Minisztérium

stringeket. (Van erre keresésre valami szép magyar vagy angol szakkifejezés?) Az a sebesség amit az IntelliJ tud a keresésre jó lenne. :)

A "b", "c" mezőkre elég lenne sima sql like mintájú keresés, és nem muszáj egy lépésben keresni, ha kell becsomagolom én egy osztályba ami külön külön meghívja az egyes mezőkre a keresést. Vagy az sem gond ha a három kereső mező miatt 3 külön collection lenne.

Van erre valami megoldás?

Hozzászólások

Szia,

ahogy látom, ez lényegében egy rekord, azaz amit te szeretnél, az valójában egy adatbáziskezelési funkcionalitás.

Ha viszont ilyesmit szeretnél, akkor miért nem töltöd be akár egy in memory SQL adatbáziskezelőbe akár egy lucene-be (http://www.lucenetutorial.com/lucene-in-5-minutes.html)

és oldod meg azon keresztül. A lucene egyébként ennél még jóval többet is tudni fog.

Szerkesztve: 2020. 12. 30., sze – 19:54

Ez 3 collection lenne amelyben valamilyen indexelheto adat van és mutat a rekord azonosítójára. A like %-kal az elején kevésbé indexelheto (lásd postgres gin index). A betutartalmazas (sorrend nélkül) egy vitterkep index a lehetséges betűkre.

Talan egy postgre/oracle adatbázisba beszurhato vagy saját (in memory) indexelest is csinalhatsz. Csak annyi rám kell bele mint a teljes adaztattalom 2x. Kész is.

Milyen gyakran frissül? Ez is egy szempont...

Az hogy java az mindegy is, ez így egy json is lehet. 

A frissülés gyakorisága változó. Lehet egy nap akár ezerszer is, lehet egy hétig egyáltalán nem. De inkább az a jellemző hogy ritkán frissül. 

Jelenleg minden egyes keresés az adatbázisból szedi össze az adatokat. Egy select az "a" és "c" mezőre X táblából, majd a következő select a "b" mezőre Y táblából, ezeket mappalem fel az "A" osztályba és a már szűrt adatokhoz szedem fel a "d" és "e" mezőkbe a Z táblából a megfelelő adatokat. Elég nyakatekert az üzleti logika. De mivel általában hosszú időn keresztül nem változnak az adatok és viszonylag kevés van belőlük (szerintem 150 ezernél soha nem lesz több) érdemes lenne a 3 adatbázis táblából a fent említett módon összeszedni az adatokat, és "egy példányban" tárolni, és mivel keresés akár több száz is lehet rá másodpercenként így talán hatékonyabb lenne mint minden kereséskor az adatbázishoz nyúlni.

Komolyan gondoltam a stream api-t, vagy a sima for ciklust, és gyorsan ki is próbáltam: 40 ms alatt megy végig 150 000 tételen, kisbetűsiti (amit előre megtehetsz) az a, b, c-t, és keres benne, egy listába összeszedi az eredményt.

Tehát a desktop gépemen, ami egy 10 ével ezelőtti első sandy bridge i7-es, 40 ms ideig tart egy keresés (egy szálon). Ez lefuthat másodpercenként több százszor is. (a memóriából)

Szerkesztve: 2020. 12. 30., sze – 20:20

Ha összesen 100 000 db példányod lesz, és bent lesz a memóriában, akkor javaslom az egyszerű for ciklust  (vagy a stream api-t) mindenféle variálás és kavarás nélkül.

Szerintem gyors lesz.

Egyébként egy érdekesség: Branch Prediction in Java | Baeldung (bár nem hiszem, hogy ezzel most bármi kérdés lenne, csak érdekességként osztom meg)

Pont ezt akartam írni én is.

A posztolónak: a kérdés az, hogy pontosan mi is az, hogy gyorsnak kell lennie? Mérés, vagy elméleti megfontolás van már, hogy mennyit tud a nyers erő, és mennyi kellene?

Vannak mindenféle indexelési módszerek is, például be lehet tenni minden kulcsot 1-1 TreeMap-be kulcsnak (csak körültekintést és szinkron blokkokat (hoppá, skálázódás!) igényel, hogy egyszerre menjen be és ki az adat), azon lehet tartományra keresni, de a hasonló betűket előre le kell butítani, pl: a->A A->A á->A Á->A, stb transzformációval.