Our new Indie Games subforum is now open for business in G&T. Go and check it out, you might land a code for a free game. If you're developing an indie game and want to post about it, follow these directions. If you don't, he'll break your legs! Hahaha! Seriously though.
Our rules have been updated and given their own forum. Go and look at them! They are nice, and there may be new ones that you didn't know about! Hooray for rules! Hooray for The System! Hooray for Conforming!

Help me understand Java generics and type safety

Jimmy KingJimmy King Registered User regular
edited May 2008 in Help / Advice Forum
Alright, so I've got some java. I have a Hashmap which has an integer as the key and a string as the value. To iterate over it I do this:
		Enumeration e = genres.keys();
		while(e.hasMoreElements()) {
			int key = Integer.parseInt(e.nextElement().toString());
			if(genres.get(key).toString().equalsIgnoreCase(genreName)) { 
				return(new Genre(key,conn));
			}
		}

This gives me a warning "Enumeration is a raw type. References to generic type Enumeration<E> should be parameterized".

Ok, so, uh, what the hell do I do? I've done quite a bit of searching, there's plenty of info out there, but nothing clicked for me. Obviously I'm supposed to put something like
		Enumeration<Integer> e = genres.keys();
		while(e.hasMoreElements()) {
			int key = Integer.parseInt(e.nextElement().toString());
			if(genres.get(key).toString().equalsIgnoreCase(genreName)) { 
				return(new Genre(key,conn));
			}
		}

But what the hell type goes there? How do I know? genres.keys() return type is just specified as "enumeration". Any type I specify results in either a full on error or a new warning that the type requires an unchecked cast, which is exactly what parameterizing that bit is intended to avoid. I've tried parameterizing it as Integer, Enumeration, and ?. Integer gets me the new warning, Enumeration gets me the new warning plus the old one because of the new Enumeration, and ? gets rid of all warnings but is just a wildcard if I understood docs right, so probably isn't actually solving any problems other than getting rid of the warning.

Jimmy King on

Posts

  • ASimPersonASimPerson And they will tremble again at the sound of our silence!Registered User regular
    edited May 2008
    Are you sure you have a HashMap? The API says there is no method "keys" for it.

    What is the type of "genres"?

    Answer those two questions and then I think we can help you.

    I'm trying to give a generic (no pun intended) answer but I need to know genres is supposed to be a hashmap or something you cooked up first...

    redoctober2.png
    SE++ Forum Battle Archive | PST = Pacific Standard Time | DRUNKSTUCK: A Homestuck recap
  • Vrtra TheoryVrtra Theory Registered User regular
    edited May 2008
    Defining your object (genres):
    // Old way
    HashMap genres = new HashMap();
    
    // New way
    HashMap<Integer, String> genres = new HashMap<Integer, String>();
    

    To loop through the values (by keys):
    for(Integer key : genres.keySet()) {
      if (genres.get(key).equalsIgnoreCase(genreName)) {
        return new Genre(key, conn);
      }
    }
    

    Or looping through key,value pairs:
    for(Entry<Integer, String> e : genres.entrySet()) {
      if (e.getValue().equalsIgnoreCase(genreName)) {
        return new Genre(e.getKey(), conn);
      }
    }
    

    In my opinion, once you're writing Java in 1.5+, there's no reason to use an Enumerator anymore (Iterator is better). And, with the new for(value:collection) construct, there's usually no need to create an explicit Iterator either.

    I recommend Sun's Generics Tutorial for more info on what generics are and how they work.

    (I'm also not sure what genres.keys() is supposed to be, it makes me wonder if you have mismatched runtime jars for your Java environment?)

  • ASimPersonASimPerson And they will tremble again at the sound of our silence!Registered User regular
    edited May 2008
    My best guess is that he has some sort of class that contains a hashmap and defined a method that supposed to return all the keys. Or some such. Hashmaps have been around since Java 1.2, and checking the 1.3 API there's no keys() method.

    Anyway OP, check out that tutorial. Once you get generics you'll wonder how you ever lived without them, trust me. :)

    redoctober2.png
    SE++ Forum Battle Archive | PST = Pacific Standard Time | DRUNKSTUCK: A Homestuck recap
  • Jimmy KingJimmy King Registered User regular
    edited May 2008
    Balls. I meant to type Hashtable up there, not HashMap. Hashtable has a keys() method which returns an enumeration. It looks like maybe I should change it to using a HashMap instead of Hashtable, though. It appears to have the same overall functionality, but works in a way that seems much more intuitive and more like the hashes I'm used to using in Perl.

    Gonna go rewrite that stuff real quick and see what happens.

    edit: much better now using HashMap instead of Hashtable. Works how I expect, the generics work how I expected after reading about them, etc. Still not straight about the enumeration stuff, though. I may have to do a quick test with a Hashtable again - maybe I initialized something wrong, because I just couldn't get it to shut up about the parameters on Enumeration it returns.

  • Vrtra TheoryVrtra Theory Registered User regular
    edited May 2008
    Ah, Hashtable makes more sense. You can do the same thing with Hashtable in 1.5, something like:
    Hashtable<Integer, String> genres = new Hashtable<Integer, String>();
    
    Enumeration<Integer> e = genres.keys();
    

    Hashtable also implements the Map class now, so you could copy and paste the exact code for HashMap and it would work that way too.

    As a side note, Hashtable is synchronized internally, while the new collections (HashMap, etc.) are not. So Hashtable will be slower than HashMap for most use cases (unless you're going to synchronize your HashMap yourself anyway.)

  • Jimmy KingJimmy King Registered User regular
    edited May 2008
    Ah, Hashtable makes more sense. You can do the same thing with Hashtable in 1.5, something like:
    Hashtable<Integer, String> genres = new Hashtable<Integer, String>();
    
    Enumeration<Integer> e = genres.keys();
    

    Hashtable also implements the Map class now, so you could copy and paste the exact code for HashMap and it would work that way too.

    As a side note, Hashtable is synchronized internally, while the new collections (HashMap, etc.) are not. So Hashtable will be slower than HashMap for most use cases (unless you're going to synchronize your HashMap yourself anyway.)
    Yeah, it didn't like it when I tried to use the Hashtable like that, which is what confused me. Maybe I typoed something or missed something and didn't realize it. I'll just stick with HashMap for now, though. It works how I expected and apparently is better, not that I expect this to frequently have more than maybe 5 things, so performance probably won't be a huge matter in any case.

Sign In or Register to comment.