Spotkałem się ostatnio z ciekawym problemem dotyczącym wyszukiwania danych. Zlecenie na program zaliczeniowy było proste napisać bibliotekę, ale bez użycia RDBMS. zabawa opiera się więc o kolekcje i ich odpowiednie projektowanie. Zadanie stosunkowo proste do momentu, w którym nie trzeba wyszukiwać danych po którejś z „kolumn”. W tym momencie mamy dwie drogi.

  • Ręczne iterowanie się po kolekcji i wyszukiwanie po id przez porównanie z każdym obiektem.
  • Emulowanie indeksu z RDBMS

Pierwsza metoda jest mało wydajna. Ma złożoność liniową, a przecież da się szybciej. Poza tym drugie rozwiązanie jest znacznie ciekawsze.

Krok 1. Klasa Autor

public class Author {<br></br> private int id;<br></br> private String name;<br></br><br></br> public String getName() {<br></br>  return name;<br></br> }<br></br><br></br> public void setName(String name) {<br></br>  this.name = name;<br></br> }<br></br><br></br> public int getId() {<br></br>  return id;<br></br> }<br></br><br></br> public Author(int id, String name) {<br></br>  super();<br></br>  this.id = id;<br></br>  this.name = name;<br></br> }<br></br><br></br>}

Krok 2. Po czym indeksujemy

Załóżmy, że chcemy indeksować po polu name. W sumie indeks dobry jak każdy inny.

Krok 3. „Tabela” authors

Zdefiniujmy klasę która będzie emulowała tabelę authors:

public class Authors extends LinkedList<author> {<br></br><br></br> private static final long serialVersionUID = 1L;<br></br>}</author>

Nie bawimy się w jakieś rozczulania czy kombinowanie tylko rozszerzamy LinkedList. W ten sposób mamy do dyspozycji odpowiednie metody i za darmo kontrolę typu.

Krok 4. „Indeks” na tabeli authors z pola name

Tu też nie ma się co bawić i rozczulać:

public class AuthorsNameIndex extends HashMap<string author="">{<br></br><br></br> private static final long serialVersionUID = 1L;<br></br><br></br>}</string>

I tu pierwsza pułapka. Pojawia man się poważna redundancja danych. Tabela authors i indeks przechowują wszystkich autorów. Nie jest to dobre rozwiązanie. Jednak nie będę go zmieniał ponieważ oznaczałoby to zmianę klasy Authors i w konsekwencji Author. Zmiana ta polegała by na ekstrakcji pola id jako klucza do map. Na razie olać.

Pytanie 1. Co robi programista?

Mamy już „Bazę danych”, która ma nawet „Indeks” w czym zatem problem? Przyjrzymy się takiemu oto kodowi:

Authors authors = new Authors();<br></br>authors.add(new Author(0, "a"));<br></br>authors.add(new Author(1, "b"));<br></br>

Widać w czym problem? Dla mało spostrzegawczych nie ma możliwości dodawania autorów do indeksu tak by obiekt dodany do tabeli i obiekt dodany do indeksu był to ten sam obiekt. Musimy zatem nadpisać metodę add() dla klasy Authors.
Nowa klasa wygląda tak:

public class Authors extends LinkedList<author> {<br></br><br></br> private static final long serialVersionUID = 1L;<br></br><br></br> private static AuthorsNameIndex authorsNameIndex = new AuthorsNameIndex();<br></br><br></br> @Override<br></br> public boolean add(Author o) {<br></br>  boolean b = super.add(o);<br></br>  authorsNameIndex.put(o.getName(), o);<br></br>  return b;<br></br> }<br></br><br></br> public Author get(String name) {<br></br>  return authorsNameIndex.get(name);<br></br> }<br></br><br></br>}</author>

Klasa została wzbogacona o indeks i metodę wybierającą na podstawie danych z indeksu.

Teraz wystarczy napisać testy i bangla 🙂