HashMap key wird nicht erkannt trotz überschriebener equals/hashCode Methode

Ikaron

Bekanntes Mitglied
Naja, der Titel beschreibt mein Problem ja schon 🙂
Ich habe folgende Klasse zum Splitten eines Images:

Java:
package lib.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;

import javax.imageio.ImageIO;

public class GridImage {

	private BufferedImage mainImage;
	private int gridWidth, gridHeight, gridMaxX, gridMaxY;

	private HashMap<Point2D, BufferedImage> imgs = new HashMap<Point2D, BufferedImage>();
	private HashMap<String, Point2D> aliases = new HashMap<String, Point2D>();

	public GridImage(String s, int gridWidth, int gridHeight) {

		try {
			mainImage = ImageIO.read(new File(s));
		} catch (IOException e) {

			e.printStackTrace();
		}

		this.gridWidth = gridWidth;
		this.gridHeight = gridHeight;
		this.gridMaxX = mainImage.getWidth() / gridWidth;
		this.gridMaxY = mainImage.getHeight() / gridHeight;
	}
	
	public void addSplit(Point2D c1, Point2D c2) {

		addSplit(c1.x(), c1.y(), (short) (c2.x() - c1.x()), (short) (c2.y() - c1.y()));
	}
	
	public void addSplit(short x, short y, short w, short h) {

		if (x >= 0 && y >= 0 && (x + w < gridMaxX) && (y + h < gridMaxY))
			imgs.put(
					new Point2D(x, y),
					ImageHelper.cropImage(mainImage, x * gridWidth, y
							* gridHeight, w * gridWidth, h * gridHeight));
	}

	public void addAlias(Point2D c, String s) {

		aliases.put(s, c);
	}

	public ArrayList<Point2D> getCoords() {
		
		ArrayList<Point2D> aliases = new ArrayList<Point2D>();

		Iterator<Entry<Point2D, BufferedImage>> it = this.imgs.entrySet().iterator();
		
		while (it.hasNext()) {
			
			aliases.add(it.next().getKey());
		}
	    
		return aliases;
	}

	public ArrayList<String> getAliases() {
		
		ArrayList<String> aliases = new ArrayList<String>();

		Iterator<Entry<String, Point2D>> it = this.aliases.entrySet().iterator();
		
		while (it.hasNext()) {
			
			aliases.add(it.next().getKey());
		}
	    
		return aliases;
	}

	public BufferedImage getImage(String s) {

		return imgs.get(aliases.get(s));
	}

	public BufferedImage getImage(Point2D c) {

		return imgs.get(c);
	}
}

Wie man sehen kann benutze is Point2D, aber nicht diese java.geom (Oder wo auch immer die ist) sondern meine eigene. Ich hab equals and hashCode überschrieben, trotzdem:
new Point2D(0, 0) == new Point2D(0, 0) ist false, obwohl new Point2D(0, 0).equals(new Point2D(0, 0)) true ist.
Hier ist Point2D:

Java:
package lib.util;

public class Point2D {

	private short x, y;

	public Point2D(int x2, int y2) {

		x = (short) x2;
		y = (short) y2;
	}

	public short x() {

		return x;
	}

	public short y() {

		return y;
	}

	public boolean equals(Object o) {

		if (this == o)
			return true;

		if (!(o.getClass().equals(Point2D.class)))
			return false;

		Point2D c = (Point2D) o;

		return c.x == x && c.y == y;
	}
	
	public int hashCode() {
		
		return x + (y << 32);
	}

	public String toString() {

		return "lib.util.Point2D[" + x + "; " + y + "]";
	}
}

Danke für jede Hilfe.
Ikaron

@Edit: Ich dachte ich wär in nem englischen Forum xD
 
Zuletzt bearbeitet:
Java:
new Point2D(0, 0) == new Point2D(0, 0)
Die Anweisung kann nie und niemals true werden.
Code:
==
vergleicht ob die Instanzen identisch sind, equals prüft ob die Instanzen die gleichen sind (das bestimmst du selber durch deine equals Methode).

Wenn du also deine Objekte vergleichen willst, dann musst immer equals nutzen.
 
Richtig, das Problem ist jetzt, dass HashMap intern anscheinend auch == verwendet, was mir dann in die Quere kommt. Wenn dies so ist, wie kann ich eine HashMap mit Koordinaten machen, ohne sowas wie HashMap<Integer, HashMap<Integer, E>> zu verwenden?
 
HashMap verwendet intern erstmal die Methode hashCode um den richtigen "Topf" für den Eintrag zu finden. Liegen in dem Topf schon Key-Value Paare drin wird per equals verglichen ob die Einträge gleich sind, nicht per
Code:
==
.
Selbiges gilt für das rausholen der Einträge. Auch da wird zunächst equals und danach equals verwendet.

Wo genau ist da jetzt dein Problem?
 
Nun ja, wenn ich etwas einspeichere, zum Beispiel in dem Fall ein BufferedImage, gibt er mir bei Größe 1 zurück (Klar), Wenn ich aber mit new Point2D(0, 0) drauf zugreifen möchte, wird null zurückgegeben, obwohl das Image auch mit new Point2D(0, 0) gespeichert wurde.
 
Dann passt da was mit deiner Point2D Klasse nicht. Wobei das equals ganz gut ausschaut. Aber die HashMap nutzt definitiv die equals Methode:

Java:
	public static void main(String[] args) throws Exception {
		HashMap<Key, String> map = new HashMap<Key, String>();
		map.put(new Key(1), "foo");
		map.put(new Key(2), "bar");
		
		System.out.println(map.get(new Key(1)));
	}
	
	private static class Key {
		private final int i;

		public Key(int i) {
			this.i = i;
		}
		
		@Override
		public boolean equals(Object obj) {
			return i == ((Key)obj).i;
		}

		@Override
		public int hashCode() {
			return 42;
		}
	}
 
Hmm... Anscheinend liegt das Problem da, dass meine render()-Methode nicht aufgerufen wird... Ich guck mir das nochmal an...

@Edit: Och neee... Mist, ich bin echt dumm :lol:
Das lag daran, dass ich in meiner bib etwas namens "setInit()" eingebaut hab.. Das hab ich dann aber vergessen, und das ist jetzt das 3te mal, dass es deshalb nicht get 😳
 
Zuletzt bearbeitet:

Zurück
Oben