As was foretold, we've added advertisements to the forums! If you have questions, or if you encounter any bugs, please visit this thread: https://forums.penny-arcade.com/discussion/240191/forum-advertisement-faq-and-reports-thread/

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 Cold... and hard.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...

    ASimPerson on
  • 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?)

    Vrtra Theory on
    Are you a Software Engineer living in Seattle? HBO is hiring, message me.
  • ASimPersonASimPerson Cold... and hard.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. :)

    ASimPerson on
  • 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.

    Jimmy King on
  • 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.)

    Vrtra Theory on
    Are you a Software Engineer living in Seattle? HBO is hiring, message me.
  • 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.

    Jimmy King on
Sign In or Register to comment.