HashMap verwirrt mich

R4M

R4M

Neues Mitglied
4
Als JS und PHP Programmierer sind mehrdimensionale Array eigentlich kein Problem, aber hier bei Java und HashMap werde ich bekloppt im Kopf.

Also, ich möchte dynamisch ein mehrdimensionale Array (mit String Inhalten) erstellen, später auch Sortieren und in JS würde es bei mir so aussehen:

Code:
meinArray[0] = { "key1" : val, "key2" : val, "key3" : val }
meinArray[1] = { "key1" : val, "key2" : val, "key3" : val }
meinArray[2] = { "key1" : val, "key2" : val, "key3" : val }

... oder ...

for ( var i = 0; i < 3; i++ ) {
  meinArray[i] = {
    "key1" : val,
    "key2" : val,
    "key3" : val
  }
}

Wie bereits erwähnt soll später dann z.B. nach Value von key2 sortiert werden. Nun dachte ich mir, ok, HashMap wäre hier eventuell das richtige für mich. Aber nach gefühlten 100 verschiedenen Beispielen (meist nur auf einfache Arrays) dreht sich mir der Kopf.

Code:
HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();
hm.put(???);
...

Aber wie es hier weiter gehen muss verstehe ich einfach nicht. Und ja, ich habe die Seite "Java ist auch nur eine Insel" gelesen. Gibt es hierzu noch eine andere Seite (wenn möglich in deutsch) die das ganze einfacher Erklärt?
 
Hallo R4M,

ich hatte dir bereits schon darauf geantwortet :)
Dynamische Einträge mit HashMap?

Post #5

Und Sortieren geht mit Collections.sort

Bei Android/Java solltest du grundsätzlich mehr in die C/C++ schiene denken.
Schleifen sind z.b. tötlich, sowas lagert man am besten in Threads aus (AsyncTask),
es sei denn sie sind ganz klein, dann kann man das "riskieren".
 
Zuletzt bearbeitet:
Hallo swa00,

ja ja ich weiß :) Dort bezog sich der Beitrag auf das Einspielen in ListView (was ich mit festen Testdaten) hinbekommen habe. Jetzt könnte ich meine Daten zwar einlesen, aber dann stehe ich beim nächsten Problem mit dem Sortieren. Also war jetzt mein Grundgedanke:

- Daten als String[] einlesen und daraus ein mehrdimensionales Array (hier dachte ich eben an HashMap) bauen
- Array so bauen, dass es sortierbar ist
- Array an ListView übergeben (ist praktisch fertig)

Und ja, das Array wird klein. Wir reden hier vielleicht von max. 50 Einträgen. Hmmm, ich könnte natürlich auf HashMap verzichten, wenn ich herausfinde wie ich ArrayList sortieren kann. Werde mich dazu noch mal belesen.
 
Hallo R4M,

ich denke , du stehst ziemlich auf dem Schlauch und ich versuche dir mal aus dem Sumpf zu helfen :)

Kommen wir einfach mal dazu, was du zum Schluss sortieren möchtest
Wir nehmen an , du möchtest ein mehrdimensionales Array, bestehend aus einem String und einem Integer .

Deklaration
class MyStruct
{
String strval;
int intval;
};

Dann deklarieren wir unser Array
ArrayList <MyStruct> MeinArray;

Dann initiieren
MeinArray = new ArrayList();


Jetzt Einträge aus deinem Ursprungsarray (String[]) hinzufügen - UND DA KANN DEINE SCHLEIFE GREIFFEN
for int i = 0; i < MeinEnde; i++)
{
MyStruct tmp = new MyStruct();
tmp.strval = DeinString_AN_POS_i;
tmp.intval = Was_auch_immer;
MeinArray.add();
}

Und jetzt sortieren wir
Collections.sort(MeinArray, new Comparator<MyStruct>() {
@override
public int compare(MyStruct s1, MyStruct s2)
{
return s1.strval.compareToIgnoreCase(s2.strval);
}
});

Thats it - NOT More :)


Verstanden ? :)
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: Kardroid
@R4M,

also du willst ein mehrdimensionales Array, und das ist nicht so schwer wie es aussieht. Es kommt da ganz darauf an wie du die Daten abfragen willst.

Beispiel:

daten[a][c] index als integer werte
oder
daten["a"]["b"]["c"] index als String werte

Bei einem normalem Array kann man direkt zuweise

daten[a][c] = xyz

HashMap sind Objekte und der Zugriff geht nur über eine Funktion get, put und einem Schlüsselwort, dafür sind sie dynamisch. Der Trick ist nun der, dass du deine KEY addiert

KEY1 + KEY2 + ..... + KEYn

dann wäre der Zugriff der daten.get(KEY1+KEY2+KEY.....)

oder beim schreiben daten.put(KEY1+KEY2+KEY...., Wert)

Da du aber unterschiedliche Datentypen speichern kannst ist der Datentyp beim schreiben immer Objekt und erst beim lesen wird der Datentyp angegeben, der natürlich auch stimmen muss

daten.getInt(KEY1+KEY2+KEY.....)
daten.getBoolean(KEY1+KEY2+KEY.....)
daten.getString(KEY1+KEY2+KEY.....)

Das wäre die einfachste Lösung. Jedoch ist das nicht immer optimal und um die optimale Lösung zu finden kommt es darauf an was du im Array Speichern willst und wie du es abfragen willst und so wie du oben erwähnt hast, wie du es sortieren willst.

Die erste Aufgabe ist die sich Gedanken über die Daten zumachen die man im Array speichern will. Also ein Konzept erarbeiten. Und dann wie man sie "abrufen" will, denn danach richtet sich das "wie" man es schreiben muss.

Alles klar?

Wenn nicht, dann kann ich die da schon weiterhelfen

Grüße
 
Erstmal Danke für eure Bemühungen mir hier auf die Sprünge zu helfen! Ja, der Schlauch auf dem ich stehe ist sowas von dick :)

Ich werde mir das am Wochenende noch mal in Ruhe reinziehen (müssen).
 
R4M schrieb:
Erstmal Danke für eure Bemühungen mir hier auf die Sprünge zu helfen! Ja, der Schlauch auf dem ich stehe ist sowas von dick :)

Ich werde mir das am Wochenende noch mal in Ruhe reinziehen (müssen).

Ist nicht schwer wie es dir nun vorkommt. Du kennst doch Excel, oder OpenOfficeCalc?, diese Tabellen sind im Grund 2 Dimensionale Arrays
Spalten A,B,C, .......
Zeilen 1,2,3, ........

Der Index auf eine Zelle ist dann
A1, A2, A3, .....
B1,B2,B3, ......
Und so weiter.

In einem Java Array würde der Zugriff dann so aussehen

Array[][] sheet = new Array[10][10];
.....
sheet[zeile][spalte] = "hugo"

in einer HashMap könnest du das so schreiben

Hashmap sheet = new Hashmap();

sheet.put("A1"), "hugo");
sheet.put("A2"), "peter");

Es ist da egal wie die Daten in Java organisiert sind, sondern nur wie man darauf zugreifen will.

Bei dem HashMap Beispiel hast du gesehen, dass ich die Vektoren Zeile und Spalte einfach aneinander geklebt habe. Eine HashMap braucht nur einen KEY also Schlüssen unter dem der Wert abgelegt wird. Und diesen KEY kannst du benennen wie du willst. Einzige Bedingung ist dafür zu sorgen, dass der KEY nur einmal vorkommt. Damit kannst du mit einer HashMap zur Laufzeit des Programms beliebig viele Dimensionen verwenden. Zum Beispiel x,y,z
Dimensionswerte:
x = 15
y = 20
z = 5
v = "Hugo"

Um nun einen KEY für die HashMap zu erzeugen
KEY = x + "," + y + "," + z;
das ergibt dann
KEY = "15,20,5"

Und der Zugriff wäre dann

sheet.put(KEY,v);

Auf diese weise kann dein Array beliebig viele Dimensionen zur Laufzeit haben.

Wenn du dies einfache Art der Verwendung verstanden hast, können wir "Verschachtelte" Arrays (Der Wert ist eine Array) ins Auge fassen :biggrin:

Aber nicht verzagen, das ist viel einfacher als es aussieht. :biggrin:

Grüße
 
Hallo,

danke auch dir für deine Bemühung! Ich werde damit mal am Wochenende experimentieren. Unter der Woche habe ich nach Feierabend dafür kein Kopf mehr frei. Das Prinzip mit Zweidimensionalen Arrays hab ich soweit auch verstanden. Wenn ich jedoch unter einem Key noch ein Array habe, ist bei mir Kurzschluss in der Birne :)
 
R4M schrieb:
Hallo,

danke auch dir für deine Bemühung! Ich werde damit mal am Wochenende experimentieren. Unter der Woche habe ich nach Feierabend dafür kein Kopf mehr frei. Das Prinzip mit Zweidimensionalen Arrays hab ich soweit auch verstanden. Wenn ich jedoch unter einem Key noch ein Array habe, ist bei mir Kurzschluss in der Birne :)

Ok, ich versuch dir mal das Prinzip einer HashMap zu erklären. Bei einem normalem Mehrdimensionalem Array wird Speicher reserviert.

Beispiel mit einem Integer Array:

int[] arr = new int[10]

Ein int hat 4 Byte es werden also 40 Byte reserviert. Die Variable arr enthält die RAM-Adresse auf die 1. 4 Byte.

arr[5] = 20;

5 ist der index von der Basisadresse also Basisadresse + 5*4 = Zieladresse.

Da der Bereich eines normalen Array festgelegt ist, kann es auch nicht erweitert werden.

int[][] arr = new int[5][7];

arr[3][2] = 10;

die Berechnung der Speicherstelle funktioniert im Prinzip wie folgt:

Basisadresse + 3*7*4 + 2*4 = Zieladresse im Ram

Du siehst, dass auch in Mehrdimensionalen Arrays die einzelnen Vektoren zu einem OFFSET zur Basis verrechnet werden.

Bei einer HashMap funktioniert das anders, da wird nicht mit einem festen Index (offset) gearbeitet sondern mit einem dynamisch errechneten Offset. Der dynamische Offset wird durch einen Beliebigen Text errechnet, das bedeutet, dass eine Algorithmus aus dem Text einen Wert den Hash errechnet.
Der Wert des Hash liegt normal zwischen 0-255

Im Prinzip entspricht eine HashMap dieser Darstellung

HasMap map = new HashMap();

entspricht

Object[] obj = new Object[255];

Der Zugriff würde dann im Prinzip so aussehen

int hash = getHash("irgendein Text");

obj[hash] = Object;

Eine Mehrdimensionale HashMap gibt es also nicht. Alle Vektoeren müssen dann zu einem TEXT zusammengepackt werden damit daraus ein Hash-Wert errechnet werden kann.

Eine HashMap enthält immer Objekt-Vertoren, die auf die Objekte verweisen. Der DatenTyp eier HasMap ist also immer Object.

Mann kann seit Java 5 diesen Objekttyp bei der Definition festlegen

HasMap map = new HashMap();


map.put("Adresse von Hans", "Nirgendwo" );
oder
map.put("Alter von Hans", 25);

Und nun zur verschachtelten HashMap

Wie oben erwähnt enthält eine HashMap immer ein Object. Wenn der Objekt-Typ immer der selbe ist kann man den auch bei der definition festlegen und spart sich casts

HashMap<string, HashMap> map = new HashMap():

HashMap<string, String> map_innen = new HashMap():

map_innen.put("alter", 25);


map.put("hans", map_innen);

map_innen = map.get("hans");
map_innen.get("alter);

Wie du siehst kannst du auf die in einer HashMap gespeicherten Objekte nicht direkt zugreifen, sondern du musst diese Objekte erst aus der HashMap mit get() auslesen und einer variablen zuweisen.

Beispiel:
Vergleichen wir die HashMap mit einem Schrank, dann kann ich in diesen eine Schuhschachtel mit Schuhe hinein stellen. Wenn ich nun die Schuhe anziehen will mus ich zu erst die Schachtel mit den Schuhen aus dem Schrank holen und kann dann auf den Inhalt der Schuhschachtel zugreifen.

Und so ist es auch mit HashMaps, auf die darin enthaltene Objekte kann ich nicht direkt zugreifen, die Objekte müssen erst mit get() aus der HashMap gelesen und einer variablen zugewiesen werden. Dann kann ich wie üblich auf das Objekt zugreifen.

Ich hoffe ich hab dich nun nicht noch mehr verwirrt :confused2:

Grüße
 
Kurze Zusammenfassung

HashMaps haben erst mal nichts mit Arrays zu tun. Normalerweise sind Arrays in der Größe beschränkt, man muss sie vor den Benutzen ihre Größe festlegen. Arrays kommen aus der strukturierten Programmierung. Arrays in PHP sind eine Kreuzung zwischen "richtigen" Arrays und Listen. Die Sprachentwickler wollten etwas mit den Vorteil aus beiden Welten.

In Java gibt es Listen und Maps. In Listen und Maps werden die Daten gestapelt (Stack). Um an Daten in einer Liste zu kommen, muss man alle Daten einzeln nacheinander abklappern, weil die einzelnen Daten (Objekte) kein Index haben. Das hört sich furchtbar umständlich an, aber viel mehr braucht man nicht. Ein guter Programmierer sortiert die Daten in einer Liste so, das er einfach nur jedes Glied einzeln abklappern muss.
Compiler funktionieren genauso. Sie sortieren den Quellcode so in einer Liste (Stack), das der Rechner einfach nur ein Glied nach dem andern abarbeitet.
Eine HashMap ist eine "Liste" , die aus einem Schlüssel (Key) und einem Objekt bestehen. Der Hash (Key) dient dazu ein Objekt in einer Liste zu finden, ähnlich der Speicherverwaltung im PC. Jede Speicher hat eine Adresse und Daten, welche unter der Adresse erreichbar sind.
Wenn ich jetzt ein bestimmtes Objekt suche, suche ich einfach den dazugehörigen Hash, und habe dann das passende Objekt.

Am nächsten kommt ein PHP Array die Arraylist. In Java braucht man kein 2 zweidimensionales Array. Wenn man so was braucht, packt man eine ArrayList in eine ArrayList.

Collections: Listen - Java als erste Programmiersprache - Javaschublade

Noch eine Anmerkung zu den Basisadressen. So etwas gibt es nicht wirklich in Java. Dort gibt eigentlich nur Referenzen. Die sehen ungefähr so aus:
"java.lang.String@Ae43a123". Es ähnelt den Zeigern, ist aber nicht das gleiche (leider, fehlt mir manchmal).
 
  • Danke
Reaktionen: swa00
markus.tullius schrieb:
Noch eine Anmerkung zu den Basisadressen. So etwas gibt es nicht wirklich in Java. Dort gibt eigentlich nur Referenzen. Die sehen ungefähr so aus:
"java.lang.String@Ae43a123". Es ähnelt den Zeigern, ist aber nicht das gleiche (leider, fehlt mir manchmal).

Es ähnelt nicht nur den Zeigen, es ist der Zeiger, den ohne diesen wäre die Echte stelle im RAM nicht zu finden. Und da ist es unerheblich ob dieser relativ oder absolut ist.

grüße
[doublepost=1480100200,1480099434][/doublepost]
markus.tullius schrieb:
Kurze Zusammenfassung

HashMaps haben erst mal nichts mit Arrays zu tun. Normalerweise sind Arrays in der Größe beschränkt, man muss sie vor den Benutzen ihre Größe festlegen. Arrays kommen aus der strukturierten Programmierung. Arrays in PHP sind eine Kreuzung zwischen "richtigen" Arrays und Listen.

Das kann ich so auch nicht stehen lassen, denn Array (deutsch Tabelle) ist im physischen RAM immer sequentiell, also immer eine Liste. Denn alle Speicherzellen (BYTE) sind im RAM, wie bei einer Perlenschnur, aneinander gereiht. Das bedeutet, dass jede Form von Tabelle immer nur eine Simulation einer Tabelle ist. Das bedeutet, das bei allen Arrays, egal wie viele Dimensionen es haben möchte, die Vektoren immer in einen Eindimensionalen Vektor umgerechnet werden.

int[][] arr = new int[10][10];

ist genau das selbe wie

int[] arr = new int[100];

nur mit dem Unterschied, dass ich die Berechnung der Offsets selber machen muss.

Ergo im Computer gibt es definitiv keine Tabellen sondern nur die Simulation von Tabellen.


Grüße
 
Dir ist klar, das Java unabhängig von der Rechner Architektur ist? Und Referenzen keine Zeiger sind.
Und bevor wir eine längere Diskussion anfangen, füge ich Dir die dazugehörige Dokus an:
https://docs.oracle.com/javase/specs/jvms/se7/jvms7.pdf
Für Android sieht es noch ein bisschen anders aus, das Stichwort ist ART.
 
Habe jetzt mal so mich einiges ausprobiert. Nun Ausgangspunkt ist String wie dieser hier:

Code:
String text = "";
text += "ID1, Uhu1, Geier1, Fuchs1 \n";
text += "ID2, Uhu2, Geier2, Fuchs2 \n";
text += "ID3, Uhu3, Geier3, Fuchs3 \n";

Dieser String wird dann in seine Einzelteile zerlegt. In PHP sehe es dann so aus:

Code:
$meinArray = Array();
$meinArray[0] = Array ( "A1" => "ID1", "A2" => "Uhu1", "A3" => "Geier1", "A4" => "Fuchs1" );
$meinArray[1] = Array ( "A1" => "ID2", "A2" => "Uhu2", "A3" => "Geier2", "A4" => "Fuchs2" );
$meinArray[2] = Array ( "A1" => "ID3", "A2" => "Uhu3", "A3" => "Geier3", "A4" => "Fuchs3" );

Array
(
    [0] => Array
        (
            [A1] => ID1
            [A2] => Uhu1
            [A3] => Geier1
            [A4] => Fuchs1
        )

    [1] => Array
        (
            [A1] => ID2
            [A2] => Uhu2
            [A3] => Geier2
            [A4] => Fuchs2
        )

    [2] => Array
        (
            [A1] => ID3
            [A2] => Uhu3
            [A3] => Geier3
            [A4] => Fuchs3
        )

)

Die Schlüssel mit A1 bis A4 wären (für mich einfacher) aber zur Not geht es auch ohne. Später soll aber nach A1 bis A4 das ganze Sortierbar sein. Nun sahen meine Überlegungen so aus:

Code:
// Example 1
HashMap<Integer, String[]> meinArray = new HashMap();
meinArray.put(0, new String[] { "ID1", "Uhu1", "Geier1", "Fuchs1" } );
meinArray.put(1, new String[] { "ID2", "Uhu2", "Geier2", "Fuchs2" } );

// zum testen
String[] A1 = meinArray.get(0);
Log.d("test", A1[1] );

Das kommt (für meine Begriffe) dem schon etwas näher. Da der Inhalt vom String dynamisch ist, kenne ich nicht den Inhalt vorher. Ich kann nicht festlegen wie groß mein Array sein wird.

Mein 2 Versuch (ich denke hier umständlicher) sah so aus:


Code:
// Example 2
HashMap<Integer, HashMap> meinArray2 = new HashMap();

HashMap<String, String> map1 = new HashMap();
map1.put("A1", "ID1");
map1.put("A2", "Uhu1");
map1.put("A3", "Geier1");
map1.put("A4", "Fuchs1");
meinArray2.put(0, map1 );

HashMap<String, String> map2 = new HashMap();
map2.put("A1", "ID1");
map2.put("A2", "Uhu1");
map2.put("A3", "Geier1");
map2.put("A4", "Fuchs1");
meinArray2.put(1, map2 );

// zum testen
HashMap A2 = meinArray2.get(0);
Log.d("test",  A2.get(2).toString() );

Allerdings halte ich Beispiel 2 zu umständlich. Das ganze muss über eine Schleife laufen. Keine Ahnung wie da wieder map1 bis map<n> dynamisch mache.
 
@R4M :
Nimm mal mein beispiel und ändere das int in der MyStruct lediglich in ein String um
..

Oder soll ich dir das hier schreiben ?
 
Zuletzt bearbeitet:
Ich versuche es mal selber.
 
Oder so:

Code:
...
ArrayList<Tiere> kaefigListe = new ArrayList<>();

kaefigListe.add(new Tiere("1","Uhu","Geier","Fuchs"));
kaefigListe.add(new Tiere("1","Uhu","Geiersturzflug","Fuchs"));

// oder

Tiere kaefig1 = new Tiere();
kaefig1.id ="1",
kaefig1.addTier("Uhu");
kaefig1.addTier("Geier");
kaefig1.addTier("Maus");

kaefigListe.add(kaefig1);

// und

String myTier = kaefigListe.get(1).getTierList.get(1);

// myTier ist gleich "Geiersturzflug"
//

// Und auf Wunsch von swa00:
String alleTiere = "";
for(Tiere zelle : kaefigListe) {
   Log.d("Zellen Id: "+ zelle.id);
   alleTiere += "id= "+zelle.id+"\n"
   for (String tier : zelle.getTierList) {
       Log.d("Tier :"+ tier);
       alleTiere += tier+"\n";
   }
   alleTiere +="\n"
}

Log.d("alle Tiere","Alle Tiere: " + alleTiere;
...


public class Tiere {

    private ArrayList<String> tierList = new ArrayList<>();
    public String id;

    public Tiere() {}
    public Tiere(String id.String tier1, String tier2, String tier3) {
        this.id = id;
        tierList.add(tier1);
        tierList.add(tier2);
        tierList.add(tier3);
    }

    public void addTier(String tier) {
        tierList.add(tier);
    }
    public ArrayList <String> getTierList() {
        return tierList;
    }

}
 
Zuletzt bearbeitet:
Ok, jetzt hast du es gemacht :)

Markus mach ihm noch ne schleife rein ( so wie ich oben )
Darauf kommt es ihm an ( und ggf den Sort - Copy & Paste auch von mir oben)
 
  • Danke
Reaktionen: markus.tullius
Mache ich doch gerne. :biggrin:
Aber die Sortierung darfst du selber schreiben. Füge sie gerne ein (mit Copyright ;) ).
 
Und nun die Sortierung auf das Markus Beispiel

public class Tiere {

private ArrayList<String> tierList = new ArrayList<>();
public String id;

public Tiere() {}
public Tiere(String id.String tier1, String tier2, String tier3) {
this.id = id;
tierList.add(tier1);
tierList.add(tier2);
tierList.add(tier3);
}

public void addTier(String tier) {
tierList.add(tier);
}
public ArrayList <String> getTierList() {
return tierList;
}
public sort ()
{
Collections.sort(tierList, new Comparator<String>()
{
@override
public int compare(String s1, String s2)
{
return s1.compareToIgnoreCase(s2);
}
}

}
});

Quelle : CopyRight with kind approval 2016 by Cicero, Italy
 
Und aufgerufen wird die Sortierung mit:
Code:
Tiere kaefig = new Tiere("1","Uhu","Geier","Fuchs"));
kaefig.sort();
String alleTiere ="";
for (String tier : zelle.getTierList) {
      Log.d("Tier :"+ tier);
      alleTiere += tier+"\n";
}

Log.d("sort",alleTiere);
// liefert: 
// Fuchs (kaefig.get(0);)
// Geier  (kaefig.get(1);)
// Uhu    (kaefig.get(2);)
 

Ähnliche Themen

S
Antworten
49
Aufrufe
4.752
jogimuc
J
D
Antworten
3
Aufrufe
1.054
dandor
D
R4M
Antworten
20
Aufrufe
1.794
R4M
R4M
Zurück
Oben Unten