Avatar billede sniperkiller Nybegynder
28. december 2002 - 12:24 Der er 34 kommentarer og
1 løsning

HashCode problemer

Er der en 'Guru' der vil hjælpe en vildfaren Java studerende med at analysere noget kode??
Avatar billede jespernaur Nybegynder
28. december 2002 - 12:31 #1
Du må da vise den kode, hvis du vil have nogen til at kigge på den!
Avatar billede sniperkiller Nybegynder
28. december 2002 - 12:35 #2
Ja men jeg spurgte jo bare først..  ;-)

Jeg skal bruge metoderne equals() og hashCode() og bruge CPRnummer som nøgle.
CPRnummeret skal først castes til en Integer. Gør jeg det rigtigt??
class Studerende
{
    private String Navn;
    private int CPRNummer;  // Skal castes til Integer
    private int Alder;
    public Object[] arr = new Object[10];
   
    public Studerende(String navn, int CPRnummer, int alder)
    {
        this.Navn = navn;
        this.CPRNummer = CPRnummer;
        this.Alder = alder;
    }   
   
    public Integer hashCode()
    {
        Integer nr = (Integer)CPRNummer;
        return nr.hashCode();
    }
/*    public equals()
    {
        ;
    } 
*/     
}
Avatar billede erikjacobsen Ekspert
28. december 2002 - 12:38 #3
Har du overvejet om et CPR-nummer overhovedet kan være i en
int eller Integer ??

Men ellers er den rigtige metode
Integer nr = new Integer(CPRNummer);
Avatar billede erikjacobsen Ekspert
28. december 2002 - 12:40 #4
Iøvrigt skal det jo være
  public int hashCode()

Har oversætteren sagt noget til dit program?
Avatar billede sniperkiller Nybegynder
28. december 2002 - 12:41 #5
Det har jeg ikke nej.
Jeg har overhovedet ikke ret meget styr på det her Hash.
'Arbejder' HashMap ikke som et Array??
Og isåfald hvad er foskellen??
Avatar billede sniperkiller Nybegynder
28. december 2002 - 12:42 #6
Mit fejl output er :
Pro\MyProjects\ADT\ADT\HashStuderende\Studerende.java:18: hashCode() in
Studerende cannot override hashCode() in java.lang.Object; attempting to use incompatible return type
found  : java.lang.Integer
required: int
    public Integer hashCode()
Avatar billede sniperkiller Nybegynder
28. december 2002 - 12:45 #7
Okay med din rettelse gik det. Hurra.
Du er jo en Guru. TAK!
Avatar billede erikjacobsen Ekspert
28. december 2002 - 12:46 #8
Ved du hvor mange bits der er i en int eller Integer?
Avatar billede sniperkiller Nybegynder
28. december 2002 - 12:47 #9
DVS. public int hashCode()
    {
        Integer nr = new Integer(CPRNummer);
        return nr.hashCode();
    }
Men det er returnerer er jo Integer object ikke?
Men min retur type er en int, hvordan det?
Avatar billede sniperkiller Nybegynder
28. december 2002 - 12:47 #10
32 mener jeg....
Avatar billede erikjacobsen Ekspert
28. december 2002 - 12:51 #11
Ja, så det største positive tal, der kan opbevares
er 2 opløftet til 31, sådan ca. dvs. ca

  2.150.000.000

kan du se et problem i det?

Du returnerer den type metode hashCode i Integer objektet
returnerer. Og det er en int.
Avatar billede sniperkiller Nybegynder
28. december 2002 - 12:56 #12
Nej. Jeg ved ikke lige hvor du vil hen?? Mener du at et CPR nr har for stor værdi??

Men hvorfor skal Integer Objektet værdi ikke castes til en int værdi?
Sker det helt af sig selv?
Avatar billede erikjacobsen Ekspert
28. december 2002 - 12:57 #13
Du kalder en metode i et Integer objekt. Så er det
metodens returtype, der tæller.

Hvor stort er det største CPR-nummer du kan forestille dig?
Avatar billede sniperkiller Nybegynder
28. december 2002 - 13:02 #14
ja okay så faldt 10-øren.
Nå men så må jeg hellere finde en anden nøgleværdi.

Er det så rigtigt forstået mht. equals()
Hvis jeg indsætter to eller flere objecter(personer) i array kan jeg sammenligne deres nøgleværdier med equals() metoden??
Avatar billede erikjacobsen Ekspert
28. december 2002 - 13:06 #15
Lad os lige tage een ting af gangen. Ja int/Integer er for lille.
Du kunne bruge long/Long - men ret beset er et CPR-nummer ikke
et tal. Du skal aldrig lægge dem sammen fx. Og foranstillede 0'er
forsvinder ved udskrift.

Hvad siger du til et forslag om at lade et CPRnummer være en String ?
Avatar billede sniperkiller Nybegynder
28. december 2002 - 13:09 #16
ja det burde jeg nok lave det om til.
Avatar billede sniperkiller Nybegynder
28. december 2002 - 13:12 #17
jeg kunne jo også bare for nemheds skyld lade cpr bestå af kun de første 6 cifre (i dette eksempel), til jeg lige har forstået hashmap. ;-)
Avatar billede sniperkiller Nybegynder
28. december 2002 - 13:16 #18
Er det her noget du underviser i?
Avatar billede erikjacobsen Ekspert
28. december 2002 - 13:23 #19
Hashmap? Ja, hvis det er for eksemplets skyld  -  og det er det
jo nok - så kan du jo f.x bruge de første 6 cifre.

Equals? Om to objekter er ens kan være en træls affære at checke,
da der kan være mange delvariabler. Så det man plejer at gøre, er
at check de 2 objekters hashcode. Er de forskellige, så er objekterne
også forskellige (ellers er hashCode-metoden lavet forkert). Er de
to hashCode værdier ens, er objekterne MÅSKE ens, og så er man nødt til
at checke om alle delvariabler også er ens.
Avatar billede sniperkiller Nybegynder
28. december 2002 - 13:29 #20
Okay. Jeg snupper lige en bid mad så vender tilbage og prøver det. ;-)
Avatar billede arne_v Ekspert
28. december 2002 - 13:50 #21
hashCode og HashMap har ikke så meget med hinanden gøre
(den sidste bruger kun den første).

Hvis du lader CPR nummeret være en String, så er det nemt både
at lave hashCode og equals.

public int hashCode() {
    return CPRNummer.hashCode();
}

public boolean equals(Object o) {
    if(o instanceof Studerende) {
        return CPRNummer.equals(((Studerende)o).CPRNummer);
    } else {
        return false;
    }
}

Hvis du skal checke diverse ting udfra CPR nummer, så kan jeg du låne
lidt fra følgende kode:

import java.util.*;

public class CPR {
    // format of danish CPR number:
    //  ddmmyy-nnnc
    // where:
    //  dd  = day
    //  mm  = month
    //  yy  = year
    //  nnn = sequence (includes century)
    //  c  = checksum (includes sex)
    private String number;

    // constructor
    public CPR(String number) {
        this.number = number;
    }

    // check validity
    public boolean isValid() {
        int[] ix = { 0, 1, 2, 3, 4, 5, 7, 8, 9, 10 };
        int[] c = { 4, 3, 2, 7, 6, 5, 4, 3, 2, 1 };
        if (number.length() != 11) {
            return false;
        }
        if (number.charAt(6) != '-') {
            return false;
        }
        for (int i = 0; i < 10; i++) {
            if (!Character.isDigit(number.charAt(ix[i]))) {
                return false;
            }
        }
        if (dd() > 31) {
            return false;
        }
        if (mm() > 12) {
            return false;
        }
        if (century() == 0) {
            return false;
        }
        int temp = 0;
        for (int i = 0; i < 10; i++) {
            temp = temp + c[i] * numericValue(number.charAt(ix[i]));
        }
        return ((temp % 11) == 0);
    }

    // check make/female
    public boolean isMale() {
        return odd(numericValue(number.charAt(10)));
    }
    public boolean isFemale() {
        return even(numericValue(number.charAt(10)));
    }

    // get date of birth
    public Date getBirth() {
        int year = yy() + century();
        int mon = mm() - 1;
        int mday = dd();
        GregorianCalendar temp = new GregorianCalendar();
        temp.set(year, mon, mday);
        return temp.getTime();
    }

    // get age
    public int getAge() {
        Calendar now = GregorianCalendar.getInstance();
        Calendar born = new GregorianCalendar();
        born.setTime(getBirth());
        int result;
        result = now.get(Calendar.YEAR) - born.get(Calendar.YEAR);
        if (now.get(Calendar.DAY_OF_YEAR) < born.get(Calendar.DAY_OF_YEAR)) {
            result--;
        }
        return result;
    }
   
    // standard methods
    public int hashCode() {
        return number.hashCode();
    }
    public boolean equals(Object o) {
        if(o instanceof CPR) {
            return number.equals(((CPR)o).number);
        } else {
            return false;
        }
    }

    // get parts
    private int dd() {
        return Integer.parseInt(number.substring(0, 2));
    }
    private int mm() {
        return Integer.parseInt(number.substring(2, 4));
    }
    private int yy() {
        return Integer.parseInt(number.substring(4, 6));
    }

    // calculate century
    private int century() {
        switch (numericValue(number.charAt(7))) {
            case 0 :
            case 1 :
            case 2 :
            case 3 :
                return 1900;
            case 4 :
            case 9 :
                if (yy() < 37)
                    return 2000;
                else
                    return 1900;
            case 5 :
            case 6 :
            case 7 :
            case 8 :
                if (yy() < 37)
                    return 2000;
                else if (yy() > 57)
                    return 1800;
                else
                    return 0;
            default :
                return 0;
        }
    }

    // odd/even
    private static boolean odd(int v) {
        return ((v & 1) == 1);
    }
    private static boolean even(int v) {
        return ((v & 1) == 0);
    }

    // numeric value of char
    private static int numericValue(char c) {
        return (c - '0');
    }
}
Avatar billede arne_v Ekspert
28. december 2002 - 13:52 #22
erik> Jeg forstå ikke dit argument for at bruge hashCode i equals.
Meget ofte vil hashCode jo skulle have fat i alle delvariablene
alligevel. Så jeg kan ikke se gevindsten.
Avatar billede arne_v Ekspert
28. december 2002 - 13:58 #23
Et CPR nummer kan ikke være upakket i en int/Integer, da
de har max. værdi 2.1 milliard mens CPR nummer har max.
"værdi" 3.1 milliard.

Et CPR nummer kan godt være pakket i en int/Integer, da
der kun er 365 millioner forskellige værdier grundet
begrænsninger på dsg og måned.

Men det vil bare være for bøvlet at pakke ind og ud hele
tiden.
Og jeg er ikke engang sikker på, at den pakning er god til hashCode beregning.
Avatar billede erikjacobsen Ekspert
28. december 2002 - 13:58 #24
Der skulle vist have stået "i en hashmap" et par steder, Arne...;)
Avatar billede sniperkiller Nybegynder
28. december 2002 - 14:15 #25
Jeg værdsætter meget den hjælp der gives her, men jeg bliver sgu lidt forvirret!
Arne du skriver:" hashCode og HashMap har ikke så meget med hinanden gøre
(den sidste bruger kun den første)".
Hvad er hashCode og HashMap så????
Er HashMap ikke ligesom et array?
Og hashCode er en metode som HashMap kan bruge for at få returneret en bestemt værdi (ud fra objektet)?
Avatar billede arne_v Ekspert
28. december 2002 - 14:25 #26
hashCode er en funktion som returnerer en numerisk værdi
for et objekt.

HashMap er en data-struktur hvor man kan gemme key-value
pairs i.

HashMap bruger hashCode internt.
Avatar billede arne_v Ekspert
28. december 2002 - 14:28 #27
Og jeg forstår ikke hvor HashMap kommer ind i billedet.

Hvis du vil bruge objekter af typen Studerende som key,
så skal du bruge hashCode og equals for Studerende, men hvad
skal så være value ??

Hvis du vil bruge Studerende som value og CPR nummer som key,
så behøver du ikke bøvle med hashCode og equals for Studerende
(og både Integer og String har dem allerede, så du skal heller
ikke lave dem for CPR nummer).
Avatar billede sniperkiller Nybegynder
28. december 2002 - 14:35 #28
HashMap er nok noget jeg har forvildet ind i hovedet.
Men det er det sidste forslag jeg skal arb. med.
Da dette er min opgave bliver jeg dog nødt til at bøvle med hsahCode og equals:
- Lave en klasse 'Studerende' med nogle passende atributter. (nummer, navn m.v.)
- Overloade metoderne equals() og hashCode() på klassen 'Studerende'. Brug f.eks. cprnummer som nøgle.
- Placere et antal forekomster af 'Studerende' i et array på grundlag af objektets hashCode.
- Genfinde objekterne på grundlag af deres nøgle.
Avatar billede erikjacobsen Ekspert
28. december 2002 - 14:46 #29
De sidste 2 punkter lyder uklare - ved du hvad
der er ment med dem? Skal du lave din egen hashMap?
Avatar billede arne_v Ekspert
28. december 2002 - 14:48 #30
Der lyder nærmest som om du skal lave din egen implementation
af HashMap istedetfor at bruge den der kommer med Java.
Avatar billede sniperkiller Nybegynder
28. december 2002 - 14:50 #31
Det tror jeg også er meningen.
Avatar billede sniperkiller Nybegynder
28. december 2002 - 14:52 #32
Så giver det måske bedre mening (for Jer) med den kode jeg sendte med i starten??
Avatar billede arne_v Ekspert
28. december 2002 - 14:55 #33
Faktisk ikke.

En hash map (java eller din egen) har keys og values.

Hvad er key og hvad er value ?

Umiddelbart skulle jeg tro at CPRNummer var key og Studerende
var value !
Og så behøver du ikke hashCode for Studerende, da man kun skal
hashe keyen ikke value.
Avatar billede sniperkiller Nybegynder
28. december 2002 - 14:58 #34
Det er jeg enig med dig i. Bortset fra de 2 sidste linier.
Det har jeg ikke lige check på.
Avatar billede arne_v Ekspert
28. december 2002 - 15:00 #35
Grundliggende fungerer en hash map som følger:

* man har et array med keys og values
* put kalkulerer en hash af af key og indsætter key-value
  på en position udfra den hash
* get leder efter value udfra key ved at man kalkulerer hash og
  kigger i den position i arrayet

(man skal så lige kunen håndtere situationen med to keys
med samme hash value)

Derfor er det kun hashCode af key der er interessant.
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