PDA

View Full Version : HashMap problems


bauhsoj
03-24-2005, 12:42 AM
I keep receiving errors from NetBeans 4.0 when I try to get information from a HashMap. Below is the class I am using for this:

import java.text.NumberFormat;
import java.util.*;

public class ItemRunner {
public static String[] aItemID = {"1234","4567","7890"};
public static String[] aItemKeyMap = {"name","price","descr"};
public static Map mItemList = new HashMap();
public static Map mItem = new HashMap();

public static void ItemRunner() {
// Create the Item info.
String[][] aItems = {{"Coat","129.95",
"Coat description"
},
{"Gloves","28.99",
"Gloves description"
},
{"Earmuffs","14.50",
"Earmuff description."
}
};

// Fill the Item HashMaps.
for (int i=0; i<aItemID.length; i++) {
for (int n=0; n<aItemKeyMap.length; n++)
mItem.put(aItemKeyMap[n], aItems[i][n]);
mItemList.put(aItemID[i], mItem);
mItem.clear();
}
}

public static String getItem(int iUID, String sAttribute) {
// Determine what Item to return.
String sUID = Integer.toString(iUID);
Map mItemByID = new HashMap();
if (mItemList.containsKey(sUID))
mItemByID = mItemList.get(sUID);

// Determine which Item attribute to return.
String sItemValue = "";
if (mItemByID.containsKey(sAttribute))
sItemValue = mItemByID.get(sAttribute);

// Return the results.
if (!sItemValue.equalsIgnoreCase(""))
return sItemValue;
else
return "0";
}
}


Each time I try to use the get() method on mItemList or mItemByID I am met with an incompatible type warning by NetBeans.

Any idea why the above might not work?

cfc
03-24-2005, 01:30 AM
Where are aItemID and aItemKeyMap defined? 4 of the 6 errors are caused by the absence of those symbols.

The incompatible types errors are being caused by not casting Objects to HashMaps and Strings on lines 35 and 40, respectively. You can get around this with generics in Java 1.5 but that's only useful if you can guarantee that the only Java version this will be run on is 1.5.

I'm not going to speculate what aItemID and aItemKeyMap are (well, I'm not going to post my speculation at least) but here's the getItem method fixed with just a couple of casts: :)

public static String getItem(int iUID, String sAttribute) {
// Determine what Item to return.
String sUID = Integer.toString(iUID);
Map mItemByID = new HashMap();
if (mItemList.containsKey(sUID))
mItemByID = (Map)mItemList.get(sUID);

// Determine which Item attribute to return.
String sItemValue;
if (mItemByID.containsKey(sAttribute))
sItemValue = (String)mItemByID.get(sAttribute);

return sItemValue;

}

bauhsoj
03-24-2005, 03:36 AM
Where are aItemID and aItemKeyMap defined? 4 of the 6 errors are caused by the absence of those symbols.

I added those to my original code posting. I simply forgot to copy them from the original code. They were two String arrays.

cfc
03-24-2005, 04:18 AM
Well with this code, the only error left is that sItemValue might not have been initialized because it's only initialized in an if structure before it's returned so you need to add an else clause to the end of getItem. I assumed that aItemID and aItemKeyMap were supposed to be aProductID and aProductKeyMap.


import java.text.NumberFormat;
import java.util.*;

public class ItemRunner {
public static String[] aProductID = {"1234","4567","7890"};
public static String[] aProductKeyMap = {"name","price","descr"};
public static Map mItemList = new HashMap();
public static Map mItem = new HashMap();

public static void ItemRunner() {
// Create the Item info.
String[][] aItems = {{"Coat","129.95",
"Coat description"
},
{"Gloves","28.99",
"Gloves description"
},
{"Earmuffs","14.50",
"Earmuff description."
}
};

// Fill the Item HashMaps.
for (int i=0; i < aProductID.length; i++) {
for (int n=0; n < aProductKeyMap.length; n++)
mItem.put(aProductKeyMap[n], aItems[n]);
mItemList.put(aProductID[i], mItem);
mItem.clear();
}
}

public static String getItem(int iUID, String sAttribute) {
// Determine what Item to return.
String sUID = Integer.toString(iUID);
Map mItemByID = new HashMap();
if (mItemList.containsKey(sUID))
mItemByID = (Map)mItemList.get(sUID);

// Determine which Item attribute to return.
String sItemValue;
if (mItemByID.containsKey(sAttribute)) // sItemValue is only defined on this condition which the java compiler considers an error.
sItemValue = (String)mItemByID.get(sAttribute);

return sItemValue;

}
}


Is there a reason everything needs to be static?

bauhsoj
03-24-2005, 04:25 AM
I applied the type casting and that eliminated the errors but I am somewhat confused about the reason.

I thought that the value returned from a HashMap was the value of the type that was originally stored in it. For instance, if I have a String variable and am retrieving a String value why would I need to type cast it?

Also, why would a HashMap variable need to be type cast into a Map when the value it returns is being stored in a variable that is already declared as a HashMap?

bauhsoj
03-24-2005, 04:32 AM
Well with this code, the only error left is that sItemValue might not have been initialized because it's only initialized in an if structure before it's returned so you need to add an else clause to the end of getItem. I assumed that aItemID and aItemKeyMap were supposed to be aProductID and aProductKeyMap.

I just changed the naming of some variables and forgot to make those consistant when I resubmitted the updated code. :p

Is there a reason everything needs to be static?

I am actually still learning Java and trying to get the hang of stuff. Every time I declare a class variable as "public" instead of "public static" I get the error: non-static variable cannot be referenced from a static context.

cfc
03-24-2005, 05:00 AM
In the J2SE 1.4 API spec, you'll see that the get() method of every Collection (I think) returns an Object. You must then downcast the Object to the type it's supposed to be which can be unsafe at times. This is different in Java 1.5 where generics (templates) were introduced and you can add type-specific information to the declaration of each Collection. The older approach still works in 1.5 of course and the documentation is still good, just recognize that where it says something returns E, K, V, T, etc. it means that it can be of a specified type. For backwards compatibility purposes, the E and T probably default to Object if a type is not given... not sure about that though.

You can't reference non-static class members from a static context, but you can create class instances from a static context. I don't think any of that class needs to be static, if you're using a main() method within the class for testing purposes just create an instance of the class within main() and you don't have to make anything static :) .

If I'm right and you're using a main() within the class for testing, here's a slightly refined OOP approach:

import java.text.NumberFormat;
import java.util.*;

public class ItemRunner {
private String[] aProductID = {"1234","4567","7890"};
private String[] aProductKeyMap = {"name","price","descr"};
private Map mItemList = new HashMap();
private Map mItem = new HashMap();

public ItemRunner() {
// Create the Item info.
String[][] aItems = {{"Coat","129.95",
"Coat description"
},
{"Gloves","28.99",
"Gloves description"
},
{"Earmuffs","14.50",
"Earmuff description."
}
};

// Fill the Item HashMaps.
for (int i=0; i < aProductID.length; i++) {
for (int n=0; n < aProductKeyMap.length; n++)
mItem.put(aProductKeyMap[n], aItems[n]);
mItemList.put(aProductID[i], mItem);
mItem.clear();
}
}

public String getItem(int iUID, String sAttribute) {
// Determine what Item to return.
String sUID = Integer.toString(iUID);
Map mItemByID = new HashMap();
if (mItemList.containsKey(sUID))
mItemByID = (Map)mItemList.get(sUID);

// Determine which Item attribute to return.
String sItemValue = "0";
if (mItemByID.containsKey(sAttribute)) {
sItemValue = (String)mItemByID.get(sAttribute);

return sItemValue;
}

public static void main (String[] args)
{
ItemRunner myItemRunner = new ItemRunner();
// Do your tests...
}
}

The changes are based on my estimation of your implementation, so I'm aware that I might be wrong. I don't know if you need any properties to be public or methods (other than main of course) to be static. If you don't need the properties to be public, it's considered good OOP practice to make them private (or protected depending on the situation) and use get and set methods to return or modify them.

There's still the problem of sItemValue being conditionally initialized of course.

bauhsoj
03-24-2005, 04:34 PM
There's still the problem of sItemValue being conditionally initialized of course.

I corrected that as well in the original post by adding:// Return the results.
if (!sItemValue.equalsIgnoreCase(""))
return sItemValue;
else
return "0";

Thanks for all of the input! That really helped clear some stuff up for me. :thumbsup: :D

bauhsoj
03-25-2005, 06:11 PM
Okay, I got most of my program worked out but all of the HashMaps are empty and the getItems() method always returns a zero (0) indicating sProductValue is empty. I tried doing System.out.println("ItemListValues: "+mItemList.values()); to see what had been stored but I get an empty set of brackets [ ].

Any idea what might be wrong? :confused: