Muszę zaimplementować generowanie wykresów z pewnego zbioru danych.
Dane te będą pochodziły z bazy danych i będą miały postać:
SELECT column, count(column) from tabele where warunek1 group by column order by column;
SELECT column, count(column) from tabele where warunek2 group by column order by column;
Kolumnowy wykres będzie przedstawiał liczność w każdym z przedziałów. W praktyce
użytkownik może dodawać, usuwać oraz ustawiać każdy z poszczególnych przedziałów,
a zmiany na wykresie mają być nanoszone dynamicznie. Do rysowania wykresów
używam biblioteki JFreeChart. Teraz kawałek kodu:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test<E extends Comparable<E>> {
List<Element<E>> data1 = new ArrayList<Element<E>>();
List<Element<E>> data2 = new ArrayList<Element<E>>();
List<E> divs = new ArrayList<E>();
List<Integer> cardinality1 = new ArrayList<Integer>();
List<Integer> cardinality2 = new ArrayList<Integer>();
public void doIt() {
Iterator<Element<E>> iter = data1.iterator();
boolean overflow = false;
a:
for(int i = 0; i < divs.size(); i++) {
while(iter.hasNext()) {
Element<E> e = iter.next();
if(e.element.compareTo(divs.get(i)) <= 0) {
cardinality1.set(i, cardinality1.get(i) + e.cardinality);
} else {
/* W przypadku gdyby ostatni element nie okazał się końcowym */
if(i + 1 >= cardinality1.size()) {
overflow = true;
break;
}
cardinality1.set(i + 1, e.cardinality);
continue a;
}
}
break;
}
/* Jesli jakies elementy zostaly to dodaj je na koniec */
if(!overflow) {
int size = 0;
while(iter.hasNext()) {
size += iter.next().cardinality;
}
int last = cardinality1.size() - 1;
cardinality1.set(last, cardinality1.get(last) + size);
}
/* To samo dla drugiego przedziału ...*/
}
public static void main(String[] args) {
Test<String> test = new Test<String>();
test.data1.add(new Element<String>("ala", 3));
test.data1.add(new Element<String>("alicja", 5));
test.data1.add(new Element<String>("anna", 7));
test.data1.add(new Element<String>("basia", 8));
test.data1.add(new Element<String>("beata", 1));
test.data1.add(new Element<String>("celina", 1));
test.data1.add(new Element<String>("dagmara", 4));
test.data1.add(new Element<String>("dominika", 9));
test.data1.add(new Element<String>("elzbieta", 2));
test.data1.add(new Element<String>("filipina", 5));
/* Przedziały pochodzą ze zbioru wyżej */
test.divs.add("ala");
test.divs.add("beata");
test.divs.add("dagmara");
test.divs.add("filipina");
/* Zerujemy każdy z przedziałów */
test.cardinality1.add(0);
test.cardinality1.add(0);
test.cardinality1.add(0);
test.cardinality1.add(0);
/* Przykład działania */
test.doIt();
for(Integer i : test.cardinality1) {
System.out.println(i);
}
}
}
class Element<E> {
E element;
int cardinality;
public Element(E element, int cardinality) {
this.element = element;
this.cardinality = cardinality;
}
}
Pierwsze pytanie : czy da się to zrobić prościej?
Oczywiście nie przeliczam wszystkiego za każdym razem tylko zmieniam poszczególne przedziały (kodu nie wrzucam).
Po każdym przeliczeniu liczności tworzę DefaultCategoryDataset i nanoszę go na wykres.
Drugie pytanie związane jest z samą javą:
Takie rozwiązanie ma jeden problem - nie każda klasa posiada interface Comparable<E>.
Głównie chodzi mi o klasę java.sql.Date. java.sql.Date dziedziczy po java.util.Date która implementuje Comparable<java.utli.Date>, jednak sama
nie może zaimplementować drugi raz interfacu Comparable (swoją drogą mogli by to wprowadzić kiedyś) i o
ile java.sql.Date nie dodaje żadnych pól u siebie i można by stosować bezpiecznie metode compareTo() z klasy java.util.Date to już Timestamp dodaje pole nanos.
Jak zrobić to bardziej przenośnym?
Mogę oczywiście dostarczać komparator do każdej klasy ale to jest kopiowanie kodu, który potrzebny jest tylko w paru przypadkach.
public class Test<E, T extends Comparator<E>>
Mogę też nie przejmować się i traktować zarówno java.sql.Date oraz Timestamp jak java.util.Date, ale nie jestem pewien tego rozwiązania.
Pozdrawiam.