Datentypen Probleme mit Vector.contains()

Curry

Aktives Mitglied
Moin Moin!

Ich habe eine Methode geschrieben, die ein Paar Integer-Werte als Array verpackt in ein Vector schreibt. Es sollen aber nur die Integer-Werte in den Vector geschrieben werden, wenn diese dort nicht schon vorhanden sind. Diese Prüfung funktioniert bei mir leider nicht und ich verstehe nicht weshalb.

Warum ist das so und was muss ich anderes machen?

Java:
public void addBook(int library_id, int book_id) {
		Integer[] array = new Integer[2];
		array[0] = library_id;
		array[1] = book_id;
		
		System.out.println("array.length = " + array.length);
		System.out.println("array.toString() = " + array.toString());
		System.out.println("_e.size() (nr. 1)" + _e.size());
		
		if(!_e.contains(array)) {
			_e.add(array);
			setChanged();
			notifyObservers();
		}
		
		System.out.println("_e.size() (nr. 2)" + _e.size());
	}
 
So funktioniert das nicht. Du schaust nach, ob ein neu angelegtes Array schon im Vector ist. Das kann aber nicht sein, da alle Arrays verschiedene Objekte sind.

Ein paar Tipps:
1. Verwende keine Integer-Arrays sondern mach dir eine eigene Klasse (IntPair oder so). Da kannst du dann equals() und hashcode() entsprechend implementieren.
2. Verwende keinen Vector sondern das Interface List und z.B. ArrayList als Implementierung.
3. Für dieses Problem sind Listen uneffektiv, da sie ständig durchsucht werden müssen. Mach dich mit Sets und Maps vertraut, vielleicht passt das besser.
4. Verwende keine Unterstriche in Variablennamen. Das ist gegen die Code-Konventionen.
 
hier ein Beispiel @Aldi:
Java:
import java.util.*;

public class StringArrayWrapper {
	private String[] array = {"abc", "123"};
	
	public static void main(String[] args) {
		List<String[]> list = new ArrayList<String[]>();
		list.add(new String[] {"abc", "123"});
		System.out.println(list.contains(new String[] {"abc", "123"}));
		
		List<StringArrayWrapper> list2 = new ArrayList<StringArrayWrapper>();
		list2.add(new StringArrayWrapper());
		System.out.println(list2.contains(new StringArrayWrapper()));
	}
	
	@Override
	public boolean equals(Object o) {
		StringArrayWrapper saw = (StringArrayWrapper)o;
		for (int i = 0; i < this.array.length; i++) {
			if (saw.array.length != this.array.length || !saw.array[i].equals(this.array[i]))
				return false;
		}
		return true;
	}
}

Ausgabe:

false
true
 
@tfa:

Danke für deine tollen Tipps! Ich habe jetzt eine Klasse "IntPair()" geschrieben (siehe unten) und deren Objekte speichere ich in einer HashSet. Weshalb eigentlich kein Vector? Wegen der Eigenschaft des Hashsets die Objekte einmalig zu speichern?

Java:
public class IntPair {
	
	private int a;
	private int b;
	
	public IntPair(int a, int b) {
		this.a = a;
		this.b = b;
	}
	
	@Override public int hashCode() {
		return this.a * 100 + this.b;
	}
	
	@Override public boolean equals( Object that ) {
		
		if( that == null ) {
			return false; 
		}
		
		if ( getClass() != that.getClass() ) {
			return false; 
		}
		
		if ( this.a != ((IntPair)that).a || this.b != ((IntPair)that).b ) {
			return false;
		}
		
		return true;
	}
	
	public int getA() {
		return this.a;
	}
	
	public int getB() {
		return this.b;
	}

Hast du noch Verbesserungsvorschläge für diese Klasse? Mich stören ja ein wenig die Namen der Eigenschaften "a" und "b". ;-)

Bezüglich der Code-Konventionen ist es dann sinnvoller die Namen der Eigenschaften durch "this." kenntlich zu machen?
 
Das sieht doch schon sehr gut aus.

Weshalb eigentlich kein Vector? Wegen der Eigenschaft des Hashsets die Objekte einmalig zu speichern?
Ja, für mich sahen deine Anforderung so aus, als ob du jedes Paar nur einmal haben willst. Ich kenn allerdings das konkrete Problem nicht.
Einen Vector musst du jedes Mal von vorne bis hinten durchsuchen. Der Zugriff in ein HashSet passiert sofort.

Hast du noch Verbesserungsvorschläge für diese Klasse?
Nichts wichtiges. Du könntest die Member-Variablen final deklarieren - die Klasse ist ja offensichtlich immutable. Das final würde dafür sorgen, dass auch so bleibt und nicht aus Versehen durch irgendwelche Quelltextänderungen verloren geht. Außerdem gibt es einen Performance-Vorteil - zumindest theoretisch.

Die Berechnung des Hashcode kann man eventuell noch optimieren. Normalerweise nimmt man als Faktor eine Primzahl (statt 100). Das hilft dabei, Kollisionen zu vermeiden. Aus welchem Wertebereich sind denn die Integer?

Mich stören ja ein wenig die Namen der Eigenschaften "a" und "b".
Keine Ahnung, welche Bedeutung diese Werte haben. Da kann ich dir nicht helfen. Zur Not nenn sie eben "first" und "second" oder so.

Bezüglich der Code-Konventionen ist es dann sinnvoller die Namen der Eigenschaften durch "this." kenntlich zu machen?
Kann man machen. Meine IDE ist z.B. so eingestellt, dass das automatisch beim Abspeichern geschieht.
 
Ja, für mich sahen deine Anforderung so aus, als ob du jedes Paar nur einmal haben willst. Ich kenn allerdings das konkrete Problem nicht.
Einen Vector musst du jedes Mal von vorne bis hinten durchsuchen. Der Zugriff in ein HashSet passiert sofort.
Das hattest du richtig erkannt. Von daher bin ich mit dem HashSet auch sehr zufrieden!

Nichts wichtiges. Du könntest die Member-Variablen final deklarieren - die Klasse ist ja offensichtlich immutable. Das final würde dafür sorgen, dass auch so bleibt und nicht aus Versehen durch irgendwelche Quelltextänderungen verloren geht. Außerdem gibt es einen Performance-Vorteil - zumindest theoretisch.
Ja, die Klasse ist wirklich als immutable gedacht und ich habe die Eigenschaften soeben final deklariert.

Die Berechnung des Hashcode kann man eventuell noch optimieren. Normalerweise nimmt man als Faktor eine Primzahl (statt 100). Das hilft dabei, Kollisionen zu vermeiden. Aus welchem Wertebereich sind denn die Integer?
Diese ursprünglich gepostete Methode ist ein Teil eines ViewModels, in dem ich unter anderem speicher welche Tabs in einem JTabbedPane geöffnet sind. Eigentlich sollten dort nicht mehr 10 Tabs offen sein.

Keine Ahnung, welche Bedeutung diese Werte haben. Da kann ich dir nicht helfen. Zur Not nenn sie eben "first" und "second" oder so.
Das mit dem Namen ist nicht sooo wichtig. ;-)

Kann man machen. Meine IDE ist z.B. so eingestellt, dass das automatisch beim Abspeichern geschieht.
Welche IDE verwendest du? Diese Funktion finde ich sehr reizvoll. Ich verwende aktuell Eclipse.
 

Zurück
Oben