Alternative für mehrdimensionales Array

Nisbo

Bekanntes Mitglied
Servus,

ich habe in einer CSV Datei Datensätze welche über 16 Spalten gehen, die Zeilenanzahl ist variabel und somit fallen Arrays schon mal raus.

Idee wäre evtl eine Arraylist in einer Arraylist.

Was ich aber gerne machen möchte ist in dem "Array" suchen und evtl sortieren

daten[1][0] = "Berlin"
daten[1][1] = "Max"
daten[1][2] = "Mustermann"
daten[2][0] = "Hamburg"
daten[2][1] = "Max"
daten[2][2] = "Mustermann"
daten[3][0] = "Dortmund"
daten[3][1] = "Max"
daten[3][2] = "Mustermann"

Geht sowas dann mit einer Arraylist in einer Arraylist ?
Oder gibt es da was besseres ?

Am liebsten wäre mir ja ein Equivalent zu einer MySQL Datenbank 😀 (ohne eine solche installieren zu müssen)
SELECT * FROM meinetabelle WHERE ort = 'Berlin' SORT BY vorname ASC;
 
Am besten wären vernünftige Objekte für sowas 😉

Jede Zeile ein Objekt (mit Ort, Name, Vorname in dem Beispiel) und alle Zeilen in einer List.

Das suchen/sortieren lässt sich damit dann recht leicht implementieren, zB mit mit Streams, oder halt eigenen Methoden dafür
 
Bei Objekt fällt mir das erst mal so ein, funktioniert soweit auch mehrdimensional nur muss ich auch hier vorher sagen wieviele Zeilen ich habe. Zum Testen habe ich da einfach mal 2000 angegeben aber das ist ja nicht Sinn der Sache

Java:
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        InputStream inputStream = (InputStream) conn.getContent();
        Scanner scanner = new Scanner(inputStream);
      
      
        Integer ccc = 0;
        Object[][] data = new Object[2000][16];

        while (scanner.hasNext()) {
            //  System.out.println(scanner.nextLine());

            String[] splitti = scanner.nextLine().split(";");
          
            if(splitti[0].contains("num")) continue;

            data[ccc][0] = splitti[0];
            data[ccc][1] = splitti[1];
            data[ccc][2] = splitti[2];
            data[ccc][3] = splitti[3];
          
            System.out.println(data[ccc][1]);
            ccc++;
        }
      
        System.out.println("Test:" + data[222][1]);
 
Deine Lösung ist ein mehrdimensionales Arrays ohne Verwendung sinnvoller Objekte, also genau das, was du nicht wolltest 😉

Erstell dir eine Klasse, die eine Zeile deiner CSV repräsentiert, und dann Benutz eine Liste, zB ArrayList, von Objekten deiner Klasse.
 
Also rein bekomme ich die Daten schon mal, glaube ich zumindest ^^

Java:
private ArrayList<ChannelList> ArrayListChannels;
.
.
.
this.ArrayListChannels = new ArrayList<ChannelList>();

.
.
.

// in der Schleife beim Einlesen
this.ArrayListChannels.add(new ChannelList(splitti[0],
                    splitti[1],
                    splitti[2],
                    splitti[3],
                    splitti[4],
                    splitti[5],
                    splitti[6],
                    splitti[7],
                    splitti[8],
                    splitti[9],
                    splitti[10],
                    splitti[11],
                    splitti[12],
                    splitti[13],
                    splitti[14],
                    splitti[15]));

.
.
.

// nach der Schleife gibt zumindest die Größe aus
System.out.println("Test:" + this.ArrayListChannels.size());

hier die Class
Java:
public class ChannelList {

    private String testtest;
   
    public ChannelList(
            String aaa,
            String bbb,
            String ccc,
            String ddd,
            String eee,
            String fff,
            String ggg,
            String hhh,
            String iii,
            String jjj,
            String kkk,
            String lll,
            String mmm,
            String nnn,
            String ooo,
            String longcall){
        testtest= aaa;
    }
   
    public void test123(){
       
    }
}

wie komme ich da jetzt an die einzelnen Daten wieder ran ?
System.out.println("Test:" + this.ArrayListChannels.get(222));
gibt mir wieder
Test:de.meineseite.dcc.ChannelList@6204328f
 
Erstmal vorab, kennst du dich Grundsätzlich mit Java aus?
Erstell dir sinnvolle Klassen, mit sinnvollen Variablen und sinnvollen Methoden, um diese abzufragen.
 
Die Variabeln sind doch nur zur Demo, die sind im Programm schon anders benannt.
Ansonsten bin ich ja hier im Anfängerforum zum lernen.

Aber ich glaube ich gabe die Getter vergessen
 
mit den Gettern gehts nun
Java:
public String getNum(){
        return num;
    }
zum abfragen dann z.b.
Java:
this.ArrayListChannels.get(223).getNum();

Ja so langsam macht es bei mir Click 😀
 
Verschachtelte Listen heißt hier das Zauberwort...

SQLite serverless ginge natürlich auch, nur wie überführst du von einem Datentyp in den anderen... Das macht dann kein Spaß
 
Als erstes solltest du dir einen entsprechenden Datentypen erstellen. In deinem Fall sicherlich eine Klasse Person mit den Attributen Name Vorname und Ort.
Die Daten kannst du dann in einer List<Person> speichern.

Mit CQEngine lassen sich auch Collections mit einer SQL Syntax abfragen:
https://github.com/npgall/cqengine

Java:
import com.googlecode.cqengine.ConcurrentIndexedCollection;
import com.googlecode.cqengine.IndexedCollection;
import com.googlecode.cqengine.codegen.AttributeBytecodeGenerator;
import com.googlecode.cqengine.query.parser.sql.SQLParser;
import com.googlecode.cqengine.resultset.ResultSet;
import com.googlecode.cqengine.testutil.Car;
import com.googlecode.cqengine.testutil.CarFactory;
import static com.googlecode.cqengine.codegen.AttributeBytecodeGenerator.createAttributes;

public class SQLQueryDemo {

public static void main(String[] args) {
    SQLParser<Person> parser = SQLParser.forPojoWithAttributes(Person.class, createAttributes(Person.class));
    IndexedCollection<Person> persons = new ConcurrentIndexedCollection<Person>();
  
    persons.add(new Person("Berlin", "Max", "Mustermann"));
    persons.add(new Person("Hamburg", "Max", "Mustermann"));
    persons.add(new Person("Dortmund", "Max", "Mustermann"));
  
    ResultSet<Person> results = parser.retrieve(persons, "SELECT * FROM persons WHERE " +
                                    "ort = 'Berlin' "  +
                                    "ORDER BY vorname ASC ");
    for (Person p : results) {
        System.out.println(p);
    }
}

}
 
Zuletzt bearbeitet:
Oder mit Stream:
Java:
List<Person> berliner = all.stream()
                .filter(person -> person.getOrt.equals("Berlin"))
                .sorted(Comparator.comparing(Person::getVorname))
                .collect(Collectors.toList());
 
Danke Danke so habe ich es inzwischen schon gemacht, also Klasse mit Setter und Getter.
Jetzt wo ich das langsam verstehe macht es auch wieder Sinn 😀 und sogar Spaß 😀 😀 😀

Momentan bin ich dran die Datensätze sortiert auszugeben
Collections.sort(ArrayList);
geht da leider nicht ganz so einfach da meine Arraylist ja Objekte enthält, mache das jetzt halt übern Umweg einer weiteren Arrylist, in dem Code hier für das Dropdown der Länder (wird noch in eine List verlagert wegen MultiSelect

Java:
    public void createCountryList(){
        Integer ii = 0;
      
        // get all available Country --> to a ArrayList
        while (ii < this.ArrayListChannels.size()){
            if(!this.ArrayListCountry.contains(this.ArrayListChannels.get(ii).getCountry())){
                this.ArrayListCountry.add(this.ArrayListChannels.get(ii).getCountry());
            }
            ii++;
        }
      
        // Sort the Country Array List and generate DropDown
        ii = 0;
        Collections.sort(ArrayListCountry);
        this.ComboBox_Country_Box.removeAllItems();
        while (ii < this.ArrayListCountry.size()){
            this.ComboBox_Country_Box.addItem(this.ArrayListCountry.get(ii));
            ii++;
        }
    }
 
Was willst du denn da machen? Aus der Liste der Objekte eine Liste von Orten erstellen?

Guck dir mal foreach-Loops an 😉
 
Ich habe in meinem CSV Datensatz Angaben mit Ländern (nicht nur ein Eintrag pro Land) und nun will ich die im Datensatz verfügbaren Länder haben, natürlich nicht doppelt

SELECT country FROM datensatz GROUP BY country, SORT by country ASC

und ja foreach da haste wohl recht
 
OK dann muss ich mir Streams mal ansehen, toll wenn man so langsam dahinter steigt 😀

btw jetzt mit for(each)
Java:
    public void createCountryList(){
        // get all available Country --> to a ArrayList
        for(ChannelList entry: arrayListChannels){
            if(!this.arrayListCountry.contains(entry.getCountry())){
                this.arrayListCountry.add(entry.getCountry());
            }
        }

        // Sort the Country Array List and generate DropDown
        Collections.sort(arrayListCountry);
        for(String country: arrayListCountry){
            this.countryListModell.addElement(country);
        }
    }
 
So mal Stream getestet, coole Sache 🙂

so schauts jetzt bei mir aus
Java:
List<ChannelList> allCountries = arrayListChannels.stream()
                .filter(singleCountry -> singleCountry.getCountry().equals("Germany"))
                .distinct()
                .sorted(Comparator.comparing(ChannelList::getCountry))
                .collect(Collectors.toList());

Allerdings funktioniert .distinct() nicht oder ich habe nur keine Ahnung wie ich das richtig einsetze 😀 Soll ja im Endeffekt nur die Länderliste liefern und hätte dann in dem Fall nur einen Eintrag raus werfen dürfen da ja noch der Filter auf Germany drin war. Aber ich habe wie gesagt keine Ahnung wie ich .distinct() sage er soll nach getCountry gruppieren.

Was mir noch fehlt ist wie eine ODER Verknüpfung beim Filter geht, UND geht ja durch anhängen eines weiteren Filters
Java:
.filter(singleCountry -> singleCountry.getCountry().equals("Germany"))
.filter(singleNetwork -> singleNetwork .getNet().equals("BM"))

Hintergrund:
Ich habe verschiedene Netzwerke in verschiedenen Ländern, einige sind überregional und andere nur regional

Wenn jetzt ein Benutzer ein oder mehrere Länder auswählt dann werden alle verfügbaren Netzwerknamen angezeigt.

Jetzt will ich alle (ausgewählten) Netzwerke in den (ausgewählten) Ländern anzeigen
Ich brauche quasi sowas

Java:
.filter((singleCountry -> singleCountry.getCountry().equals("Germany") || (singleCountry -> singleCountry.getCountry().equals("Ausria") || (singleCountry -> singleCountry.getCountry().equals("Switzerland"))

AND

.filter((singleNetwork -> singleNetwork .getNet().equals("BM") || singleNetwork -> singleNetwork .getNet().equals("ABC") || singleNetwork -> singleNetwork .getNet().equals("XYZ")))
 
Allerdings funktioniert .distinct() nicht oder ich habe nur keine Ahnung wie ich das richtig einsetze 😀 Soll ja im Endeffekt nur die Länderliste liefern und hätte dann in dem Fall nur einen Eintrag raus werfen dürfen da ja noch der Filter auf Germany drin war. Aber ich habe wie gesagt keine Ahnung wie ich .distinct() sage er soll nach getCountry gruppieren.
Distinct wird auf das Objekt was grad benutzt wird, angewendet, entweder du implementierst #equals und #hashcode passend, oder du mapst das erst auf den String, der dich interessiert.

GroupBy ist was anderes als Distinct 😉

Jetzt will ich alle (ausgewählten) Netzwerke in den (ausgewählten) Ländern anzeigen
Ich brauche quasi sowas

.filter(singleCountry -> (singleCountry.getCountry().equals("Germany")||singleCountry.getCountry().equals("Austria")))
 
OK da verstehe ich jetzt nur Trainstation 😀
ist wohl für den Anfang dann doch etwas zu viel ^^

Das ODER und UND habe ich jetzt hinbekommen 🙂
Java:
.filter(singleCountry -> (singleCountry.getCountry().equals("Germany")||singleCountry.getCountry().equals("Austria")))
.filter(singleNetwork -> (singleNetwork.getNet().equals("BM")||singleNetwork.getNet().equals("XYZ")))
das muss jetzt natürlich nur noch dynamisch werden abhängig der jeweiligen Auswahl in den Listen

Java:
for (String selectedCount : this.CountryList.getSelectedValuesList()){
wie Du siehst hab eich mich gerade in for each Schleifen verliebt 😀
 
So ich bin stolz auf mich 😀

Habe jetzt die Dynamik rein gebracht in Abhängigkeit der JLists und deren Auswahl und möchte das der Allgemeinheit natürlich nicht vorenthalten falls jemand vor dem selben Problem steht

Java:
List<ChannelList> allCountries = arrayListChannels.stream()
                .filter(
                        singleCountry -> (
                                    getSelectedCountries(singleCountry)
                                )
                        )
                .filter(
                        singleNetwork -> (
                                    getSelectedNetworks(singleNetwork)
                                )
                        )
                .distinct()
                .sorted(Comparator.comparing(ChannelList::getCountry))
                .collect(Collectors.toList());

Java:
    private boolean getSelectedNetworks(ChannelList singleNetwork) {
        for (String selectedCount : this.networkList.getSelectedValuesList()){
            if(singleNetwork.getNet().equals(selectedCount)){
                return true;
            }
        }
       
        return false;
    }
   
   
    private boolean getSelectedCountries(ChannelList singleCountry) {
        for (String selectedCount : this.CountryList.getSelectedValuesList()){
            if(singleCountry.getCountry().equals(selectedCount)){
                return true;
            }
        }
       
        return false;
    }

das ist so cool wenn man das erst mal verstanden hat 😀
 
wieso ? fangen doch mit nem Kleinbuchstaben an ?
OK selectedCount könnte man anders nennen aber ansonsten sehe ich da kein Problem.

Ansonsten kläre mich mal auf, den Refractor --> Rename habe ich schon entdeckt 😀
 
Deine Klasse ChannelList ist keine Liste von Channels, sondern repräsentiert einen Channel (vermute ich mal...).

Deine arrayListChannels enthält den Typ der Liste - meistens schlechter Stil, sinnvoller wäre sowas wir einfach nur channels.

In #filter nennst du deine Listen-Elemente einmal singleCountry, und einmal singleNetwork, da die Liste Channel enthält, wäre in beiden Fällen einfach nur channel besser.

getSelectedNetworks und getSelectedCountries sind beides keine Getter, tun also nicht das, was der Name vermuten lässt (und auch wieder die Parameternamen wie bei den #filter). Besser wäre sowas wie checkNetwork.
 

Neue Themen


Zurück
Oben