# Duplikate aus eigenen Datentypen entfernen



## xplox (11. Sep 2009)

Hallo. 

Ich weiß nicht so recht ob ich lieber hier oder doch im Anfängerforum posten soll. Na ja. 
Einer der Moderatoren wird sich schon drum kümmern. 

Zu meiner Frage bzw. zu meinem Problem:

Ich bekomme von der Datenbank eine Ergebnismenge zurückgeliefert. Diese enthält 8 unterschiedliche String Parameter! Ein Teil dieser Strings benötige ich, um eine Gruppierung durchzuführen. Also erstelle ich mir mittels Konstruktor und entsprechender Klasse ein neues Objekt, dass nur diese 4 der 8 Strings beinhaltet. 
Die Objekte werden daraufhin von mir in eine LinkedList eingefügt! Da in der LinkedList keine Duplikate vorkommen dürfen habe ich es auch schon mit einem LinkedHashSet versucht. Auch das Hinzufügen der Ergebnisse zu einem Set bzw. HashSet führte mich nicht weiter. Es sind immer gleich viele Objekte in der Liste vor bzw. nachdem ich das Set darauf angewendet habe. 

Hier ist mal mein Codeausschnitt:

```
LinkedHashSet<DTO_Parameter3> list3 = new LinkedHashSet<DTO_Parameter3>();
Collection<DTO_Parameter2> tmp = col_parameter2;

System.out.println("TMP SIZE: " + tmp.size());
Iterator<DTO_Parameter2> itr2to3 = tmp.iterator();
while(itr2to3.hasNext())
{
   DTO_Parameter2 dto = (DTO_Parameter2) itr2to3.next();
   DTO_Parameter3 d3 = new DTO_Parameter3(dto.getPlausibtext(), dto.getLabor(), 
           dto.getGruppenposition(), dto.getMe_typ());
   if(!list3.contains(d3)) list3.add(d3);			
}

System.out.println("LList SIZE: " + list3.size());
		
Set<DTO_Parameter3> hs = new HashSet<DTO_Parameter3>(list3);
list3.clear();
list3.addAll(hs);
		
System.out.println("HASHSET SIZE: " + hs.size());
Collection<DTO_Parameter3> col_parameter3 = list3;
System.out.println("LList SIZE: " + list3.size());
```

col_parameter2 sind die Daten die aus der Datenbank kommen (8 Strings).
col_parameter3 sind die Daten ohne Duplikate die ich für die weitere Verarbeitung brauche (4 Strings).

Hoffe das war jetzt halbwegs verständlich! Kann mir jemand helfen???


----------



## bygones (11. Sep 2009)

xplox hat gesagt.:


> Da in der LinkedList keine Duplikate vorkommen dürfen habe ich es auch schon mit einem LinkedHashSet versucht. Auch das Hinzufügen der Ergebnisse zu einem Set bzw. HashSet führte mich nicht weiter.


unsinn - in einer Liste (also LinkedList) koennen Duplikate vorkommen.

In einem Set jedoch nicht. Damit das bei Objekten gewaehrleistet wird muss equals und hashcode ueberschrieben werden !


----------



## ARadauer (11. Sep 2009)

Arbeitest du mit Eclipse, lass dir für deine Datenklasse mal equal sund hasCode generieren -> Source -> Generate hashCode...

Und bitte versuch dich an Code Konventionen zu halten. DTO_Parameter2 sieht komisch aus und sagt eigentlich nichts über den Zweck der Klasse aus...


----------



## ARadauer (11. Sep 2009)

Beispiel:


```
import java.util.ArrayList;
import java.util.HashSet;
import Adress;


public class Test {

   public static void main(String[] args) {
     ArrayList<Adress> list = new ArrayList<Adress>();
     list.add(new Adress("AAA", "BBB"));
     list.add(new Adress("CCC", "DDD"));
     list.add(new Adress("AAA", "BBB"));
     
     HashSet<Adress> set = new HashSet<Adress>(list);
     
     System.out.println( set.size());
   }


}
```


```
public class Adress {
   private String firstName;
   private String lastName;
   
   
   
   public Adress(String firstName, String lastName) {
      super();
      this.firstName = firstName;
      this.lastName = lastName;
   }
   
   public String getFirstName() {
      return firstName;
   }
   public void setFirstName(String firstName) {
      this.firstName = firstName;
   }
   public String getLastName() {
      return lastName;
   }
   public void setLastName(String lastName) {
      this.lastName = lastName;
   }
  
   @Override
   public String toString() {
      return "Adress [firstName=" + firstName + ", lastName=" + lastName + "]";
   }
```
liefert natürlich 3. Java vergleicht hier nicht die inhalte der Felder. Java weiß ja nicht wann ein Objekt gleich ist..



```
@Override
   public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result
            + ((firstName == null) ? 0 : firstName.hashCode());
      result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
      return result;
   }

   @Override
   public boolean equals(Object obj) {
      if (this == obj)
         return true;
      if (obj == null)
         return false;
      if (getClass() != obj.getClass())
         return false;
      Adress other = (Adress) obj;
      if (firstName == null) {
         if (other.firstName != null)
            return false;
      } else if (!firstName.equals(other.firstName))
         return false;
      if (lastName == null) {
         if (other.lastName != null)
            return false;
      } else if (!lastName.equals(other.lastName))
         return false;
      return true;
   }
```
fügst du das in die Klasse Adress ein kommt 2 raus... 
Der Code wurde von Eclipse generiert...


----------



## bygones (11. Sep 2009)

so gern ich eclipse mag... die generierten equals methoden sind einfach nur ein graus....


----------



## xplox (11. Sep 2009)

ARadauer hat gesagt.:


> Arbeitest du mit Eclipse, lass dir für deine Datenklasse mal equal sund hasCode generieren -> Source -> Generate hashCode...
> 
> Und bitte versuch dich an Code Konventionen zu halten. DTO_Parameter2 sieht komisch aus und sagt eigentlich nichts über den Zweck der Klasse aus...



DTO_Parameter2 sagt sehr wohl etwas über den Zweck der Klasse aus. Es handelt sich hierbei um ein DatenTransferObjekt (DTO) der Tabelle Parameter2!

Ansonsten Danke für den Tipp. Da hätt ich eigentlich auch selbst drauf kommen können, dass die Klasse equals und hashCode selbst implementieren muss.


----------



## maki (11. Sep 2009)

> DTO_Parameter2 sagt sehr wohl etwas über den Zweck der Klasse aus. Es handelt sich hierbei um ein DatenTransferObjekt (DTO) der Tabelle Parameter2!


Naja, muss da ARadauer zustimmen, nicht nur dass der Name nicht der Konvention entspricht (kein richtiges Camelcase, unterstriche..), der Name an sich sagt nicht viel aus.
DTOs nutzt man eigentlich immer in Verbindung mit Objekten, wenn jetzt der Name der Klasse zu welchem dieses DTO gehört mit drinn wäre, könnte man sich mehr vorstellen.

list3, hs, itr2to3, getMe_typ() etc. pp. sind keine sprechenden Namen...


----------



## ARadauer (11. Sep 2009)

bygones hat gesagt.:


> so gern ich eclipse mag... die generierten equals methoden sind einfach nur ein graus....



da hast schon recht... hab da mal irgendwo eine super Alternative gesehen. Eine Generator Klasse mit verkettbaren Methodenaufrufen... Ich find das aber nicht mehr, weiß jemand was ich meine? Dachte mir das es eine lib aus den apache commons wäre... finde es aber nicht mehr ;-)


----------



## xplox (11. Sep 2009)

Das mit der Klasse geb ich ja zu ... die hätte ich noch dazu schreiben können. Es handelt sich hierbei um eine Kontrollklasse. Aber ihr seid ja hier so gut, dass ihr es auch so verstanden habt!

Habe meinen ursprünglichen Code jetzt übrigens so geändert!


```
package ...
import ...

public class Kontrolle
{
   ...
   LinkedHashSet<Parameter> list = new LinkedHashSet<Parameter>();
   Collection<Parameter2> tmp = WerteAusDerDatenbank;
   Iterator<Parameter2> itr = tmp.iterator();
		
   while(itr.hasNext()) {
	Parameter2 param = (Parameter2) itr.next();
	list.add(new Parameter(param.getPlausibtext(), param.getLabor(), 
        param.getGruppenposition(), param.getMethodenTyp());
   }

   System.out.println(list.size());
   ...
}//class
```


```
package ...
import ...

public class Parameter
{
   private String plausibtext;
   private String labor;
   private String gruppenposition;
   private String methodenTyp;

   public Parameter(ResultSet rset)
   {
	try {
	   this.setPlausibtext(rset.getString("plausibtext"));
	   this.setLabor(rset.getString("labor"));
	   this.setGruppenposition(rset.getString("gruppenposition"));
	   this.setMethodenTyp(rset.getString("me_typ"));			
	} catch (SQLException e) {
	   e.printStackTrace();
	}
   }
	
   public Parameter(String plausibtext, String labor, String gruppenpostion, String methodenTyp)
   {
	this.setPlausibtext(plausibtext);
	this.setLabor(labor);
	this.setGruppenposition(gruppenposition);
	this.setMethodenTyp(methodenTyp);
   }

   public void setPlausibtext(String plausibtext) {
	this.plausibtext = plausibtext;
   }
   public String getPlausibtext() {
	return plausibtext;
   }
   public void setLabor(String labor) {
	this.labor = labor;
   }
   public String getLabor() {
	return labor;
   }
   public void setGruppenposition(String gruppenposition) {
	this.gruppenposition = gruppenposition;
   }
   public String getGruppenposition() {
	return gruppenposition;
   }
   public void setMethodenTyp(String typ) {
	this.methodenTyp = typ;
   }
   public String getMethodenTyp() {
	return methodenTyp;
   }

   @Override
   public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result
		+ ((gruppenposition == null) ? 0 : gruppenposition.hashCode());
	result = prime * result + ((labor == null) ? 0 : labor.hashCode());
	result = prime * result + ((methodenTyp == null) ? 0 : methodenTyp.hashCode());
	result = prime * result
		+ ((plausibtext == null) ? 0 : plausibtext.hashCode());
	return result;
   }

   @Override
   public boolean equals(Object obj) {
	if (this == obj)
	   return true;
	if (obj == null)
	   return false;
	if (getClass() != obj.getClass())
	   return false;
	Parameter other = (Parameter) obj;
  	   if (gruppenposition == null) {
		if (other.gruppenposition != null)
			return false;
	   } else if (!gruppenposition.equals(other.gruppenposition))
		return false;
	   if (labor == null) {
		if (other.labor != null)
			return false;
	   } else if (!labor.equals(other.labor))
		return false;
	   if (methodenTyp == null) {
		if (other.methodenTyp != null)
			return false;
	   } else if (!methodenTyp.equals(other.methodenTyp))
		return false;
	    if (plausibtext == null) {
		if (other.plausibtext != null)
			return false;
	   } else if (!plausibtext.equals(other.plausibtext))
		return false;
	return true;
   }
}//class
```

Vielen Dank!


----------



## bygones (11. Sep 2009)

ARadauer hat gesagt.:


> da hast schon recht... hab da mal irgendwo eine super Alternative gesehen. Eine Generator Klasse mit verkettbaren Methodenaufrufen... Ich find das aber nicht mehr, weiß jemand was ich meine? Dachte mir das es eine lib aus den apache commons wäre... finde es aber nicht mehr ;-)



EqualsBuilder (Commons Lang 2.4 API)


----------



## Ariol (11. Sep 2009)

```
package doubleButton;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class EqualChecker
{
	public static boolean check(Object o1, Object o2)
	{
		if(o1==null || o2==null)
		{
			if(o1==null && o2==null)
				return true;
			else
				return false;
		}
		
		if(o1.equals(o2) || o1 == o2)
			return true;
		
		if(o1.getClass() != o2.getClass())
			return false;
		
		if(!checkFields(o1, o2))
			return false;
		
		if(!checkMethods(o1, o2))
			return false;
				
		
		return true;
	}
	
	

	private static boolean checkFields(Object o1, Object o2)
	{ 
		Field[] fields = o1.getClass().getFields();
		for(Field field : fields)
		{
			try
			{
				field.setAccessible(true);
				Object val1 = field.get(o2);
				Object val2 = field.get(o2);
				
				if(!val1.equals(val2) && val1 != val2)
					return false;
			}
			catch (Exception e)
			{
				return false;
			}
		}
		return true;
	}
	
	private static boolean checkMethods(Object o1, Object o2)
	{
		Method[] methods = o1.getClass().getMethods();
		for(Method method : methods)
		{
			try
			{
				method.setAccessible(true);
				if(!method.getName().startsWith("get"))
					continue;
				
				if(method.getParameterTypes().length > 0)
					continue;
				
				Object val1 = method.invoke(o1);
				Object val2 = method.invoke(o2);
				
				if(!val1.equals(val2) && val1 != val2)
					return false;
			}
			catch (Exception e)
			{
				return false;
			}
		}
		return true;
	}
}
```

Aber ob sowas sinnvoll ist ^^


----------



## Landei (12. Sep 2009)

Mal abgesehen davon, dass das ganze ziemlich aufgeblasen und überflüssig aussieht:

Haben die nicht mal die Grundlagen der Logik drauf?


```
//statt
if(o1==null && o2==null)
   return true;
else
   return false;

//kürzer
return o1==null && o2==null;


//statt
if(o1.getClass() != o2.getClass())
   return false;
if(!checkFields(o1, o2))
   return false;
if(!checkMethods(o1, o2))
    return false;
return true;

//kürzer
return o1.getClass() == o2.getClass() && checkFields(o1, o2) && checkMethods(o1, o2);
```

und so weiter...


----------



## Ariol (12. Sep 2009)

Landei hat gesagt.:


> Mal abgesehen davon, dass das ganze ziemlich aufgeblasen und überflüssig aussieht:
> 
> Haben die nicht mal die Grundlagen der Logik drauf?



"Die" war ich und hab das ganze in 10 Minuten mal schnell zusammengebastelt und dabei mehr auf Lesbarkeit als Einfachheit geachtet.

War nur so als Idee.


----------



## Landei (12. Sep 2009)

Sorry, dann ist das natürlich was anderes. Ich dachte, das wäre von Apache oder so...


----------



## Ariol (12. Sep 2009)

Landei hat gesagt.:


> Sorry, dann ist das natürlich was anderes. Ich dachte, das wäre von Apache oder so...



Kein Sorge, bin ja nicht aus Zucker und nehm auch nicht alles persönlich


----------

