hashmap probleem

Status
Niet open voor verdere reacties.

UnrealEd

Nieuwe gebruiker
Lid geworden
9 mei 2006
Berichten
3
gegroet allen,

ik ben redelijk nieuw in de java-wereld, en ook op dit forum :), en ik had een vraag over hashMap.
Ik moet voor de unief een werkje maken, en ik maar daarin gebruik van een hashmap om gegevens op te slaan. de values van de hashmap zijn echter van een verschillend data type. zoals iedereen weet retourneert een hashmap bij de methode hashmap.get(key) een Object.
weet er iemand soms een manier om toch het juist data type terug te krijgen?

vb:
Code:
import java.util.HashMap;

HashMap hmap = new HashMap();
hmap.put("bericht", "hello world");
hmap.put("id", 1);

hmap.get("bericht"); // zou een string moeten teruggeven i.p.v een Object
hmap.get("id"); // zou een int moeten teruggeven i.p.v een Object

er werd mij iets verteld over generics, maar van wat ik heb kunnen afleiden, verergert dit mijn probleem alleen maar, omdat je echt specifieert voor de totala hashmap wat de inputs en outputs moeten zijn. of begrijp ik dit verkeerd?

hartelijk dank,
met vriendelijke groet,
UnrealEd
 
Als je zeker weet dat je een string terug krijgt dan kan je dit op de volgende manier doen:

String test = (String) hmap.get("bericht");

Wat betreft je integer gaat het helemaal fout. Je kan namelijk geen int in een hashmap voeren. Hiervoor moet je deze in een Integer object stoppen.

hmap.put("id",new Integer(1));
Integer getal = (Integer) hmap.get("id");
int id = getal.intValue();

of natuurlijk in 1 regel:
int id = ((Integer) hmap.get("id")).intValue();


Let wel op dat wanneer je het verkeerde datatype gebruikt je dan een class cast exception zal krijgen. Dat tussen haakjes zetten van het datatype heet dan ook casting. Met het casten zeg je tegen java dat je al weet dat je dat datatype moet verwachten.
 
Wat u ook kunt gebruiken is Generics... dit is nieuw in Java 1.5 ( 5.0) of het voor een hashmap werkt weet ik niet, maar voor Priority Queue's/Stacks enz werkt het wel.

in dit voorbeeldje geef ik een paar regels weer, met daarin een priority queue met behulp van generics. Met behulp van deze code sorteer ik een wk-poule op aantal punten enz. Hierbij maak ik gebruik van een Priority Queue waar ik een Object Land op zet.
Code:
public void sorteerPoule(){
    PriorityQueue<Land> pq = new PriorityQueue<Land>();
    for (int i=0; i<4; i++){
        pq.add(team[i]);
    }
    for (int i=3; i>=0; i--){
        team[i] = pq.remove();
    }
}

zoals u ziet geef ik bij het aanmaken van de PriorityQueue een type mee. Er mogen dus ook geen andere Objecten op de PriortyQueue gezet worden. Dus bij uw probleem zou u gebruik moeten maken van 2 hashmaps.
Bij de code team = pq.remove() hoeft dus niet gecast te worden naar het type Land omdat het al bekend is dat er alleen objecten van het type Land in de priorityqueue zitten..
 
Laatst bewerkt:
hello,

ik weet dat je generics kan gebruiken, maar dat verhelpt mijn probleem niet.
ik zou verschillende datatypes in een hashmap moeten kunnen steken.
dus als ik een int erin steek, dan wil ik ook een int terugkrijgen, steek ik er een string in, wil ik een string terug krijgen. Ik heb ondertussen ook gevonden dat het gewon niet mogelijk is omdat je in java altijd een return-type moet teruggeven als je een methode hebt gemaakt. bijgevolg wordt er altijd eenzelfde datatype teruggestuurd, en kan ik dus nooit verschillende datatypes uit een hashmap halen, zonder ze eerst te casten.

toch bedankt in ieder geval,
Groeten,
UnrealEd
 
Maar dat is toch geen probleem? Je maakt er eerst een Object van, generieker kan het niet en vervolgens test je of je hem verder kan casten:

Object test = (Object) hmap.get("id");
if ( test instanceof Integer ) { enzovoorts

via instance methoden kan je ook de ware classe wel achterhalen.
 
ja dat klopt, maar ik krijg die hashmap terug uit een andere methode, waarin een user enkele gegevens heeft moeten invullen (met verschillend datatype). ik gebruik deze methode in m'n andere klasse wel 5 keer, de hashmap heeft een lengte van 15-20 elementen, en als ik die elke keer opnieuw moet gaan casten wanneer ik deze hashmap ontvang, verlies ik zowaar 5 * 20 regels. en dit zijn eigenlijk overbodig gecodeerde zaken.

ik begrijp heel goed dat je strikt wil kunnen programmeren, maar is dit niet een beetje te strikt? ik bedoel: kijk naar flash AS, dat is ook strikt, maar die maken er geen probleem van of je in Arrays strings, objecten, integers, of eender wat in steekt. Alle elementen hebben daar hun eigen type, en kunnen dus ook eruit gehaald worden zonder typecasting.

Ik heb het ook gevraagd aan een van de assistenten, en daar kreeg ik het antwoord dat die typecasting het eenvoudiger maakt voor de compiler, maar dit vind ik toch wel de belachelijkste reden die ik gehoord heb tot nog toe. Het zou niet moeten zijn dat de programmeur zich in bochten moet wringen, maar de compiler

Groeten,
UnrealEd
 
Tja love it or hate it, java is erg strikt. Het casten is nodig niet om het makkelijker te maken, maar juist omdat de striktheid in java gewenst werd door zijn programmeurs.

Wat in java wordt voorkomen is dat op een bepaald object een methodenaam wordt aangeroepen die niet voor dat object bestaat. Wanneer je niet weet wat voor soort waarde er je variabele/Object zit kan dit nooit gecontroleerd worden (neem bijvoorbeeld een afrondfunctie voor een String, dit zal je niet kunnen aanroepen in java maar bijvoorbeeld wel in perl)

Goed ik krijg wel iets meer inzicht in wat je probeert te doen. Waarom maak je geen WrapperClass? Dus een eigen Classe met een String en een Integer als variabele en stop je alleen objecten van die wrapperclass in je hashmap. Vervolgens kan je deze er altijd uithalen omdat je moet casten naar die wrapperclass en vervolgens kan je in die classe wel een methode maken van getIntValue() (die bijvoorbeeld standaard 0 terug geeft als je in dat object een string had opgeslagen)

Voorbeeldje:
PHP:
public class Wrapper {
    private int number;
    private String text;
    private boolean isI;
    private boolean isText;
    
    public Wrapper() {
    }
    
    public void setText(String text) {
        //het wordt een tekst dus geen integer
        isI = false;
        //maar wel een tekst
        isText = true;
        this.text = text;
    }

    public void setNumber(int number) {
        //het wordt een getal dus geen tekst
        isText = false;
        //maar wel een getal
        isI = true;
        this.number = number;
    }
    
    public boolean isNumber() {
        return isI;
    }
    
    public boolean isText() {
        return isText;
    }
    
//de getter kan je bijvoorbeeld uitrusten met een exceptionhandling
    public String getText() throws WrongTypeException {
        if ( !isText() ) {
            throw new WrongTypeException("This object is not a String");
        }
            return text;
    }
//maar je kan ook gewoon een lege string teruggeven wanneer het geen string was bijvoorbeeld    
    public String getText() {
        if ( !isText() ) {
            return "";
        }
        return text;    
    }
//ook zo voor je getalletje een getter maken met een exceptionhandling of zonder   
    public String print() {
        String total = "";
        if ( isText() ) { total = text; }
        if ( isNumber() ) { total = total + getNumber(); }
        return total;
    }
}
Deze wrapper bied je alle mogelijkheden. Je kan bijvoorbeeld direct naar het scherm printen via het print commando, je kan precies opvragen wat voor type het is. Dus gewoon alleen objecten van deze wrapper in je hashmap gooien en je hebt nooit een probleem. En zo is het bedoeld in java :cool:
 
Wat u ook kunt proberen is het schrijven van een eigen HashTable classe... en de afhandeling binnen deze klasse te laten gebeuren.... Of aan de hand van de key bepalen welk data type er terug komt, maar onder het casten komt u niet uit...
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan