lina-: Vergleich von Objekten

moin liebes Forum :)

Irgendwie bin ich verzweifelt. Meine autodidaktische Methode für Java ist an Grenzen gestoßen, denn ich grübel schon lange an einem (bestimmt einfach zu lösendem Problem).

Ich habe ein Objekt der Klasse Order und eine Liste (ungeordnet), die mehrer Objekte dieser Klasse enthält.
Nun würde ich ja erwarten, dass folgende Anweisung orderList.contains(actualOrder) überprüft, ob der Auftrag (Order) bereits in der Liste enthalten ist oder nicht. Leider bekomme ich _immer_ false zurück - selbst wenn ich kurz zuvor der Liste diesen Auftrag hinzugefügt habe (orderList.add(actualOrder).

Nun hatte ich die Vermutung, dass sich diese Objekte nicht vergleichen lassen, weshalb ich der Klasse Order gesagt habe, sie solle das Interface "Comparable" implementieren (natürlich habe ich die compareTo()-Methode ausprogrammiert indem ich die Auftragsnummern  aus Order und nicht die Objekte selber verglichen habe - hätte ja sonst keinen Sinn, da contains() auch nur mit object.equals(object2) arbeitet).

Leider hat auch das nicht gefruchtet und contains() scheint sich überhaupt nicht für "meine" compareTo-Methode interessiert zu haben.

Nun könnte ich natürlich bei der Überprüfung eine weitere Schleife anlegen, in der ich die Auftragsnummern auf Vorhandensein prüfe - aber das erscheint mir doch wenig elegant und ich würde eine andere Vorgehensweise begrüßen.

Hat jemand (soweit meine wirren Ausführungen es zulassen) Ideen für mich?

vielen Dank für die Aufmerksamkeit und liebe Grüße aus Berlin
lina-

--
Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
  1. Hallo,

    Ich habe ein Objekt der Klasse Order und eine Liste (ungeordnet), die mehrer Objekte dieser Klasse enthält.
    Nun würde ich ja erwarten, dass folgende Anweisung orderList.contains(actualOrder) überprüft, ob der Auftrag (Order) bereits in der Liste enthalten ist oder nicht. Leider bekomme ich _immer_ false zurück - selbst wenn ich kurz zuvor der Liste diesen Auftrag hinzugefügt habe (orderList.add(actualOrder).

    deine Erwartung war nicht unbegründet. Was hast du da für eine Liste verwendet? Welche VM-Version? Bist du sicher, dass actualOrder nach add(actualOrder) nicht irgendwoher neu belegt wird?

    Nun hatte ich die Vermutung, dass sich diese Objekte nicht vergleichen lassen,

    Er vergleicht ja nicht die Objekte sondern die Referenzen auf diese, d.h. es wird auf Objektidentität geprüft. Das Comparable Objekte ermöglicht dagegen den Vergleich _verschiedener_ Objekte. Das ist in deinem Fall der falsche Weg.

    Hat jemand (soweit meine wirren Ausführungen es zulassen) Ideen für mich?

    Wenn die Antworten auf meine Fragen nix bringen, dann musst du ein bissel Code rausrücken.

    Gruß
    MrWurf

    1. moin MrWurf :)

      deine Erwartung war nicht unbegründet. Was hast du da für eine Liste verwendet?

      Einen Vector. Ist das in irgendeiner Form ausschlaggebend?

      Welche VM-Version?

      1.4.2

      Bist du sicher, dass actualOrder nach add(actualOrder) nicht irgendwoher neu belegt wird?

      ja - ganz sicher. Ich hatte das ja testweise nur reingeschrieben und zwar direkt in der übernächsten Zeile ;) Aber ich glaube ich verstehe jetzt...
      ich nehme gleich nochmal darauf Bezug.

      Nun hatte ich die Vermutung, dass sich diese Objekte nicht vergleichen lassen,
      Er vergleicht ja nicht die Objekte sondern die Referenzen auf diese, d.h. es wird auf Objektidentität geprüft. Das Comparable Objekte ermöglicht dagegen den Vergleich _verschiedener_ Objekte. Das ist in deinem Fall der falsche Weg.

      Ha! Hier liegt der Hase im Pfeffer begraben. Die Objekte in der Liste haben ja nicht die gleichen Referenzen wie die zu vergleichenden.
      Also wäre das Comparable doch der richtige Weg für mich.
      Nur was habe ich bei der Umsetzung falsch gemacht? Reicht es nicht, die Klasse das Interface implementieren zu lassen (und natürlich die Mehthode auszuprogrammieren)?

      Wenn die Antworten auf meine Fragen nix bringen, dann musst du ein bissel Code rausrücken.

      Deine Fragen haben mir durchaus weitergeholfen, das Problem zu verstehen. Aber der Lösung bin ich dennoch nicht näher gekommen.
      Hier mal ein paar Codeschnipsel, die ich für relevant halte:

      1. das Erzeugen der Auftragsliste anhand der vorhanden XML-Dateien.

        
      public List getCustomersOrders(String customerNumber) {  
         File custDir=new File(base,customerNumber);  
         List result = new Vector();  
         if (custDir != null && custDir.exist()) {  
           File[] orders = custDir.listFiles();  
           for (int i = 0; orders != null && i < orders.length; i++) {  
             if (orders[i].isDirectory()) {  
               File oFile = new File(orders[i], ORDERFILE);  
               if (oFile.exists()) {  
                 try {  
                   SAXReader reader = new SAXReader();  
                   Document doc = reader.read(oFile);  
                   Order o = new Order(doc); //Auftragsobjekt erstellen  
                   Job j = getJob(o);  
                   o.setJob(j);  
                   result.add(o); //Hier wird der Auftrag der Liste hinzugefügt  
                 } catch (DocumentException e) {  
                   error("DOM Error", e);  
                 }  
               }  
             }  
           }  
         }  
         if (orderBy != null) {  
           Collections.sort(result, new OrderComparator(orderBy));  
         }  
         if (orderByDesc != null) {  
           Collections.sort(result, new OrderComparator(orderByDesc));  
           Collections.reverse(result);  
         }  
         return result; //Sortierte Liste zurückgeben  
        }  
      
      

      2. Das Zusammenstellen der Aufträge verschiedener Kunden (können doppelt vergeben sein - sollen aber freilich nur einmal angezeigt werden)

        
      Vector result=new Vector();  
      ... //Hier wird der Vector mit den Aufträgen gefüllt, die auf jeden Fall da sein müssen  
      Iterator it=store.getCustomersOrders(store.getUser().getNumber()).iterator();  
        while(it.hasNext()) {  
        Order o=(Order)it.next();  
            if(!result.contains(o)){  //Der Auftrag soll nur hinzugefügt werden, wenn er noch nicht vorhanden ist.  
              result.add(o);  
            }  
        }  
      
      

      3. meine compareTo-Methode aus der Klasse Order

        
      public int compareTo(Object o) {  
          try {  
            Order order = (Order) o;  
            if (order.getNumber().equals(this.getNumber())){  
              return 0; //Objekte sind gleich  
            }  
          } catch (ClassCastException e) {  
             error("No order");  
          }  
          return 1;  //Objekte sind nicht gleich  
      }  
      
      

      liebe Grüße aus Berlin
      lina-

      --
      Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
      1. moin :)

        ja - ganz sicher. Ich hatte das ja testweise nur reingeschrieben und zwar direkt in der übernächsten Zeile ;) Aber ich glaube ich verstehe jetzt...
        ich nehme gleich nochmal darauf Bezug.

        Das habe ich jetzt glatt vergessen ;)
        Ich wollte nur erwähnen, dass ich auch hier ein neues Objekt erzeugt habe und somit die Referenz auch nicht die selbe war...

        liebe Grüße aus Berlin
        lina-

        --
        Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
      2. Hallo lina,

        Die contains() Methode bezieht sich immer auf Objekt-Gleichheit, verwendet also equals, compareTo oder einen angegebenen Comparator (je nach Implementierung).
        Ausnahmen sind einige wenige Implementierungen, bei denen explizit angegeben ist, dass sie Objekt-Identität also == verwenden.

        Was Du tun musst, und wohl nicht getan hast, ist equals zu überschreiben. Dies musst Du auch dann tun, wenn Du Comparable implementierst. Die Spezifikation von Comparable verlangt sogar explizit, dass o1.compareTo(o2) == 0 genau dann wenn o1.equals(o2).
        Der Vector wird equals verwenden, er muss ja nur vergleichen und braucht keine Ordnung der Objekte. Daher funktioniert das auch nicht so, wie Du es erwartest.

        Der zweite Punkt ist, dass Comparable eine Ordnung auf den Objekten definieren muss, d.h. es muss unter anderem gelten: o1.compareTo(o2) > 0 genau dann wenn, o2.compareTo(o1) < 0. Deine Implementierung gibt aber immer 1 zurück, wenn zwei Objekte verschieden sind und verletzt somit die Spezifikation.
        Wenn Du solche Objekte z.B. sortieren lässt, terminiert der Sortieralgorithmus vermutlich nicht einmal mehr.

        Ich denke, Du willst nur auf Gleichheit testen und keine Ordnung definieren. In dem Fall reicht es völlig, equals zu überschreiben.
        Es ist zu beachten, dass Du dann auch hashCode überschreiben musst, da dessen Spezifikation logischerweise verlangt o1.equals(o2) impliziert o1.hashCode() == o2.hashCode(). Wenn Du solche Objekte z.B. in eine Hashtabelle packst, kommt es sonst zu komischen Effekten.

        Die Verwendung einer Hashtabelle würde sich übrigens anbieten, um zu prüfen, ob ein gleiches Objekt schon einmal vorkam. Die contains()-Methode einer unsortierten Liste muss ja immer die komplette Liste durchlaufen. Da Du das für jedes Objekt, dass Du hinzufügst machst, läuft das auf ein O(n²)-Verfahren hinaus, was natürlich ungünstig ist, wenn es mehr als eine Hand voll Objekte sind.

        Grüße

        Daniel

      3. Hallo lina,

        ist dein Problem mit den Hinweisen von gelöst?
        Ansonsten könnte ich noch andere Ansätze vorschlagen. Ich bin nämlich kein Fan von überschriebenen equals-Methoden.

        Gruß
        MrWurf

        1. Hallo,

          Ansonsten könnte ich noch andere Ansätze vorschlagen.

          Mach mal! :)

          Gruß
          Slyh

        2. moin MrWurf, moin Daniel :)

          erstmal vielen Dank an Daniel. Deine Erklärung hat meinem Verständnis für dieses Problem sehr geholfen.

          Leider bin ich mir absolut nicht im Klaren, in wie fern ich die equals-Methode überschreiben sollte. Den Vergleich habe ich ja schon in der CompareTo-Methode drin (ist die dann überhaupt noch nötig?). Muss dieser Vergleich dort auch stattfinden?

          Am plausibelsten würde mir ja für einen solchen Fall dieses Konstrukt erscheinen (wirklich glücklich bin ich damit aber nicht):

            
          public int compareTo(Object o) { //überschreibende compare-Methode  
              if(this.equals(o)) return 0  
              else return 1  
          }  
          public boolean equals(Object o) { //überschreibende equals-Methode  
             try {  
                Order order = (Order) o;  
                if (order.getNumber().equals(this.getNumber())){  
                  return true; //Objekte sind gleich  
                }  
              } catch (ClassCastException e) {  
                 error("No order");  
              }  
              return false;  //Objekte sind nicht gleich  
          }  
          
          

          Allerdings bleibt ja hier dann noch das Problem mit der "Ordnung", die ich mit der compare-Methode erzielen müsste (was ich nicht kann, weil es für diese Auftragsobjekte keine wirkliche Ordnung gibt... und selbst wenn es sie geben würde, wär sie nicht interessant für die Anwendung)

          Vor allem aber, habe bei dieser Lösung ich nicht die leiseste Ahnung, mit was ich die hashCode-Methode überschreiben sollte.

          ist dein Problem mit den Hinweisen von gelöst?

          Noch nicht ganz...

          Ansonsten könnte ich noch andere Ansätze vorschlagen. Ich bin nämlich kein Fan von überschriebenen equals-Methoden.

          Ich bin für alles offen :) Laß mich an deinen Ideen teilhaben.

          liebe Grüße aus Berlin
          lina-

          --
          Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
          1. Hallo lina,

            Da es keine Ordnung gibt, ist es auch nicht sinnvoll überhaupt Comparable zu implementieren. Der Vector benötigt das sowieso nicht. Comparable ist nur interessant, wenn Du irgendwie sortierst oder die Elemente in ein TreeSet o.ä. steckst und so Elemente bezüglich ihrer Größe verglichen werden müssen.
            Für alles andere reicht ein Test auf Gleichheit mittels equals aus.
            Das ist sprachlich immer etwas schwer zu unterscheiden, weil "vergleichen" eben "testen auf Gleichheit" oder "vergleichen bezüglich Größe" meinen kann. Comparable stellt eine Schnittstelle für letzteres zur Verfügung und die scheinst Du nicht zu brauchen.

            Ich würde Comparable also nicht implementieren und equals und hashCode implementieren:

              
            public boolean equals(Object o) {  
              if(o instanceof Order) {  
                Order order = (Order) o;  
                if (order.getNumber().equals(this.getNumber())) {  
                  return true;  
                }  
              }  
              return false;  
            }  
              
            public int hashCode() {  
              return getNumber().hashCode();  
            }  
            
            

            equals sollte eigentlich nie irgendwie eine Ausnahme werfen. Entweder sind die Objekte gleich oder sie sind es nicht. Ungültige Eingaben für equals gibt es somit nicht. (Für compareTo gilt das nicht, zwei Objekte können durchaus unvergleichbar sein.)

            hashCode soll ja eine Id des Objekts liefern und zwar so, dass gleiche Objekte auch die gleiche Id haben. Natürlich sollten möglichst wenige verschiedene Objekte, die gleiche Id haben. Das darf aber durchaus passieren. (Eine Implementierung, die z.B. immer 0 zurück gibt ist immer korrekt)
            hashCode sollte man also immer so implementieren, dass man möglichst viele Eigenschaften mit einbezieht, die man in equals verwendet.
            In Deinem Fall ist das nur die Nummer, also kann man einfach deren hashCode nehmen.

            Grüße

            Daniel

            1. moin Daniel :)

              Vielen vielen Dank!

              Irgendwie hatte ich ein Brett vorm Kopf und die Idee Comparable zu implementieren hat mich blockiert. So macht das natürlich sehr viel mehr Sinn und funktioniert auch wunderbar!

              Dass das mit dem Hash-Code dann doch so eine einfach Sache ist, hätt ich ja nicht gedacht ;)

              Auf jeden Fall werde ich dieses Prinzip jetzt auch für andere Objekte überdenken. *freu*

              Danke nochmal!

              liebe Grüße aus Berlin
              lina-

              PS: MrWurf - natürlich bin ich trotzdem noch an Alternativen interessiert. Ich möcht ja weiter lernen!

              --
              Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
          2. Hallo lina,

            hier also mein Vorschlag:
            Soweit ich dich verstanden habe, willst du eine Menge von Order-Objekten ausgeben, in der keine Order doppelt vorkommen soll. Ausserdem sollen die Orders noch irgendwie sortiert werden.
            Dazu nehme ich einfach mal an: (korrigiere mich wenn ich falsch liege)

            • die Orders haben eine eindeutige Bestellnummer,
            • die Orders haben ein Datumseintrag, nach dem du sortieren willst,

            Zum Aussortieren von doppelten Einträgen solltest du die Bestellungen in eine Hashtable packen, jeweils mit der Bestellnummer als Key. Die values dieser Hashtable sind dann automatisch die eindeutigen Bestellungen.

            Hashtable orderhash = new Hashtable();
              // Loop durch Verzeichnisse...
                  Order order = new Order(document);
                  orderhash.put( order.getOrdernumber(), order);
              //

            Zum Sortieren implementierst du das Comparable-Interface an der Order, und sortierst die Values der oben gefüllten Hashtable mit

            Vector sortme = new Vector(orderhash.values());
            Collections.sort(sortme);

            Der Vector sortme enthält nun die eindeutigen sortierten Orders.

            Gruß
            MrWurf

            1. moin MrWurf :)

              hier also mein Vorschlag:
              Soweit ich dich verstanden habe, willst du eine Menge von Order-Objekten ausgeben, in der keine Order doppelt vorkommen soll. Ausserdem sollen die Orders noch irgendwie sortiert werden.

              Ohje - nein - da hast du mich falsch verstanden :/ bzw. habe ich die falschen Ausdrücke verwendet.
              Ich möchte zwei Order-Objekte nur auf Gleichheit testen (wie ich gelernt habe ist das nicht gleichzusetzen mit "vergleichen")

              Dazu nehme ich einfach mal an: (korrigiere mich wenn ich falsch liege)

              • die Orders haben eine eindeutige Bestellnummer,

              richtig

              • die Orders haben ein Datumseintrag, nach dem du sortieren willst,

              falsch - es gibt keinerlei Ordnung in den Orderobjekten.

              Zum Sortieren implementierst du das Comparable-Interface an der Order, und sortierst die Values der oben gefüllten Hashtable mit
              Vector sortme = new Vector(orderhash.values());
              Collections.sort(sortme);
              Der Vector sortme enthält nun die eindeutigen sortierten Orders.

              Dieser Sachverhalt ist mir bei den User-Objekten über den Weg gelaufen - aber gelöst habe ich ihn anders. Und zwar habe ich mir eine Klasse UserComparator gebastelt, die ich so aufrufe: Collections.sort(users, new UserComparator(orderByDesc));
              "users" ist hier die Liste die schliesslich die sortierten User enthält.

              Nur der Vollständigkeit halber möchte ich hier noch meine Comparator-Klasse zeigen. Falls ihr hier Unstimmigkeiten findet, sagt mir doch bitte bescheid (bin jetzt ein wenig verunsichert wegen deines Lösungsweges)

              public class UserComparator implements Comparator {  
                private String             orderBy;  
                public static final String ORDERBY_NAME= "name";  
                public static final String ORDERBY_NUMBER   = "number";  
                
                public UserComparator(String attribute) {  
                  this.orderBy = attribute;  
                
                }  
                public int compare(Object o1, Object o2) {  
                  if (o1 != null && o2 != null && orderBy != null && o1 instanceof User  
                      && o2 instanceof User) {  
                    if (ORDERBY_NUMBER.equals(orderBy)) {  
                      return ((User) o1).getNumber().compareTo(((User) o2).getNumber());  
                    }  
                     else if (ORDERBY_NAME.equals(orderBy)) {;  
                      return ((User) o1).getNumber().compareTo(((User) o2).getNumber());  
                    }  
                  }  
                  return 0;  
                }  
              }
              

              liebe Grüße aus Berlin
              lina-

              --
              Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
              1. Hallo lina und MrWurf,

                Mit Hashing zu arbeiten ist sicher sinnvoll, spätestens dann, wenn es ein paar Objekte mehr sind. Wenn man equals und hashCode ordentlich implementiert hat, kann man auch einfach alle Objekte in ein HashSet schieben.

                Zu Deiner (MrWurf) Anmerkung, dass Du ungern equals überschreibst: Natürlich muss man da aufpassen. Equals sollte man nur dann überschreiben, wenn die Objekte wirklich immer als gleich anzusehen sind. Das ist aber natürlich dann der Fall, wenn sie das selbe reale Objekt repräsentieren (wie in dem Fall eben die Bestellung). Man kann sich dann natürlich noch fragen, ob es überhaupt notwendig ist, dass es mehrere solche Objekte gibt. Es ist ja auch schon problematisch, die Objekte immer zu synchronisieren.
                Equals so zu überschreiben, dass es auf sich ändernden Eigenschaften beruht, ist eigentlich immer etwas problematisch, weil plötzlich zwei Objekte gleich sein können, die es vorher nicht waren. Das führt natürlich mit entsprechenden Datenstrukturen zu problemen (z.B. Hashtabellen)

                Dieser Sachverhalt ist mir bei den User-Objekten über den Weg gelaufen - aber gelöst habe ich ihn anders.

                Genau in dem Fall ist ein Comparator sinnvoll. Comparable zu implementieren ergibt eigentlich nur für eine irgendwie universelle Ordnung sinn. (z.B. für Datumsobjekte).

                Ein paar kleine Anmerkungen zu Deiner Comparator-implementierung:

                • Ich nehme an, Du musst noch Java 1.4 verwenden? Mit 1.5 geht das nämlich wesentlich eleganter.
                • Du verwendest die Konstanten ORDERBY_*. Üblicherweise werden da nur ints verwendet. Da kann man dann z.B. auch nen switch() verwenden, ist aber auch so ok.
                • Wenn ein Objekt null ist oder von einem anderen Typ, ist es gleich zu jedem anderen Objekt. Ich würde weder auf null noch auf den Typ prüfen sondern einfach den vergleich machen. Die Spezifikation von Comparator lässt es meines Wissens explizit zu, dass NullPointerExceptions oder ClassCastExceptions geworfen werden, wenn kein sinnvoller Vergleich möglich ist. Man sollte die Exceptions in dem Fall natürlich dokumentieren.
                  So wird die Implementierung weniger umständlich und es gibt einen Fehler, wenn man mit dem Comparator etwas vergleicht, wozu er nicht gedacht ist.

                Die Java 1.5 implementierung sähe so aus:

                  
                public class UserComparator implements Comparator<User> {  
                  
                  public enum OrderBy {NAME, NUMBER};  
                  
                  private final OrderBy orderBy;  
                  
                  public UserComparator(OrderBy orderBy) {  
                    this.orderBy = orderBy;  
                  }  
                  
                  public int compare(User u1, User u2) {  
                    switch(orderBy) {  
                      case NAME:  
                        return u1.getName().compareTo(u2.getName());  
                      case NUMBER:  
                        return u1.getNumber().compareTo(u2.getNumber());  
                    }  
                    throw new Error("Implementation error.");  
                  }  
                  
                }  
                
                

                Grüße

                Daniel

                1. moin Daniel :)

                  Ein paar kleine Anmerkungen zu Deiner Comparator-implementierung:

                  • Ich nehme an, Du musst noch Java 1.4 verwenden? Mit 1.5 geht das nämlich wesentlich eleganter.

                  Ja leider. Noch ist zu viel zu basteln als dass eine Umstellung auf 1.5 denkbar wäre. Es ist allerdings angedacht, dass die Umstellung Ende des Jahres erfolgen soll. Erfahrungsgemäß ist im Winter weniger los, so dass ich auch die Zeit dafür habe ;)

                  • Du verwendest die Konstanten ORDERBY_*. Üblicherweise werden da nur ints verwendet. Da kann man dann z.B. auch nen switch() verwenden, ist aber auch so ok.

                  Das werde ich auf jeden Fall mit übernehmen. Ich lege viel Wert auf eleganten Code.

                  [Exceptions]

                  So wird die Implementierung weniger umständlich und es gibt einen Fehler, wenn man mit dem Comparator etwas vergleicht, wozu er nicht gedacht ist.

                  hmmm - das ist eine Überlegung wert. Aber dann muss ich die natürlich bei jeder Verwendung sinnvoll abfangen. Ich denke das kommt auf die "nice-to-have"-Liste (die mittlerweile länger ist als die "must-have"-Liste)
                  Ich sehe die Gefahr, dass ich mich langsam mit den vielen Exceptions verheddere ;) da muss ich unbedingt Ordnung reinbringen.

                  liebe Grüße aus Berlin
                  lina-

                  --
                  Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
                  1. Hallo lina,

                    hmmm - das ist eine Überlegung wert. Aber dann muss ich die natürlich bei jeder Verwendung sinnvoll abfangen.

                    Nein, das sind RuntimeExceptions. Die musst Du nicht abfangen und es ist auch meist nicht sinnvoll. Du fängst ja auch keine ArrayIndexOutOfBoundsException ab, wenn Du weißt, dass die nicht auftreten darf (was eigentlich immer der Fall ist).
                    Der Comparator kann eben nur bestimmte Objekte vergleichen. Wenn man ihn anders verwendet als spezifiziert, kracht es eben. Der unterschied ist, dass es mit einer RuntimeException kracht und nicht damit, dass irgendwie doch was getan wird, was dann vielleicht irgendwo zu Fehlern führt.
                    Im übrigen kann man natürlich auch beweisen, dass Deine implementierung der Spezifikation widerspricht ;-)

                    null ist bei Dir gleich jedem anderen Objekt.
                    Seien a und b zwei Objekte für die gilt a < b.
                    Es gilt a = null und b = null. Und folglich a = b was offensichtlich ein Widerspruch ist.
                    Das gleiche Spielchen kann man natürlich mit Objekten anderen Typs machen. Wenn man also eine Ordnung mit allen Objekten und null definieren will, so müsste man z.B. festelegen: Alle anderen Objekte und null sind untereinander gleich und kleiner als User-Objekte.
                    Darauf würde dann auch eine Sortierung wieder funktionieren, aber das ist meiner Meinung nach einfach zu umständlich.

                    Dieses beharren auf die Einhaltung solcher Axiome ist natürlich ein bisschen akademisch, Dein System funktioniert wahrscheinlich auch so. Aber ich finde, man bekommt bessere und übersichtlichere Software, wenn das berücksichtigt.

                    Grüße

                    Daniel

                    1. moin Daniel :)

                      null ist bei Dir gleich jedem anderen Objekt.
                      Seien a und b zwei Objekte für die gilt a < b.
                      Es gilt a = null und b = null. Und folglich a = b was offensichtlich ein Widerspruch ist.

                      Ich war in boolscher Algebra noch nie so fit - das musst du mir näher erklären...

                      wir nehmen an a und b sind zwei Objekte von denen a kleiner sein soll als.
                      Dummerweise sind während der Überprüfung auf Gleichheit aber beide nicht initialisiert (also null). Wie willst du dann noch sicherstellen, dass a<b ist?

                      Für mich ist es eigentlich eindeutig: wenn beide Objekte null sind - sind sie gleich (ähm... man könnte auch sagen "gleich wenig vorhanden" *g*).

                      Ich finde die Logik muss den Sonderfall "beide Objekte null" mit berücksichtigen und kann sich in diesem speziellen Fall nicht mehr auf die gegebene Aussage a<b stützen. ("nichts" kann nicht kleiner oder größer sein als "nichts").

                      liebe Grüße aus Berlin
                      lina-

                      --
                      Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)
                      1. Hallo lina,

                        Ich hab < und = bezüglich Deines Comparators gemeint. Ich kann das nochmal anders schreiben:

                        Sei c ein UserComparator, a und b zwei Objekte mit c.compare(a,b) < 0
                        Mit Deiner Implementierung gilt c.compare(a, null) == 0 und c.compare(n, null) == 0. Da c.compare(null, null) == 0 folgt daraus mit der Spezifikation von compare: c.compare(a, b) == 0 und somit ein Widerspruch.
                        Auf Deutsch: Da alle Objekte für Deinen  Comparator gleich null sind, müssen sie auch untereinander gleich sein.
                        Das alles hat eigentlich nichts mit Boolscher Algebra sondern nur mit den Axiomen von Ordnungs- und Äquivalenzrelationen zu tun. compare definiert im Prinzip solche Relationen.
                        Die zu erfüllenden Bedingungen sind auch alle in der API-Spezifikation aufgeführt: < http://java.sun.com/j2se/1.5.0/docs/api/java/util/Comparator.html#compare(T,%20T)>

                        Für mich ist es eigentlich eindeutig: wenn beide Objekte null sind - sind sie gleich (ähm... man könnte auch sagen "gleich wenig vorhanden" *g*).

                        Ja, es geht nicht um den Fall, dass beide null sind, sondern dass nur eines von beiden null ist.

                        Grüße

                        Daniel

                        1. moin Daniel :)

                          Für mich ist es eigentlich eindeutig: wenn beide Objekte null sind - sind sie gleich (ähm... man könnte auch sagen "gleich wenig vorhanden" *g*).
                          Ja, es geht nicht um den Fall, dass beide null sind, sondern dass nur eines von beiden null ist.

                          hups... davon bin ich aber ausgegangen.
                          Unter dem Aspekt, dass nur ein Objekt null ist, macht das natürlich wieder Sinn.
                          Werde ich heut abend mal überdenken.

                          liebe Grüße aus Berlin
                          lina-

                          --
                          Self-Code: ie:% fl:( br:^ va:) ls:/ fo:| rl:( ss:) de:] js:| mo:)