Java HashLists vergleichen

cl0udt

Lt. Junior Grade
Registriert
Sep. 2008
Beiträge
508
Hi Leute,

habe zwei zweidimensionale Hashlists und würd die gerne inhaltlich miteinander vergleichen:

Beide HashLists sind vom Typ HashList<int[]>. Der enthaltene int-Array hat immer die länge 2 und enthält eine x- und eine y-koordinate. Jetzt will ich herausfinden, ob der eine int-array (bzw. eine Koordinate) in dem anderen schon enthalten ist...aber wie macht man das?
Leider haben hashlists ja keinen index. Es müssen auch zwingend Hashlists sein.
Ich könnte allerhöchstens in ArrayList umcasten, aber das krieg ich auch nicht so wirklich hin. Habt ihr da vll ne idee?

Edit: also wenn ich die beide sauber in ne ArrayList<int[]> bekommen würde, wäre das schon top...
 
Laut API-Doc kann man in einer Hashlist per Index zugreifen. Machste ne For-Schleife und da ist dein Index (mit Haslist.size() Durchläufen). Alternativ nimmste halt nen Iterator. Viel Erfolg :)
 
ja aber es gibt keine methode get(index). Sry, programmiere noch net so lange java und weiß nicht, wie ich ohne get(index) auf die einzelnen int[] in der Hashlist zugreifen soll =/.
 
ich weiß nicht mal was ne hashmap ist. Nee, ist ganz sicher hashlist ;)
 
Tja - und ich weiß nicht was eine HashList ist. ;)
Die gibt es auch nicht standardmäßig in Java. Hab zwar einige Implementierungen dazu durch Google gefunden, aber nicht wirklich was aussagendes. Kannst du mal den kompletten Klassennamen (z.B. anvil.java.util.Hashlist) nennen?
 
Also laut dem offizellen JavaDoc gibts keine Hashlist??

du könntest das hier jedch mal probieren, bringt natürlich nichts wenn deine "hashlist" nicht von Colletion erbt..

Code:
for(int[] i : hashlist1){
      if(hashlist2.contains(i)) hashlist1.remove(i);
}
 
Sry, dadurch dass ich als mit ArrayList und HashSet rumexperimentiert habe, hab ichs verwechselt...so viel zu meine "ganz sicher". HashSet ist es...und falls das von HashMap erbt, dann wird es auch ne HashMap sein, aber kein plan :D
 
oder du arbeitest mit iteratoren:
Code:
Itereator iter = meinSet.iterator();

for(iter.hasNext()) {
int a[] = iter.nextx();

if (a[0]==gesuchterWert[0] && a[1]==gesuchterWert[1]) {
throw new Exception("Schon vorhanden");
break;
}
}

schöner ist natürlich, dir ein eigenes Exception zu schreiben, aber für den Anfang sollte es auch so gehen...

edit://verdammt, übersehen, dass es um int-Arrays geht - angepasst
 
Zuletzt bearbeitet:
Code:
schleife:
for(int[] i : hs1) {
	for(int[] j : hs2) {	
		if(i[0]==j[0]&&i[1]==j[1]) {
			System.out.println("i aus hs1 und j aus hs2 sind gleich!");
			break schleife;
		}
	}
}

Wenn du willst kannst du dir natürlich auch die Koordinaten noch mit ausgeben lassen. Das solltest du aber selber hinbekommen ;)
 
Code:
public boolean hashSetVergleich(){
		int z = 0;
		for(int[] i : h1) {
			for(int[] j : h2) {	
				if((i[0]==j[0])&&(i[1]==j[1])) {
//					System.out.println("gleich!");
					z++; 	
					
				}
//				else System.out.println("net gleich");
			}
		}
		
		if (z == h1.size()){
			return true;
		} else return false;
		
	}

Hab das jetzt hierzu umgebaut.
Leider werden wohl auch in nen hashset gleiche koordinaten mehrmals gespeichert. Er zählt halt die vairable z auch hoch, wenn koordinaten doppelt drin sind...so kanns natürlich nix werden.
Wichtig ist halt, das alle Zellen von h1 in h2 sind...

Danke schonmal soweit.
 
cl0udt schrieb:
Leider werden wohl auch in nen hashset gleiche koordinaten mehrmals gespeichert. Er zählt halt die vairable z auch hoch, wenn koordinaten doppelt drin sind...so kanns natürlich nix werden.
Wichtig ist halt, das alle Zellen von h1 in h2 sind...

1. HashSets speichern nie etwas doppelt - in deinem Fall sieht es nur so aus. Der Grund: Als Basis für Gleichheit werden die Methoden equals() und hashCode() herangezogen. Das von Dir verwendete Array hat die Defaultimplementierung dieser Methoden von Object geerbt. Diese sind nicht geeignet, somit werden inhaltlich gleiche Arrays auch nicht zwingend als gleich erkannt -> Merke: Verwendet man HashSets oder HashMaps sollte man für die Klassen der darin gespeicherten Objekte IMMER equals() und hashCode() implementieren

2. Du solltest kein int[] verwenden, um einzelne Koordinaten zu Speichern. Schreib Dir lieber eine eigene Klasse Koordinaten und bei dieser implementierst du dann die beiden oben genannten Methoden. Hier hast du mal ein Skelett:
Code:
  class Koordinate
  {
    private int x;
    private int y;

    Koordinate(int x, int y)
    {
      this.x = x;
      this.y = y;
    }

    public int getX()
    {
      return x;
    }

    public int getY()
    {
      return y;
    }

    public boolean equals(Object o)
    {
       // hier musst du was coden
    }

    public int hashCode()
    {
       // hier musst du was coden
    }
  }


3. Wenn du eine eigene Klasse für Koordinaten mit equals() und hashCode hast, ist dein eigentliches Problem total einfach zu lösen mit folgendem Beispiel. Es zeigt dann auch, dass h2 nicht 3 sondern 2 Elemente enthalten wird (2 der hinzugefügten Koordinaten sind ja gleich (equal()):

Code:
    HashSet<Koordinate> h1 = new HashSet<Koordinate>();
    h1.add(new Koordinate(1,2));
    h1.add(new Koordinate(3,2));

    HashSet<Koordinate> h2 = new HashSet<Koordinate>();
    h2.add(new Koordinate(1,2));
    h2.add(new Koordinate(3,2));
    h2.add(new Koordinate(3,2));

    System.out.println("Anzahl Elemente h2: " + h2.size());

    System.out.println("h2 enthält h1: " + h2.containsAll(h1));
 
Ok, das verstehe ich jetzt.
Dein Code wäre wohl die beste Möglichkeit, das ganze zu implementieren.

Der Haken an der Sache ist leider, dass ich ein vorgegebenes Interface habe und der getter für die h2 zwingend die rückgabe Set<int[]> hat. Das einzige, was ich verändern kann, ist die Art des Sets...leider.

Vielen Dank für die Mühe!
 
cl0udt schrieb:
Der Haken an der Sache ist leider, dass ich ein vorgegebenes Interface habe und der getter für die h2 zwingend die rückgabe Set<int[]> hat. Das einzige, was ich verändern kann, ist die Art des Sets...leider.

Hmm, dann ist derjenige, der das Interface definiert hat etwas schizophren oder verwirrt.

Denn bei einem Set<int[]> wird es nur mit Umstand und Mühe möglich keine doppelten Einträge zu haben.

Da hätte derjenige dann auch gleich List<int[]> nehmen können, das wäre ebenso sinnfrei allerdings angenehmer in der Handhabung, weil man per Index auf die einzelnen Elemente zugreifen kann.

Die größte Schizophrenie ist aber, dass er Dich/Euch zwingt Collections (also auch Sets, Listen) so zu verwenden, wie sie gar nicht für vorgesehen sind. So als würde man einen LKW Mieten, um den Wochenendeinkauf zu machen.

Im Prinzip hätte er als Datentype dann auch int[][] nehmen können, das wäre nur konsequent gewesen.



Im Notfall kannst du es natürlich trotzdem so machen wie vorgeschlagen. Du müsstest Deine Getter dann eben so umsschreiben, dass die aus einem Set<Koordinate> ein Set<int[]> machen. Dafür machst du dir am besten eine Methode toIntSet() oder so. Dann bist du fein raus.
 
Joa, also ich will mich net so weit aus dem fenster lehnen, weil ich möglicherweise etwas übersehen habe und es am ende deswegen doch sinnvoll ist, aber momentan würd ich auch sagen, dass mit Sets arbeiten hier unangebracht ist.
Ich glaube ich hab es jetzt sogar hinbekommen. werde es gleich mal testen.

Habe zusätlich in die innerste vorschleife eine variable auf true gesetzt. Immer wenn der zähler einmal hochgesetzt wurde, also die koordinate aus h1 in h2 gefunden wurde, dann wird die variable "darfSchreiben" auf false gesetzt...ungefähr so:

Code:
	public boolean hashSetVergleich(){
		int z = 0;
		boolean darfSchreiben = true;
		for(int[] i : h1) {
			for(int[] j : h2) {	
				Integer freeX = i[0];
				Integer freeY = i[1];
				Integer travX = j[0];
				Integer travY = j[1];
				if((freeX.equals(travX))&&(freeY.equals(travY))) {
					if (darfSchreiben == true){
						z++; 	
						darfSchreiben = false;
					}
				}
			}
			darfSchreiben = true;
		}
		if (z == h1.size()){                                 
			return true;
		} 
		else {
			return false;
		}
	}

ob das equals jetzt an der stelle oben sinn macht, weiß ich net. Glaube da würde auch ein vergleich mit == reichen, oder wie hattest du das vorhin gemeint? naja so klappts jetzt zumindest, aber ich find es unleserlich und schlecht nachvollziehbar. mit dem korrekten datentyp wäre es halt ein klacks gewesen :(
 
Zuletzt bearbeitet:
grob drübergeschaut müsste es gehen. ich verstehe nicht, warum du am ende auf h1 clear() aufrufst. Damit löscht du alle Daten, willst du das wirklich?
 
Jein. Ich habs rausgenommen.

Ich brauch zu Beginn erstmal Koordinaten in h1. Die bekomme ich durch geth1.
Allerdings ist es sinnvoller, den getter von der Klasse, bzw. der von der Instanz der Klasse aufzurufen. Habs jetzt im test so gemacht und klappt wunderbar.

Aber das equals muss sein? Oder wäre ein "==" - Vergleich an der Stelle doch ok? Hab das glaube noch net so ganz gecheckt.
 
Zurück
Oben