ArrayList (Zahlen) aufsteigend sortieren mit Duplikaten

Tinga

Mitglied
Hallo zusammen,


ich habe wieder ein kleines Problem. Und zwar arbeite ich gerade mit Apache POI (nur als Erklärung, warum ich mit Row, Cell etc. hantiere. Das eigentliche Problem hat, denke ich, nichts mit der API zu tun und sollte recht simpel sein.)

Zum Problem:
Ich habe eine Spalte in einer Excel-Datei in der Zahlenwerte (als Double) stehen. Diese lese ich zeilenweise ein und füge sie einer Liste hinzu. Nachdem ich alle Zeilen durchlaufen habe, sortiere ich die Liste (aufsteigend). Ich bin nun an den ersten 3 Zahlenwerte interessiert bzw. vor allem, in welchen Zeilen diese Werte stehen. Dazu durchlaufe ich die Spalte nochmals zeilenweise (ist programmiertechnisch sicherlich suboptimal und nicht gerade performant, für meine Zwecke reichts aber.)

Sind die 3 Werte voneinander verschieden (z.B. 0,1; 0,2; 0,3) funktioniert alles tadellos. Kommt nur ein Wert doppelt vor (z.B. 0,1; 0,2; 0,2) zerschießt sich das Programm völlig. Ich krieg „nur“ eine NullPointerException ausgeworfen.

Ich habe auch schon im Forum gesucht aber nichts wirklich Hilfreiches gefunden. Was ich gelesen habe ist, dass Maps o.Ä. bei ähnlichen Problemen hilfreich sind. Da meine Kenntnisse von Hashmaps etc. recht begrenzt sind, wollte ich nicht rumraten.

Habt ihr ne Idee? Es ist für die Funktionalität zwingend notwendig, dass die Duplikate drin bleiben und der Mechanismus auch mit Duplikaten funktioniert.


Vielen Dank schonmal,
Tinga

Hier noch der Code (nur auszugsweise):

Java:
//Bestimmung der Datensätze mit der geringsten Abweichung
    	    
            List<Double> liste = new ArrayList<Double>();
            for (int m = 4; m <= sheet.getLastRowNum(); m++) {
            	HSSFRow datensatz = sheet.getRow(m);
    	    	HSSFCell aehnlichkeit = datensatz.getCell(14);
    	    	double a = aehnlichkeit.getNumericCellValue();
    	    	liste.add(a);
    	    	Collections.sort(liste); 	
            }
            
            //System.out.println(liste);
            
            double ersterWert = liste.get(0);
            //System.out.println(ersterWert);
            double zweiterWert = liste.get(1);
            //System.out.println(zweiterWert);
            double dritterWert = liste.get(2);
            //System.out.println(dritterWert);
            
            
            int index1 = 0;		//dient dazu, die Zeile mit dem kleinsten Zahlenwert zu finden
            int index2 = 0;		//dient dazu, die Zeile mit dem 2.-kleinsten Zahlenwert zu finden
            int index3 = 0;		//dient dazu, die Zeile mit dem 3.-kleinsten Zahlenwert zu finden
            for (int n = 4; n <= sheet.getLastRowNum(); n++) {
            	HSSFRow datensatz = sheet.getRow(n);
    	    	HSSFCell aehnlichkeit = datensatz.getCell(14);
    	    	double a = aehnlichkeit.getNumericCellValue();
    	    	if (a == ersterWert) {
    	    		index1 = n-3;
    	    	} else {
    	    		
    	    	}
    	    	if (a == zweiterWert) {
    	    		index2 = n-3;
    	    	} else {
    	    		
    	    	}
    	    	if (a == dritterWert) {
    	    		index3 = n-3;
    	    	} else {
    	    		
    	    	}
            }




//Klassifizierende Merkmale (Index, Bauteilname, Art) aus Auswahlzeile auslesen

suchergebnisAnzeigeArea.append("Das Objekt Nr." + index1);
suchergebnisAnzeigeArea.append("Das Objekt Nr." + index2);
suchergebnisAnzeigeArea.append("Das Objekt Nr." + index3);
 
Exceptions gehen immer Hand in Hand mit einem StackTrace der genau verrät in welcher Klasse und Zeile die Exception geworfen wurde.
Wie ssoul26 schon angemerkt hat wäre es natürlich sehr hilfreich wenn du diese auch posten würdest.

So können wir nur raten wo sie denn fliegt und als Lösung würde nur kommen: Du hast Objekt X nicht initialisiert!

Des weiteren kann man die Ursache einer NullPointerException ganz leicht per Debugging finden. (was meist schneller geht als im Forum auf Antworten zu warten)
 
Ok, es ist mir fast schon zu peinlich zu sagen, dass die Zelle, die ich auslesen wollte, leer war, weil ich kurz zuvor eine Änderung am Code vorgenommen habe. Ich saß jetzt mehrere Stunden dran! Habe mir die fehlerhafte Zeile sogar angeschaut und gedacht: „Da kann wirklich nichts falsch sein.“Oh Mann.
Tut mir Leid, dass ich Euch grundlos Aufwand beschert habe.

Eine Frage bleibt trotzdem noch. Es geht mir immernoch um die Duplikate. Ich melde mich gleich nochmal mit dem konkreten Problem. Ich pass den Code derweil an, damit es für Euch verständlicher wird, was ich meine.


Bis gleich
 
Ich hab euch mein Problem in kleinem Maßstab nachgebaut. Solange es keine Duplikate gibt funktioniert alles. Sieht meine Tabelle zum Beispiel so aus:
A 3
B 4
C 5
D 2
E 1
F 6
Dann erhalte ich folgende Ausgabe:
Das Objekt Nr.e weißt die größte
Übereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:1.0)

Das Objekt Nr.d weißt die zweitgrößte
Übereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:2.0)

Das Objekt Nr.a weißt die drittgrößte
Übereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:3.0)

Kommt nun ein Zahlenwert doppelt vor, z.B. so:
A 1
B 4
C 5
D 1
E 1
F 6
Dann erhalte ich diese Ausgabe:
Das Objekt Nr.e weißt die größte
Übereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:1.0)

Das Objekt Nr.e weißt die zweitgrößte
Übereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:1.0)

Das Objekt Nr.e weißt die drittgrößte
Übereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:1.0)
Ich will aber:
Das Objekt Nr.a weißt die größte
Übereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:1.0)

Das Objekt Nr.d weißt die zweitgrößte
Übereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:1.0)

Das Objekt Nr.e weißt die drittgrößte
Übereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:1.0)

Java gibt mir also 3 mal die letzte Zeile mit dem niedrigsten Wert (e) aus. Ich möchte aber, dass er mir alle 3 Datensätze ausgibt – idealerweise von oben nach unten (in dem hier dargestellten Fall also a-d-e). Wenn 3 identische Werte vorkommen soll der Output dann nicht mehr „größte, zweitgrößte, drittgrößte“ sein sondern nur noch „größte“. (Das werde ich hoffentlich selbst hinbekommen.) Für den Rest bräuchte ich aber eine Idee.

Heute Mittag habe ich einen Bock geschossen. Das ist nun ein „echtes Programmier-Problem“. Meine bisherigen Ansätze haben sich darauf konzentriert, vor der for-Schleife eine if-Anweisung zu setzen, in der ich die Unterscheidung treffe:
if (ersterWert == zweiterWert && ersterWert == dritterWert) {
}
if (ersterWert == zweiterWert) {
}
if (zweiterWert == dritterWert) {
}
Ich hab aber noch keine Anweisung in den geschweiften Klammern, weil mir der Ansatz fehlt.

Der ganze Code der funktioniert ist hier:
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;


public class Test {
	public static void main (String[] args) {
		try
	      {
			FileInputStream myInput = new FileInputStream("C:/Users/max/Desktop/Max/Studium/Master/00_Hiwi/20140307_Eclipse/20140919_Demonstration/Excel.xls");
			POIFSFileSystem fileSystem = new POIFSFileSystem(myInput);
		    HSSFWorkbook workbook = new HSSFWorkbook(fileSystem);
		    HSSFSheet sheet = workbook.getSheetAt(0);
		     
		    //Bestimmung der Datensätze mit der geringsten Abweichung
	    	    
	            List<Double> liste = new ArrayList<Double>();
	            for (int m = 0; m <= sheet.getLastRowNum(); m++) {
	            	HSSFRow datensatz = sheet.getRow(m);
	    	    	HSSFCell aehnlichkeit = datensatz.getCell(1);
	    	    	double a = aehnlichkeit.getNumericCellValue();
	    	    	liste.add(a);
	    	    	Collections.sort(liste); 	
	            }
	            
	            //System.out.println(liste);
	            
	            double ersterWert = liste.get(0);
	            //System.out.println(ersterWert);
	            double zweiterWert = liste.get(1);
	            //System.out.println(zweiterWert);
	            double dritterWert = liste.get(2);
	            //System.out.println(dritterWert);
	            
	            
	            int index1 = 0;		//dient dazu, die Zeile mit dem kleinsten Zahlenwert zu finden
	            int index2 = 0;		//dient dazu, die Zeile mit dem 2.-kleinsten Zahlenwert zu finden
	            int index3 = 0;		//dient dazu, die Zeile mit dem 3.-kleinsten Zahlenwert zu finden
	            for (int n = 0; n <= sheet.getLastRowNum(); n++) {
	            	HSSFRow datensatz = sheet.getRow(n);
	    	    	HSSFCell aehnlichkeit = datensatz.getCell(1);
	    	    	double a = aehnlichkeit.getNumericCellValue();
	    	    	if (a == ersterWert) {
	    	    		index1 = n;
	    	    		//System.out.println(sheet.getRow(index1+3).getCell(1).getStringCellValue());
	    	    	} else {
	    	    		
	    	    	}
	    	    	if (a == zweiterWert) {
	    	    		index2 = n;
	    	    		//System.out.println(sheet.getRow(index2+3).getCell(1).getStringCellValue());
	    	    	} else {
	    	    		
	    	    	}
	    	    	if (a == dritterWert) {
	    	    		index3 = n;
	    	    		//System.out.println(sheet.getRow(index3+3).getCell(1).getStringCellValue());
	    	    	} else {
	    	    		
	    	    	}
	        	
	            }
	            
	            String name1 = sheet.getRow(index1).getCell(0).getStringCellValue();
	            String name2 = sheet.getRow(index2).getCell(0).getStringCellValue();
	            String name3 = sheet.getRow(index3).getCell(0).getStringCellValue();
	            
	            System.out.println("Das Objekt Nr." + name1 + " weißt die größte \nÜbereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:" + ersterWert + ")\n"); 
	            System.out.println("Das Objekt Nr." + name2 + " weißt die zweitgrößte \nÜbereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:" + zweiterWert + ")\n");
	            System.out.println("Das Objekt Nr." + name3 + " weißt die drittgrößte \nÜbereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:" + dritterWert + ")\n");
	   
	            FileOutputStream myOutput = new FileOutputStream(new File("C:/Users/max/Desktop/Max/Studium/Master/00_Hiwi/20140307_Eclipse/20140919_Demonstration/Excel.xls"));  
	            workbook.write(myOutput);
	            myOutput.close();
	      } catch (Exception ex) {
	    	  ex.printStackTrace();
	      }
		
		
		
	}

}
 
Es hat zwar eine ganze Weile gedauert, aber mittlerweile habe ich mein Problem selbst gelöst. Für den Fall, dass jemand jemals ein ähnliches Problem haben sollte, poste ich meinen Code:

Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;


public class Test {
	public static void main (String[] args) {
		try
	      {
			FileInputStream myInput = new FileInputStream("C:/Users/max/Desktop/Max/Studium/Master/00_Hiwi/20140307_Eclipse/20140919_Demonstration_3.2-Test/Excel.xls");
			POIFSFileSystem fileSystem = new POIFSFileSystem(myInput);
		    HSSFWorkbook workbook = new HSSFWorkbook(fileSystem);
		    HSSFSheet sheet = workbook.getSheetAt(0);
		     
		    //Bestimmung der Datensätze mit der geringsten Abweichung
	    	    
	            List<Double> liste = new ArrayList<Double>();
	            for (int m = 0; m <= sheet.getLastRowNum(); m++) {
	            	HSSFRow datensatz = sheet.getRow(m);
	    	    	HSSFCell aehnlichkeit = datensatz.getCell(1);
	    	    	double a = aehnlichkeit.getNumericCellValue();
	    	    	liste.add(a);
	    	    	Collections.sort(liste); 	
	            }
	            
	            //System.out.println(liste);
	            
	            double ersterWert = liste.get(0);
	            //System.out.println(ersterWert);
	            double zweiterWert = liste.get(1);
	            //System.out.println(zweiterWert);
	            double dritterWert = liste.get(2);
	            //System.out.println(dritterWert);
	            
	            
	            int index1 = 0;		//dient dazu, die Zeile mit dem kleinsten Zahlenwert zu finden
	            int index2 = 0;		//dient dazu, die Zeile mit dem 2.-kleinsten Zahlenwert zu finden
	            int index3 = 0;		//dient dazu, die Zeile mit dem 3.-kleinsten Zahlenwert zu finden
	            for (int n = 0; n <= sheet.getLastRowNum(); n++) {
	            	HSSFRow datensatz = sheet.getRow(n);
	    	    	HSSFCell aehnlichkeit = datensatz.getCell(1);
	    	    	double a = aehnlichkeit.getNumericCellValue();
	    	    	if (a == ersterWert || a == zweiterWert || a == dritterWert) {
	    	    		if (a == ersterWert) {
	    	    			index1 = n;
	    	    		}
	    	    		for (int m = 0; m <= n-1; m++) {
	    	    			if (a == zweiterWert) {
	    	    				if (ersterWert == zweiterWert) {   	    			
		    		            	HSSFRow datensatz2 = sheet.getRow(m);
		    		    	    	HSSFCell aehnlichkeit2 = datensatz2.getCell(1);
		    		    	    	double b = aehnlichkeit2.getNumericCellValue();
		    		    	    	if (b == zweiterWert) {
		    		    	    		index2 = m;
		    		    	    	}
	    	    				}
	    	    			}
		    		    	if (a == dritterWert) {
		    		    	    	if (zweiterWert == dritterWert) {
		    		    	    		for (int o = 0; o <= m-1; o++) {
		    		    	            	HSSFRow datensatz3 = sheet.getRow(o);
		    		    	    	    	HSSFCell aehnlichkeit3 = datensatz3.getCell(1);
		    		   		    	    	double c = aehnlichkeit3.getNumericCellValue();
		    		   		    	    	if (c == dritterWert) {
		    		   		    	    		index3 = o;
		    		   		    	    	}
		    	    	    			}
		    	    	    		}
		   		    	    		if (zweiterWert != dritterWert) {
		   		    	    			for (int o = 0; o <= sheet.getLastRowNum(); o++) {
		   		    		            	HSSFRow datensatz3 = sheet.getRow(o);
		   		    		    	    	HSSFCell aehnlichkeit3 = datensatz3.getCell(1);
	    		    		    	    	double d = aehnlichkeit3.getNumericCellValue();
		    		    		    	   	if (d == dritterWert) {
		    		    		    	   		index3 = o;
		    		    		    	   	}
		    		    	    		}
		    		    	    	}
		    		    	   	}
		    		    	    	
		    	    			
		    	    		
		    	    		if (ersterWert != zweiterWert) {
		    	    			if (a == zweiterWert) {
		    	    				index2 = n;
		    	    			}
		    	    			if (a == dritterWert) {
	    		    	    		if (zweiterWert == dritterWert) {
	    		    	    			for (int o = 0; o <= m-1; o++) {
	    		    		            	HSSFRow datensatz3 = sheet.getRow(o);
	    		    		    	    	HSSFCell aehnlichkeit3 = datensatz3.getCell(1);
	    		    		    	    	double c = aehnlichkeit3.getNumericCellValue();
	    		    		    	    	if (c == dritterWert) {
	    		    		    	    		index3 = o;
	    		    		    	    	}
	    		    	    			}
	    		    	    		}
	    		    	    		if (zweiterWert != dritterWert) {
	    		    	    			if (a == dritterWert) {
	    		    	    				index3 = n;
	    		    	    			}
	    		    	    		}
	    		    	    	}
		    	    		}
		    	    	}
		    	    	
	    	    	}
	    	    	
	    	    	
	            }
	    		    	    	
	    		    	    	
	            
	            
	            String name1 = sheet.getRow(index1).getCell(0).getStringCellValue();
	            String name2 = sheet.getRow(index2).getCell(0).getStringCellValue();
	            String name3 = sheet.getRow(index3).getCell(0).getStringCellValue();
	            
	            System.out.println("Das Objekt Nr." + name1 + " weißt die größte \nÜbereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:" + ersterWert + ")\n"); 
	            System.out.println("Das Objekt Nr." + name2 + " weißt die zweitgrößte \nÜbereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:" + zweiterWert + ")\n");
	            System.out.println("Das Objekt Nr." + name3 + " weißt die drittgrößte \nÜbereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:" + dritterWert + ")\n");
	   
	            FileOutputStream myOutput = new FileOutputStream(new File("C:/Users/max/Desktop/Max/Studium/Master/00_Hiwi/20140307_Eclipse/20140919_Demonstration_3.2-Test/Excel.xls"));  
	            workbook.write(myOutput);
	            myOutput.close();
	      } catch (Exception ex) {
	    	  ex.printStackTrace();
	      }
		
		
		
	}

}
 
[...] Für den Fall, dass jemand jemals ein ähnliches Problem haben sollte, poste ich meinen Code[...]

Das ist zwar nett aber die Qualität des Codes lässt zu wünschen übrig. Der Code ist übermäßig kompliziert, unstrukturiert und enthält potenzielle Fehler.

  • Double/Float-Werte sollten nicht mit == verglichen werden, auch eine Epsilonumgebung ist nicht das Wahre. Korrekt ist die Methode Double.compare(double a, double b) zu verwenden. Weshalb, das kann jeder selbst nachlesen.
  • Der Inputstream wird nie geschlossen.
  • catch Exception ist selten eine gute Idee vielmehr sollten die möglichen Exceptions in der Reihenfolge "speziell" zu "allgemein" angeordnet sein.

Hier eine, zu Demonstrationszwecken, etwas modifizierte, kompilierbare aber ungetestete Version, die von der Struktur her noch ausbaufähig ist. Die Verwendung von Java-8 Features beschränkt sich auf Z.29.

Java:
public class Test {
    public static void main (String[] args) {
        try {
            String filePath = "C:/Users/max/Desktop/Max/Studium/Master/00_Hiwi/20140307_Eclipse/20140919_Demonstration_3.2-Test/Excel.xls";
            
            HSSFWorkbook workbook;
            try(FileInputStream myInput = new FileInputStream(filePath)) {
                POIFSFileSystem fileSystem = new POIFSFileSystem(myInput);
                workbook = new HSSFWorkbook(fileSystem);
                HSSFSheet sheet = workbook.getSheetAt(0);

                final class Result {
                    int _row;
                    double _val;

                    Result(int row, double value) {
                        _row = row;
                        _val = value;
                    }
                }

                List<Result> list = new ArrayList();
                for (int key = 0; key < sheet.getLastRowNum(); key++) {
                    double val = sheet.getRow(key).getCell(1).getNumericCellValue();
                    list.add(new Result(key, val));
                }

                list.sort(Comparator.comparingDouble(r -> r._val));

                String[] ordnung = {"größte", "zweitgrößte", "drittgrößte"};
                for (int i = 0, countEqPreds = 0; i < ordnung.length; i++) {
                    double val = list.get(i)._val;

                    if( i > 0 && Double.compare(val, list.get(i-1)._val) == 0){
                        countEqPreds++;
                    }

                    System.out.println("Das Objekt Nr."
                            + sheet.getRow(list.get(i)._row).getCell(0).getStringCellValue()
                            + " weist die "
                            + ordnung[i-countEqPreds]
                            + "\nÜbereinstimmung mit Ihrer Suchanfrage auf. (Abweichung:"
                            + val + ")\n");
                }
            }

            try(FileOutputStream myOutput = new FileOutputStream(filePath)){
                workbook.write(myOutput);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 
Zuletzt bearbeitet:

Zurück
Oben