# ArrayList Inhalt zählen



## JonnieWalker (16. Apr 2010)

Hallo Leute ich hab mal ne Frage.

Wieso zählt meine JList alle Datensätze doppelt?
Ich hab eine FensterKlasse die heisst "Wortliste" dort hol ich mir meine Datensätze aus
der SQLDatenbank. Das klappt alles super!
in der JListe bekomm ich die Datensätze wie in der der Datenbank z.B. 
30 Datensätze in der Db
30 in der jList.

ich hab aber in dem Fenster halt noch so ein Feld wo er mir die aktuelle Anzahl der Datensätze 
der jList ausgibt. Er macht die immer doppelt

Das ist die Anweisung damit er mir die Anzahl der Datensätze anzeigt:

```
ArrayList<Words>retWords = db.getWords();
        fensterWortliste.GesFilterWoerter.setText(""+retWords.size());
```


----------



## Foermchen82 (16. Apr 2010)

Erstmal ist deine Anweisung so korrekt. Nur was soll dass "" bedeuten? pack doch nur sie size() rein.

hast du auch mal mit dem Debugger geschaut, dass auch wirklich nur 30 DatenSätze in der Liste sind? Wenn du jetzt via System.out.println() die size auf der Konsole ausgeben lässt, was kommt dann?


----------



## JonnieWalker (16. Apr 2010)

hmm ich weiss es nicht:S
wie meinst du das nur die size() rein?
also in der datenbank sind 28 datensätze

es ist ja so inder db hab ihc zwei felder
einmal 
wordID not null
word

und ich lasse mir nur das word ausgeben
er macht aber 56 datensätze mir dann ausgeben obwohl er mir nur 28 in der liste anzeigt.
glaubst du das liegt daran das er zwar mir die id nicht anzeigt weil ich es auch nicht will,
sondern nur halt das word anzeigen.

ich guck mal mit system.out was er mir gibt


----------



## JonnieWalker (16. Apr 2010)

auch wenn ich System.out.println(retWords.size()); gibt er mir 54 aus:S
ich glaube das liegt daran das die wordID in der DB mitberücksichtigt wird
obwohl ich ihm in der Methode sage nur das word zurückgeben.

die wordID ist auch in der DB auf autoincrement gestellt.

Ist das der Grund also der obere


----------



## Foermchen82 (16. Apr 2010)

Mit " nur die size() " meine ich


```
fensterWortliste.GesFilterWoerter.setText(""+retWords.size());
```

poste doch auch mal das was hinter db.getWords(); steckt. Vielleicht liegt da ja schon der Fehler


----------



## JonnieWalker (16. Apr 2010)

ok also das its die Methode:


```
public ArrayList<Words> getWords() {
        Words Datensatz;
        ResultSet daten;
        String eigAnzahl;
        String eigBuchst;
        String eigZBS;
        try {
            Statement anweisung = v2.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                    ResultSet.CONCUR_READ_ONLY);
            eigAnzahl = FensterWortliste.tfAnzBuch.getText();
            eigBuchst = FensterWortliste.tfAnfangBuch.getText();
            eigZBS = FensterWortliste.tfZeichen.getText();
            daten = anweisung.executeQuery("SELECT word FROM eloftwords WHERE len(word)>"
                    + " " + eigAnzahl + " AND word LIKE '" + eigBuchst
                    + "%' AND word LIKE '%" + eigZBS + "%'");
            while (daten.next()) {
                Datensatz = new Words(
                        daten.getString("word"));

                retWords.add(Datensatz);
            }
        } catch (Exception ex) {
        }
        return retWords;
    }
```


----------



## SlaterB (16. Apr 2010)

alles liegt vor dir, du musst es nur prüfen, wieso ist in der Schleife kein System.out.println drin 
"lade nun Datensatz word .., Größe der Liste = .. "

so könntest du lockerleicht erkennen, das retWords zu Beginn der Methode schon einen Inhalt hatte,
bei jedem Ausführen werden immer wieder 28 dazugelegt, die alten bleiben dabei


----------



## Foermchen82 (16. Apr 2010)

Wo und wie wird denn retWords initialisiert? Kann es sein, dass du bei jeder neuen DB-Abfrage einfach der Liste hinzufügst und sie vorher nicht leerst?


----------



## JonnieWalker (16. Apr 2010)

hmm könntest du dich etwas anders ausdrücken und mir genau sagen was ich machen soll
bitte!


----------



## Foermchen82 (16. Apr 2010)

benutze in deiner getWords-Methode eine neue Liste, die du als Rückgabewert verwendest, oder rufe auf retWords erst clear() auf. Wobei ich erstes bevorzugen würde


----------



## JonnieWalker (16. Apr 2010)

danke jungs e shat geklappt
ich habe vor retWords.add(Datensatz);
retWords.clear();

vielen dank

also so jetzt:

retWords.clear();
ich habe vor retWords.add(Datensatz);


----------



## JonnieWalker (16. Apr 2010)

hmm jungs geht doch nicht:S
retWords.clear();
retWords.add(Datensatz);

so gibt er mir immer nur einen Datensatz immer den letzten in der DB:S


----------



## Foermchen82 (16. Apr 2010)

du rufst das clear natürlich vor deinem Datenbank aufruf auf und nicht vor jedem einfügen!!!


----------



## JonnieWalker (16. Apr 2010)

Jungs diesmal funktioniert es wirklich
danke für euere Anregungen

Hier die Methode vllt braucht das mal jemand:

```
public ArrayList<Words> getWords() {
        Words Datensatz;
        ResultSet daten;
        String eigAnzahl;
        String eigBuchst;
        String eigZBS;
        try {
            Statement anweisung = v2.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                    ResultSet.CONCUR_READ_ONLY);
            eigAnzahl = FensterWortliste.tfAnzBuch.getText();
            eigBuchst = FensterWortliste.tfAnfangBuch.getText();
            eigZBS = FensterWortliste.tfZeichen.getText();
            daten = anweisung.executeQuery("SELECT word FROM eloftwords WHERE len(word)>"
                    + " " + eigAnzahl + " AND word LIKE '" + eigBuchst
                    + "%' AND word LIKE '%" + eigZBS + "%'");
            retWords.clear();
            while (daten.next()) {
                Datensatz = new Words(
                        daten.getString("word"));
                retWords.add(Datensatz);
                
            }
        } catch (Exception ex) {
        }
        return retWords;
```


----------



## SlaterB (16. Apr 2010)

} catch (Exception ex) {
        }

->

} catch (Exception ex) {
throw new RuntimeException(ex);
        }


----------



## JonnieWalker (16. Apr 2010)

jetzt aber mal etwas anderes noch.

mit der Methode von eben auf eine Datenbank ausgeführt die 250.000 Datensätze beinhaltet!
Der braucht richtig lange und er macht es auch nicht!

was soll ich machen?


----------



## JonnieWalker (16. Apr 2010)

kann es sein das die ArrayList bei solchen größen nicht geeigent ist?
wenn ja gibt es was anderes?


----------



## Sonecc (16. Apr 2010)

Die ArrayList sollte mit einer passenden Größe initialisiert werden, sonst kann es schonmal länger dauern, wenn sie sich zig mal selbst vergößern muss


----------



## Foermchen82 (16. Apr 2010)

Das liegt nicht an der ArrayList sondern an dem Statement. Du gehts mit zwei Like Anweisungen über 250000 Datensätze. Das dauert halt


----------



## JonnieWalker (16. Apr 2010)

also soll ich das so lassen?


----------



## Sonecc (16. Apr 2010)

Foermchen82 hat gesagt.:


> Das liegt nicht an der ArrayList sondern an dem Statement. Du gehts mit zwei Like Anweisungen über 250000 Datensätze. Das dauert halt



Wenn du eine ArrayList erzeugst und ihr die größe nicht passend gibst, brauchst du bei 250000 Einträgen eine Ewigkeit...
Nur als Beispiel:

Die ArrayList wird mit 10 im Standard initialisiert.
beim ersten vergößern der Liste wird diese auf 16 erhöht.
Beim zweiten vergößern auf 25 usw. (die Formel ist (x * 3) / 2 + 1)
Dazu wird jedes mal das alte Array in das neue kopiert.
Das dauert....

Edit: Ich mess mal nach, wie lange das so dauern kann


----------



## JonnieWalker (16. Apr 2010)

wie kann ich den eine ArrayList die Größe angeben???


----------



## Sonecc (16. Apr 2010)

Folgendes erzeugte eine Liste mit der Größe 255000

```
ArrayList<String> list = new ArrayList<String>(255000);
```

Eine nicht initialisierte Liste braucht doppelt so lange um die Daten aufzunehmen. Allerdings sind die Zeiten bei den Anzahlen noch gering, wie ich beim test festgestellt habe.


----------



## SlaterB (16. Apr 2010)

das Vergrößern der ArrayList auf 255.000 für sich dauert pauschal so lange wie 100 der 255.000 Datensätze aus der DB zu lesen


----------



## Sonecc (16. Apr 2010)

hab ja nicht behauptet, dass es nicht auch an der db liegt, sondern nur festgestellt, dass es auch an der arraylist liegt.
Wie gesagt, bei 255000 Werten ist das noch eher zu vernachlässigen, aber bei 1 Milionen Daten hat man schon einen spürbaren unterschied erreicht


----------



## JonnieWalker (16. Apr 2010)

```
Hier ist die dekleration der ArrayListe:
ArrayList<Words> retWords = new ArrayList<Words>();


Das ist meine Methode die mir die Wörter aus der DB holt:
 public ArrayList<Words> getWords() {
        Words Datensatz;
        ResultSet daten;
        String eigAnzahl;
        String eigBuchst;
        String eigZBS;
        try {
            Statement anweisung = v2.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                    ResultSet.CONCUR_READ_ONLY);
            eigAnzahl = FensterWortliste.tfAnzBuch.getText();
            eigBuchst = FensterWortliste.tfAnfangBuch.getText();
            eigZBS = FensterWortliste.tfZeichen.getText();
            daten = anweisung.executeQuery("SELECT word FROM eloftwords WHERE len(word)>"
                    + " " + eigAnzahl + " AND word LIKE '" + eigBuchst
                    + "%' AND word LIKE '%" + eigZBS + "%'");
            retWords.clear();
            while (daten.next()) {
                Datensatz = new Words(
                        daten.getString("word"));
                retWords.add(Datensatz);
                
            }
        } catch (Exception ex) {
        }
        return retWords;

    }
```
ich hab die Suchkriterien etwas geändert
also 
er sucht gerade nach word in der eloftsword
die wörter in dennen ein "h" vorkommt
die Datenbank hat 4sec. gebraucht und gab mir 44597 Datensätze aus.
Mal gucken wie lange die ArrayList braucht:S

kannst du mir sagen wie ich die ArrayList vergrößere?

Beides findet in der Klasse Datenbank.java statt.


----------



## Sonecc (16. Apr 2010)

Wie schon gesagt, bei so geringen Anzahlen ist es noch nicht so brisant.
Schlimmer finde ich da eh, dass die Liste nicht in der Methode erzeugt wird, sondern davor.
Du kannst so nicht vorher schon angeben wie groß sie sein kann, weil du vorher gar nicht weißt, wie groß sie sein muss.
Das weißt du erst, wenn du die Daten ausgelesen hast

4 sekunden für 45000 Datensätze finde ich übrigens irgendwie lange...


----------



## JonnieWalker (16. Apr 2010)

ok es sind jetzt 6 min schon und er rechnet immer noch???
bist du sicher es sind gerade mal 44.000 datensätze!

nein der server hat 0.4sec gebraucht!


----------



## Sonecc (16. Apr 2010)

ahh.. 0.4 sekunden ist schon was ganz anderes^^

Woran rechnet er immer noch?
Am einfügen der Daten in die ArrayList?


----------



## JonnieWalker (16. Apr 2010)

er ist immer noch am rechnen!
ja also er soll das in die ArrayList holen
aber er rechnet immer noch!

was soll ich machen????


----------



## Sonecc (16. Apr 2010)

schreib mal in die while schleife ein system out , so dass du sehen kannst, wie oft er sie durchläuft und ob sie überhaupt ein ende nimmt.


----------



## JonnieWalker (16. Apr 2010)

also die schleife läuft gerade
das system.out
wioe du gesagt hast

er macht das so

1.hallo
2. hallo, der
3. hallo, der , mensch usw
er geht jetzt immer so weiter!
holt sich das erste wort
also 
1
dann 2= 1,2
dann 3,= 1,2,3 usw

hmm i-was stimmt doch hier nicht


----------



## Sonecc (16. Apr 2010)

zeig ma den code mit der system out drin


----------



## JonnieWalker (16. Apr 2010)

hier die methode:

```
public ArrayList<Words> getWords() {
            Words Datensatz;
            ResultSet daten;
            String eigAnzahl;
            String eigBuchst;
            String eigZBS;
            try {
                Statement anweisung = v2.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                        ResultSet.CONCUR_READ_ONLY);
                eigAnzahl = FensterWortliste.tfAnzBuch.getText();
                eigBuchst = FensterWortliste.tfAnfangBuch.getText();
                eigZBS = FensterWortliste.tfZeichen.getText();
                daten = anweisung.executeQuery("SELECT word FROM eloftwords WHERE len(word)>"
                        + " " + eigAnzahl + " AND word LIKE '" + eigBuchst
                        + "%' AND word LIKE '%" + eigZBS + "%'");
                retWords.clear();
                while (daten.next()) {
                    Datensatz = new Words(
                            daten.getString("word"));
                    retWords.add(Datensatz);
                    System.out.println(retWords +"/n");

                }
            } catch (Exception ex) {
            }
            return retWords;

        }
```


----------



## Sonecc (16. Apr 2010)

doch is scho richtig so...
nur warum er nicht aufhört weiß ich nicht


----------



## JonnieWalker (16. Apr 2010)

f+++
und was mach ich jetzt?:S:S:S:


----------



## Foermchen82 (16. Apr 2010)

Du weißt doch am Anfang, wie viele Datensätze er geladen hat. Dann kannst du doch anhand der Ausgabe sehen ob er dort schon ist oder nicht.
Wenn das sol lange dauert, wie viele Datensätze sind es denn, und wo ist er bei der Ausgabe, wenn du sagst, er läuft immer weiter?


----------



## JonnieWalker (16. Apr 2010)

wie sag ich ihm das er mir doe worte einmal ausgibt und untereinander
im System.out in der Methode???

kannst du mir das sagen?


----------



## JonnieWalker (16. Apr 2010)

ok jetzt hab ich ein System.out. unter einander machen lassen
jedes wort einmal

mal gucken ob er die Datensätze anzeigt alle 44.000
bis jetzt läuft es ganz gut


----------



## Foermchen82 (16. Apr 2010)

Statt

[Java]
System.out.println(retWords +"/n");
[/Java]

machst du


```
System.out.println(Datensatz);
```


----------



## JonnieWalker (16. Apr 2010)

also er schreibt jeden Datensatz sauber untereinander
und macht auch alle 44.000
mal gucken wie lange er für alle braucht!

aber wieso er es im Array nicht macht also solange braucht hab ich echt keine Ahnung


----------



## JonnieWalker (16. Apr 2010)

ej Leute hat echt keiner eine Idee
der macht immer noch in der Konsole und gibt die Daten aus!
Das dauert aber viel zu lange schon:S

Bitte hilft mir wenn jemand ne Idee hat.
dankeeeeeee


----------



## Foermchen82 (16. Apr 2010)

44000 zeilen auf die Konsole zu schreiben dauert halt ne ganze weile


----------



## JonnieWalker (16. Apr 2010)

er ist gerade mal bei der wordID 467
so es sind noch über 43.100 wörter die er schreiben muss in die Konsole.
Aber er macht es,

Nur was ist mit der ArrayList die sollte doch in der Lage sein so schnell wie möglich diese Datensätze anzuzeigen?????
Das ist mein Problem, die Konsole ist eigendlich unwichtig.


----------



## eRaaaa (16. Apr 2010)

ResultSet (Java Platform SE 6)
->


> In general, using the column index will be more efficient.



könnte also evtl. schon was bringen.

Und

```
ResultSet.TYPE_SCROLL_SENSITIVE
```
 : ist das vllt auch ne Bremse? Brauchen scheinst du das ja anscheinend nicht, oder? Ob das nun auch ausschlaggebend sein kann weiß ich nicht, ist nur ne Idee ^^


----------



## Sonecc (16. Apr 2010)

kann es vielleicht sein, dass er bei jedem schleifendurchlauf die abfrage nochmal macht (bin nicht so bewandert in der Datenbankprogrammierung...)


----------



## JonnieWalker (16. Apr 2010)

wie kann ich in der Methode so ne Bremse einbauen!
bsp. wenn 300 Datensätze der Abfrage vorliegen aufhören!

die Methode hier:


```
public ArrayList<Words> getWords() {
            Words Datensatz;
            ResultSet daten;
            String eigAnzahl;
            String eigBuchst;
            String eigZBS;
            try {
                Statement anweisung = v2.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                        ResultSet.CONCUR_READ_ONLY);
                eigAnzahl = FensterWortliste.tfAnzBuch.getText();
                eigBuchst = FensterWortliste.tfAnfangBuch.getText();
                eigZBS = FensterWortliste.tfZeichen.getText();
                daten = anweisung.executeQuery("SELECT word FROM eloftwords WHERE len(word)>"
                        + " " + eigAnzahl + " AND word LIKE '" + eigBuchst
                        + "%' AND word LIKE '%" + eigZBS + "%'");
                retWords.clear();
                while (daten.next()) {
                    Datensatz = new Words(
                            daten.getString("word"));
                    retWords.add(Datensatz);
                    System.out.println(Datensatz);

                }
                
                    
                
            } catch (Exception ex) {
            }
            return retWords;

        }
```


----------



## JonnieWalker (16. Apr 2010)

ich hab da an sowas gedacht:


```
if(ResultSet.daten >= 200){
                    System.out.println("Ende erreicht");
                }
```

also wenn er bei 300 Datensätzen ist ende.


----------



## JonnieWalker (16. Apr 2010)

ich hab das mal nach der while-Schleife eingebaut


```
if(retWords.size() >= 200){
 Syste.out.println("Ende");
}
```

ich denke er hört gleich bei 200 Datensätzen auf


----------



## Gast2 (16. Apr 2010)

Ist halt nicht wirklich performant da für das zweite LIKE ein Fulltable Scan gemacht werden muss. Da hilft dir auch kein Index. ich würde eher überlegen ob das Statement so sinnvoll ist oder ob du das noch ein bisserl besser eingrenzen kannst.

Nebenbei - wenn ich das richjtig sehe kommen ja die Eingaben die du mit dem SQL verkettest aus einer GUI. Dann solltest du gaaaaaanz dringend PreparedStatements verweden (Stichwort SQL Injection und String Quoting).

EDIT: huch... da bin ich wohl um ein oder zwei Seiten verutscht.. Sorry


----------



## JonnieWalker (16. Apr 2010)

war das jetzt für mich?


----------



## Gast2 (16. Apr 2010)

Jein, hatte irgendwie nur Seite 1 bis unten gelesen... und dann nach der Antwort gemerkt das es noch drei Seiten weiterging :/

Was willst du denn genau limitieren? Am ebsten wäre es natürlich den SELECT gleich mit zu begrenzen. z.B. in MYSQL mit LIMIT.

1) SELECT COUNT(*) - gesamtzahl ermitteln
2) In 200 Schritten Daten holen.

Ich denke es gibt aber auch ein lazy fetching für MySQL das nur erstmal x rows holt und dann nachfetcht wenn noch mehr da sind - siehe MySQL :: MySQL 5.1 Reference Manual :: 21.3.4.2 JDBC API Implementation Notes unter ResultSet

Der Kommentar zur GUI und Prepared Statements gilt natürlich noch


----------



## JonnieWalker (19. Apr 2010)

wie setzt ich den dieses limit ein?


----------



## Gast2 (19. Apr 2010)

```
SELECT * FROM test LIMIT <OFFSET>, <ANZAHL>
```


----------

