# ArrayList nach mehreren Spalten sortieren?



## schuetzejanett (1. Jun 2007)

Hallo,

gibt es eine Möglichkeit in einer Arraylist nur bestimmte Zeilen zu sortieren. Also nur die Zeilen 3-5 oder so. Oder gibt es vielleicht die Möglichkeit mehrere Spalten zum Sortieren anzugeben. Also erst nachname dann Vorname dann Wohnort usw.

Bin bis jetzt soweit das ich mir eine Klasse geschrieben habee die abhängig von der gewünschten Spalte die gesamt Liste sortiert. möchte aber eben nach mehreren Spalten sortieren. Deswegen meine Idee erst die gesamte tabelle nach einer Spalte dann alle gleichen nach der 2. Spalte usw. Weiß aber nicht wie ich das realisieren soll Hatte schon überlegt die gleichen jeweils in eine ArrayList und das dann weitersortieren und dann wieder die gleichen in eine ArrayList  und weitersortieren usw. Allerdings bräucte die dafür 6 arraylisten und denke das das Speicherverschwendung ist.

Habt ihr eine idee wie ich das ganze realiesieren kann?

Hier meine bisheriege sortierKlasse


```
class ArraySort implements Comparator<PjOv>{
		
		public final static int LASTNAME	= 0;		
		public final static int FIRSTNAME	= 1;
		public final static int CONTPARTNER = 2;		
		public final static int INLAND 		= 3;
		public final static int ATTACH 		= 4;
	
		private int sortField;	

                                public ArraySort(int sortField) {
			this.sortField = sortField;
		}

		public int compare(PjOv pjOv1, PjOv pjOv2 )
		{
			int result = 0;
			switch (sortField) {
			case 0:
				result = pjOv1.getLastname().getName().compareTo(pjOv2.getLastname().getName());
				break;
			case 1:
				result = pjOv1.getFirstName().getName().compareTo(pjOv2.getFirstName().getName());
				break;
			case 2:
				result = pjOv1.getContractPartner().getName().compareTo(pjOv2.getContractPartner().getName());
				break;
			case 3:
				result = pjOv1.isAttach() && (!pjOv2.isAttach()) ? 1 : -1;		
				break;
			case 4: 
				result = pjOv1.isInland() && (!pjOv2.isInland()) ? 1 : -1;		
				break;
			default:
				break;			
			}
			return result;
		}		
	}
```


----------



## SlaterB (1. Jun 2007)

statt
case 0: 
case 1: 

usw. schreibe

case LASTNAME:
usw
wenn du schon so schöne Indexe hast,

-----

mehrere Sortierungen ist relativ leicht, übergib statt einem sortField mehrere (evtl. Array)

in compare fängst du mit dem ersten sortField an und machst mit den anderen weiter,
sofern vorhanden und compare result == 0 (Schleife!)
--------

nur Teile zu sortieren wird mit Collections.sort nicht klappen,
entweder eigener Algorithmus, oder:
Teilliste erstellen, sortieren, an richtige Position zurückschreiben


----------



## kleiner_held (1. Jun 2007)

Das mit dem Sortieren nach mehreren Spalten hab ich ab und an ungefaehr so geloest:

```
public abstract class FieldComparator<T> implements Comparator<T>
	{ 
	   boolean direction;
	   int[] fields;

	   public FieldComparator(boolean direction, int ...fields)
	   {
		   this.direction = direction;
		   this.fields = fields;
	   }
	   
	   public int compare(T o1, T o2)
	   {
		  int result = 0;
		  for (int i = 0; i < fields.length && result == 0; i++)
		  {
			  result = doCompare(fields[i], o1, o2);
		  }
		  return  result * (direction ? 1 : -1);
	   }
	   
	   protected abstract int doCompare(int field, T o1, T o2);
	}
```


----------



## schuetzejanett (1. Jun 2007)

Hallo,

danke für die schnelle Antwort.

Ich hänge jetzt aber bei der umsetzung deines Tips , mehrere spalten zu sortieren.

Da ich ja weiß wieviele spalten ich sortieren will muss ich ja kein Feld übergeben sondern kann das ja gleich in der Klasse festlegen. 
ich verstehe was du damit meinst wenn result 0 weitersortieren in einer schleife bis keine spalten mehr sortiert werden müssen. Aber ich hänge ein bischen beim ablauf.

Wenn ich die arraylist sortieren will schreibe ich ja 


```
Collections.sort(ListPjOv, new ArraySort());
//ohne Parameter weil spalten ja jetzt bekannt
```

das ruft doch die compareMethode in meiner klasse Arraysort auf. 
Jetzt weiß ich allerdings nicht muss ich jetzt die compare methode mit einer schleife versehen. Oder eine andere methode die die compareMethode aufruft in der ich die spalten tück für stück angebe.


----------



## SlaterB (1. Jun 2007)

```
public int compare(PjOv pjOv1, PjOv pjOv2 ) 
      { 

int result = 0;
while(<anzahlSortierungen && result == 0) {
  int sortField = aktuellesSortField // evtl Index nebeihochzähen

   // Rest wie bisher

}

}
```

siehe auch das Post kurz vor deinem!


----------



## schuetzejanett (1. Jun 2007)

hallo,

habe das versucht. Er bringt zar keinen fehler aber er sortiert auch nicht was ist falsch.

```
public  class Sort implements Comparator<Model> 	   { 
					
			public final static int NACHNAME 	= 0;
			public final static int VORNAME 	= 1;		
			public final static int WOHNORT 	= 2;
			public final static int MAENNLICH    = 3; 
		 
		  
	      int[] fields = new int[4];      

	      public Sort() 
	      { 
	        for (int i =0 ; i <4 ;i++)
	        {
	        	
	        	fields[i] = i;
	        }
	      } 
	       
	      public int compare(Model o1, Model o2) 
	      { 
	        int result = 0; 
	        for (int i = 1; i < fields.length && result == 0; i++) 
	        { 
	           result = doCompare(fields[i], o1, o2); 
	        } 
	        return  result ;
	      } 
	       
	      private int doCompare(int field, Model o1, Model o2)
	      {
	    	  int result = 0;
	    	  switch (field) {
		
			case NACHNAME:
				result = o1.getNachname().compareTo(o1.getNachname());
				break;
			case VORNAME:
				result = o1.getVorname().compareTo(o1.getVorname());
				break;
			case WOHNORT:
				result = o1.getWohnort().compareTo(o1.getWohnort());
				break;
			case MAENNLICH:
				Boolean value3 = o1.isMaennlich();
				Boolean value4 = o1.isMaennlich();
				result = value3.compareTo(value4);				
			default:
				break;
			}	    	  
	    	  return result;
	   } 
}
```

[/code]


----------



## SlaterB (1. Jun 2007)

vom dumm rumstehen löst sich kein Programmierproblem der Welt,

erstelle dir eine Liste mit Testdaten,
und dann prüfe Schritt für Schritt, was genau der Comparator macht,
System.out.println-Lawine,
so dass am Ende rauskommt

'vergleiche Elemen A = ... mit Element B = ...'
'Result == 0, vergleiche Spalte x, Wert bei A = .., Wert = B ...'
'Endergebnis Result = ..' [oder wieder vorherigen Satz mit nächster Spalte]
usw.

lasse dir von deinem Programm millimetergenau ausgeben, 
was es wann tut und warum welches Element kleiner als welches ist,

dann findest du jeden Fehler


----------



## schuetzejanett (1. Jun 2007)

Also Testdaten geschrieben und sortiert habe ich deswegen habe ich ja gesehen das er nix macht ok werde nochmal mit dem dabugger durchgehen und ein paar testausgaben machen


----------



## schuetzejanett (1. Jun 2007)

Ok habe den Fehler gefunden habe durch copy&Paste fehler immer ein objekt mit sich selbst verglichen. 

Hier noch mal der entgültige und richtige code


```
public  class Sort implements Comparator<Model>       { 
                
         public final static int NACHNAME    = 0; 
         public final static int VORNAME    = 1;       
         public final static int WOHNORT    = 2; 
         public final static int MAENNLICH    = 3; 
       
        
         int[] fields = new int[4];      

         public Sort() 
         { 
           for (int i =0 ; i <4 ;i++) 
           { 
               
              fields[i] = i; 
           } 
         } 
           
         public int compare(Model o1, Model o2) 
         { 
           int result = 0; 
           for (int i = 1; i < fields.length && result == 0; i++) 
           { 
              result = doCompare(fields[i], o1, o2); 
           } 
           return  result ; 
         } 
           
         private int doCompare(int field, Model o1, Model o2) 
         { 
            int result = 0; 
            switch (field) { 
       
         case NACHNAME: 
            result = o1.getNachname().compareTo(o2.getNachname()); 
            break; 
         case VORNAME: 
            result = o1.getVorname().compareTo(o2.getVorname()); 
            break; 
         case WOHNORT: 
            result = o1.getWohnort().compareTo(o2.getWohnort()); 
            break; 
         case MAENNLICH: 
            Boolean value3 = o1.isMaennlich(); 
            Boolean value4 = o2.isMaennlich(); 
            result = value3.compareTo(value4);             
         default: 
            break; 
         }            
            return result; 
      } 
}
```

Danke nochmal für die schnellen Antworten


----------



## tfa (1. Jun 2007)

Warum so kompliziert?
Der Sortieralgorithmus in Collections.sort() ist stabil. Also sortier Deine Liste erst nach dem
2. Kriterium und danach nach dem 1. Sortierkriterium und Du erhälst was Du willst.

tfa


----------



## SlaterB (1. Jun 2007)

ist ja auch nur der x-fache Aufwand
(was natürlich hier keine Rolle spielt, klar)


----------



## tfa (1. Jun 2007)

SlaterB hat gesagt.:
			
		

> ist ja auch nur der x-fache Aufwand
> (was natürlich hier keine Rolle spielt, klar)



Kommt drauf an. Wenn Millionen Datensätze sortiert werden sollen, sicherlich. 
Bei normalen Mengen ist mein Vorschlag vorzuziehen. Zwei Zeilen gegenüber 54,
die alle geschrieben, getestet und debuggt werden müssen...

tfa


----------



## SlaterB (1. Jun 2007)

Erbsenzähler,
und der Original-Comparator war ja auch schon 40 Zeilen lang,
und irgendwo muss dann immer noch die Schleife und das Array der Suchfelder her 
das gibt sich nix


----------



## tfa (1. Jun 2007)

SlaterB hat gesagt.:
			
		

> Erbsenzähler,
> und der Original-Comparator war ja auch schon 40 Zeilen lang,
> und irgendwo muss dann immer noch die Schleife und das Array der Suchfelder her
> das gibt sich nix



Was ich eigentlich sagen wollte: Warum selber was basteln wenn man doch ganz einfach
eine (eingebaute) Standardlösung nehmen kann? Geht schneller, ist sicherer und einfacher.

tfa


----------

