Customer Cars und Sortieren2.0 in JAVA

Customer Cars

Bis in die frühre 80iger Jahre gab es in der Formel 1 sogenannte "Customer Cars". Einige F1 Teams waren richtiggehende Hersteller von F1 Wagen. Sie bauten die Wagen nicht nur für sich, sondern für jeden zahlenden Kunden, genau wie einige Motorenhersteller. Maserati, Lancia und Ferrari konnten man in den 50iger Jahren käuflich erwerben und einsetzen. In den 60iger waren Cooper, Lotus und Brabham weit verbreit. In den 70iger Jahren kam March als "Massenhersteller" und vereinzelte Mclaren und letztlich einige Williams FW07 auf den Markt. Das ein oder andere grosse Team fing mit solchen "Customer Cars" an, so taten es Tyrrell und Williams, aber auch kleinere Teams wie Hill, RAM und Surtees.

Customer Cars führten dazu das die Starterfelder bei einem GP gross waren, zu gross für den Geschmack einiger. Die Eintrittsschwelle für neue Fahrer und Teams war niedrig. Auch waren manche Teams echte "Garagisten" und Träumer - aber gerade diese Underdogs und Träumer haben der Formel 1 einen speziellen Reiz gegeben. Frank Williams war einer der belächelten Garagisten, und hat es mit seinem Team aber mit eisernem Willen zum Weltmeisterteam gebracht. Es gab sogar Teams die immer zu einem GP (Team Gunston - Südafrika) mit einem Wagen und lokalnm Sponsoren und Fahrern antraten. Man musste damals nicht die ganze Saison dabei sein. Entsprechend bunt waren einige Fahrzeuge ...

Die Kommerzialisierung / Professionaisierung in den 90igern und das Auftreten grosser Hersteller seit den 2000er Jahren bedeuteten das Ende für "Customer Cars" und kleine Teams in der Formel 1, als auch für die Romantik des ambitionierten Amateurs und seines ehrenwerten Scheiterns. In vielen anderen Motorsportkategorien sind "Customer Cars" nach wie vor Gang und Gäbe, und auch in der Formel 1 wäre dies m.E. möglich und sinnvoll.


In meiner F1 Anwendung (F1 WebSite trifft es nicht mehr so ganz ...) müssen die "Werkswagen" und "Customer Cars" aus diversen Gründen unterschieden werden. In der Datenbank ist das eine Sache von Atrributen und Werten, bei den Bildern eine Frage der Namenskonvention. Da ich (dem "Pfad"" von Sauro Torregianni folgend) relativ spät zu den "Customer Cars" gekommen bin, hatte ich bei der Namenskonvention die Wahl zwischen einem Suffix oder einem Präfix. Ich habe mich für das Präfix "$" entschieden - nicht ganz unpassend wie ich finde.

Ein und der gleiche Wagen kann also von zwei oder mehreren Teams eingesetzt werden. Die Customer Cars haben den Suffix $, die "Werkswagen" keinen.

Werkswagen :

1970_Lotus_49C_Ford_Rindt_Monaco_.jpg
Customer Car :
$1970_Lotus_49C_Ford_Charlton_South Africa_.jpg 

Die weiteren Felder sind das Jahr, der Konstrukteur, der Motorenhersteller, der Fahrer und das Rennen, jeweils getrennt duch einen "_" underscore. Soweit so gut, nur beim Sortieren der Bilder (und das passiert an einigen Stellen) muss das Präfix ignoriert werden. Das heisst ein angepasster Algorithmus musste her.

Sortieren

Mein erster Impuls war es, einen eigenen angepassten Sortieralgorithmus zu implementieren. Der "bubble sort" und ich haben ja eine lange Geschichte miteinander, aber auf gewisse Weise endet diese hier, denn es besteht keine Notwendigkeit einen eigenen Algorithmus in JAVA zu entwickeln. JAVA bietet Sortiermethoden für Arrays und Listen - und diese können sehr smart erweitert und modifiziert werden. Es geht hier um eines der Kernanliegen und -elemente der objektorientierten Programierung: bestehende Objekte und Methoden können angepasst werden -@Override und Comparator sind die Zauberworte.

Nun aber zum Problem und der Lösung ...

Mit der Methode arrayOfFilenames wird der Inhalt des Directories PATH als sortiertes Array von Strings zurückgeliefert:

 
                public static String[] arrayOfFilenames(String PATH) {
                    
                    String  pattern  = "_Test_";
                    List<>  fList    = new ArrayList<>();
                    File    folder   = new File(PATH);
                    File[]  files    = folder.listFiles();
                     
                    for (File f : files) 
                        if (!f.getName().contains(pattern) && f.getName().endsWith(".jpg") && f.isFile() && !f.isHidden()) 
                                fList.add(f.getName());
                        
                    String[] fileNames = fList.toArray(new String[0]);
                    Arrays.sort(fileNames);

                    return fileNames;
                }
            
Die Methode Arrays.sort(FileNames); sortiert das Array mit dem Namen fileNames alphabetisch. Sie wird in JAVA bereitgestellt.

Comparator Interface

Die Methode gibt es auch mit einem zweiten Argument. Dieses zweite Argument muss ein sogenannter Comparator sein, genauer eine Implementierung des JAVA interface Comparator. So ein Comparator ist im Prinzip ein Vergleichsoperator. Der Vergleich zweier "Werte" ist der Kern eines jeden Sortieralgorithmus.

Ein Comparator liefert zu zwei Parametern s1 und s2:

Es gibt einige vordefinierte Vergleichsoperatoren, die mit Arrays.sort() verwendet werden können. Der gängigste ist Collections.reverseOrder() und er tut mit
                Arrays.sort(fileNames,Collections.reverseOrder() );
das was man erwarten darf - das Array wird in umgekehrter alphabetischer Reihenfolge sortiert, das funktioniert mit allen Standard JAVA Datentypen.

Nun zum Coden eines eigenen Comparator ... Das Comparator Interface ist in java.util package deklariert und definert eine compare(arg1, arg2) Methode mit zwei Argumenten, welche die zu vergleichenden Objekte repräsentieren:
                public interface Comparator<T> {
                    public int compare(T o1, T o2);
                }
            
Ein eigener Comparator MyComparator würde im ersten Schritt das interface implemntieren und die Methode compare überschreiben:
                static class MyComparator implements Comparator<String> {
                    @Override
                    public int compare(String s1, String s2) {
                        return S1.compareTo(S2);
                    }
                }
            
Die JAVA String Methode compareTo() Methode vergleicht zwei Strings lexikographisch (Unicode-Werte). Soweit ist das nichts Neues. Wenn man jetzt bei den zu vergleichenden Strings ein führendes $ Zeichen entfernt, ist die neue Methde fertig!
                static class MyComparator implements Comparator {
                    @Override
                    public int compare(String s1, String s2) {
                        String cleanS1 = s1.startsWith("$") ? s1.substring(1) : s1;
                        String cleanS2 = s2.startsWith("$") ? s2.substring(1) : s2;
                        return cleanS1.compareTo(cleanS2);
                    }
                }
            
und mit dem Aufruf
                ..
                Arrays.sort(fileNames, new MyComparator());
                return fileNames;
                ... 
            

ist das Problem der führenden $-Zeichen bei "Customer Cars" gelöst.

Comparator mit Collections

Der Vollständigkeit halber - das Interface Comparator ist auch auf Listen bzw. Collections anwendbar, der obige Code kann auch so gestaltet werden:
            public static String[] arrayOfFilenames(String PATH) {
                             
                List<>  fList    = new ArrayList<>();
                File    folder   = new File(PATH);

                for (File f : folder.listFiles()) 
                    if (!f.getName().contains("_Test_") && f.getName().endsWith(".jpg") && f.isFile() && !f.isHidden()) 
                            fList.add(f.getName());
                
                Collections.sort(fList, MyComparator);

                return fList.toArray(new String[0]);
            }
        
 
s