Avatar billede _darkstar_ Nybegynder
14. september 2003 - 18:31 Der er 20 kommentarer og
1 løsning

Semantisk forskel på equals ifm. arrays kontra ArrayList - hvorfo

Hvis jeg har to arrays:

  String a[] = {"x","y"};
  String b[] = {"x","y"};

så giver a.equals(b) false fordi at der er tale om to forskellige objekter.

Hvis jeg har to ArrayLists:

  ArrayList a = new ArrayList();
  ArrayList b = new ArrayList();

  a.add("x");
  a.add("y");
  b.add("x");
  b.add("y");

så giver a.equals(b) true fordi at indholdet i de to lister er identisk.

Hvorfor har man valgt at lave sproget sådan? Er det generelt sådan at det kun er arrays som har en anden semantisk betydning af equals, eller er der flere eksempler på dette?

Er der en tekst fra SUN som forklarer hvornår man skal sammenligne værdier og hvornår man skal sammenligne objekt-identitet, samt hvad det er meningen at equals skal gøre?

Jo flere svar med officielle referencer, jo flere points vil jeg give.
Avatar billede arne_v Ekspert
14. september 2003 - 18:35 #1
Det er det samme med String (== tester om det er samme object, equals tester
om det er samme streng).

Det vil være det samme for enhver klasse som implementerer equals.
Avatar billede arne_v Ekspert
14. september 2003 - 18:36 #2
Object equals API doc forklarer lidt:

public boolean equals(Object obj)

    Indicates whether some other object is "equal to" this one.

    The equals method implements an equivalence relation:

        * It is reflexive: for any reference value x, x.equals(x) should return true.
        * It is symmetric: for any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
        * It is transitive: for any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
        * It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified.
        * For any non-null reference value x, x.equals(null) should return false.

    The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any reference values x and y, this method returns true if and only if x and y refer to the same object (x==y has the value true).

    Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
Avatar billede arne_v Ekspert
14. september 2003 - 18:37 #3
Alle klasser arver fra Object d.v.s. at hvis man ikek gør noget specielt så
er equals det samme som ==.

Men almindeligvis er det hensigtsmæssigt at kode en equals der tester
mere på indholdet.

Ovenstående beskriver "spille reglerne" for at lave en equals.
Avatar billede arne_v Ekspert
14. september 2003 - 18:38 #4
C# har iøvrigt præcis det samme. Metoden hedder bare Equals (med stort E).
Avatar billede arne_v Ekspert
14. september 2003 - 18:45 #5
ArrayList er en af de klasser der har implementeret sin egen equals.

equals

public boolean equals(Object o)

    Compares the specified object with this list for equality. Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).) In other words, two lists are defined to be equal if they contain the same elements in the same order.

    This implementation first checks if the specified object is this list. If so, it returns true; if not, it checks if the specified object is a list. If not, it returns false; if so, it iterates over both lists, comparing corresponding pairs of elements. If any comparison returns false, this method returns false. If either iterator runs out of elements before the other it returns false (as the lists are of unequal length); otherwise it returns true when the iterations complete.
Avatar billede arne_v Ekspert
14. september 2003 - 18:48 #6
Så er det store spørgsmål vel: hvorfor har de lavet det sådan ?

Jeg kender faktisk ikke nogle gode kilder til det.

Men man kan jo deducere lidt i bedste Sherlock stil:
* Java understøtter ikke operator overload
* det vil ofte være nødvendigt at sammenligne indhold af objekter
logisk konklusion:
* man skal have en metode til det
sund fornuft siger at:
* den metod ebør hedde det samme i alle klasser
og så er der vel kun tilbage at vælge navnet.

Og SUN valgte altså "equals".
Avatar billede arne_v Ekspert
14. september 2003 - 18:48 #7
Og det må være et svar.
Avatar billede _darkstar_ Nybegynder
14. september 2003 - 19:35 #8
De ting du skriver har jeg allerede tænkt mig frem til (og læst iøvrigt) - jeg har brug for at vide hvorfor.

På sin vis kan jeg godt se at Object-klassens equals-implementation er den eneste der giver mening. Ellers skulle den slet ikke være der, eller Object-klassen skulle være abstrakt (det kunne den vel sagtens være). Det ville under alle omstændigheder give udviklere et dårligt udgangspunkt for at skrive deres egne klasser, da de i så fald partout ville være nødt til at implementere deres egen equals-metode (som så iøvrigt kunne virke på lige så mange forskellige måder som der er udviklere).

På den anden side ser det ud til at SUN godt kunne have lavet et alternativ hvor equals-metoden lavede en parvis sammenligning af sine attributter for at finde resultatet. En metode som man burde kunne nedarve (i hvert fald i de nyere versioner af Java).

Det er i hvert fald inkonsistent at objekt-identitets-sammenligning på den måde er blandet sammen med værdi-sammenligning. Jeg havde nok fundet det noget mere elegant hvis man havde skelnet mere imellem de to.

Med ArrayList kan man vel altid køre en

(Object(a)).equals(b)

for at finde ud af om a og b repræsenterer den samme instans, men det er bare ikke indlysende med mindre man kender hele baggrunden.

...men som skrevet ovenfor: jeg savner kilder.
Avatar billede _darkstar_ Nybegynder
14. september 2003 - 19:37 #9
Ups...

(Object(a)).equals(b)

skulle være

((Object)a).equals(b)
Avatar billede arne_v Ekspert
14. september 2003 - 19:40 #10
Med ArrayList som alle andre objekter laver du bare a==b for atteste om det er
samme objekt.
Avatar billede arne_v Ekspert
14. september 2003 - 19:41 #11
De kunne godt have laver Object's equals så den sammenlignede members
via reflection.

Men det vil være alt alt for langsomt.
Avatar billede arne_v Ekspert
14. september 2003 - 19:43 #12
Og den skal være på Object fordi en lang række klasser bl.a.
ArrayList opererer på Object.
Avatar billede arne_v Ekspert
14. september 2003 - 19:46 #13
De har været nødt til at gøre det på den måde.

Og en god indikation af at det er bedst choice er at MS valgte at lave det
på samme måde i C#.
Avatar billede _darkstar_ Nybegynder
14. september 2003 - 21:16 #14
Jeg kan godt forestille mig at en equals-metode som sammenligner attributter vil blive noget langsommere, men endnu vigtigere ville man miste muligheden for at checke om variable indeholder det samme objekt, hvilket nok ville være meget rart at have.

Iøvrigt er jeg rimeligt overbevist om at de tidlige versioner af sproget ikke rigtig havde faciliteter til at lave en attribut-vis sammenligning uden at det ville blive noget bøvl. F. eks. reflection er først kommet til for ganske nylig.

Alt det har jeg tænkt over. Jeg savner konkrete referencer fra SUN, hvor de forklarer hvad de tænkte på, da det blev lavet sådan.
Avatar billede arne_v Ekspert
14. september 2003 - 21:32 #15
java.lang.reflect har været em del af Java siden version 1.1 !
Avatar billede arne_v Ekspert
14. september 2003 - 21:34 #16
Der står lidt af det samme som allerede er nævnt her:

http://java.sun.com/docs/books/tutorial/java/javaOO/objectclass.html
Avatar billede arne_v Ekspert
14. september 2003 - 21:41 #17
der er iøvrigt en interssant men langggg......... diskussion her:

http://www.ibiblio.org/javafaq/questions/07031998.html
Avatar billede arne_v Ekspert
14. september 2003 - 21:54 #18
Det virker som at Arnold og Gossling aldrig har udtalt sig om hvorfor.
Ihvertfald ikke noget der er på nettet.

Bloch bruger 10 sider i hans "Effective Java" på at beskrive hvordan
man bruger equals og hvordan man ikke gør det. Men heller ikke han
komemr så meget ind på hvorfor.
Avatar billede logical Nybegynder
15. september 2003 - 14:25 #19
Der er to former for sammenligninger, som er interessante:

Object Equality (Er det det samme objekt)

Data Equality (Indeholder to objekter, samme data).

Klasse String laver data equality, mens f.eks. Object laver object equality.
Klassen ArrayList laver data equality, mens f.eks. [] laver object equality.

Baggrundene er lidt vage og usikre, men bunder jo typisk i, at du skal genfinde noget igen.

Object Equality er ligesom den generelle. Det objekt, som indeholder nogle specifikke data er netop det objekt, og derfor er den eneste, som den ved den er lig med er sig selv.

(Jeg påstår f.eks. også, at jeg selv er et unikt væsen, selv om andre siger, at jeg er snydt ud af næsten på min far :-)

I et objektorienteret paradigme er hvert enkelt objekt unikt, og har sin egen identitet. Det er et tilfælde, hvis den har lighedspunkter med andre.

Hvis du har klassen person, skal beslutningen om to instanser er ens tages af programmøren, for kan 2 mennesker hedde det samme uden at være den samme? Hvis du f.eks. har fundet Hans Jensen i en liste, retter hans adresse, og skal gemme den igen, skal listen lige have en mulighed for at finde referencen, f.eks. igennem equals.

Identity og equality er meget interessant, når man snakker datastrukturer, hvor f.eks. hashstrukturer vil kræve, at hashcode() og equals() fungerer transitivt.

Men hovedregelen er, at hvis du bruger equals metoden kan du forvente at der af programmøren er udtænkt, hvorvidt identitet er direkte sammenlignelig eller ej, hvilket selvfølgelig står i javadoc for den angivne klasse.
Avatar billede arne_v Ekspert
27. september 2003 - 13:39 #20
Tid at lukke spørgsmålet ?
Avatar billede _darkstar_ Nybegynder
27. september 2003 - 16:03 #21
Jeps.

Logical>>> Jeg synes ikke at det ser ud tila t du har læst mit spørgsmål. jeg ledte ikke efter en forklaring på hvordan equals virker i forskellige situationer, men en (*officiel*) begrundelse for hvorfor.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester