Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / May 2005

Tip: Looking for answers? Try searching our database.

Generic Newbie HashMap Query

Thread view: 
MrFredBloggs@hotmail.com - 02 May 2005 00:23 GMT
import java.util.HashMap;

public class GenericMapTest
{
   private HashMap<String, ? > map  = null;
   private char                type = '\0';

   public GenericMapTest(char charIn)
   {
       super();

       switch (charIn)
       {
           case 'S':
               type = charIn;
               map  = new HashMap<String, String>();
               break;
           case 's':
               type = 'S';
               map  = new HashMap<String, String>();
               break;
           case 'I':
               type = charIn;
               map  = new HashMap<String, Integer>();
               break;
           case 'i':
               type = 'I';
               map  = new HashMap<String, Integer>();
               break;
       }
   }

   public void add(String stringIn)
   {
       switch (type)
       {
           case 'I':
               //BOUND MISMATCH: The method put(String, ?) of type
               //HashMap<String, ?> is not applicable for the
arguments
               //(String, Integer). The wildcard parameter ? has no
lower
               //bound and may actually be more restrictive than
argument
               //Integer.
               map.put(stringIn, new Integer(stringIn.trim()));
               break;
           case 'S':
               //BOUND MISMATCH: The method put(String, ?) of type
               //HashMap<String, ?> is not applicable for the
arguments
               //(String, String). The wildcard parameter ? has no
lower
               //bound and may actually be more restrictive than
argument
               //String.
               map.put(stringIn.trim(), stringIn.trim());
               break;
       }
   }
}

I'm new to generics.

Can the above errors be solved using the new Java5 generic coding
techniques or is what I am trying to do just too silly in the first
place.

Regards,

Fred.
Ross Bamford - 02 May 2005 01:09 GMT
> import java.util.HashMap;

> Can the above errors be solved using the new Java5 generic coding
> techniques or is what I am trying to do just too silly in the first
> place.

I think you need HashMap<String,Object> , or have I read you wrong?

Signature

  [Ross A. Bamford]     [ross AT the.website.domain]
Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
http://www.roscopec0.f9.co.uk/ + info@the.website.domain

Ross Bamford - 02 May 2005 01:16 GMT
> > import java.util.HashMap;
>
[quoted text clipped - 3 lines]
>
> I think you need HashMap<String,Object> , or have I read you wrong?

sorry,  HashMap<String,? extends Object>  reading your post again.

Signature

  [Ross A. Bamford]     [ross AT the.website.domain]
Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
http://www.roscopec0.f9.co.uk/ + info@the.website.domain

MrFredBloggs@hotmail.com - 02 May 2005 01:30 GMT
Even HashMap<String, ? extends Object> gives the following errors:

import java.util.HashMap;

public class GenericMapTest
{
   private HashMap<String, ? extends Object> map  = null;
   private char                              type = '\0';

   public GenericMapTest(char charIn)
   {
       super();

       switch (charIn)
       {
           case 'S':
               type = charIn;
               map  = new HashMap<String, String>();
               break;
           case 's':
               type = 'S';
               map  = new HashMap<String, String>();
               break;
           case 'I':
               type = charIn;
               map  = new HashMap<String, Integer>();
               break;
           case 'i':
               type = 'I';
               map  = new HashMap<String, Integer>();
               break;
       }
   }

   public void add(String stringIn)
   {
       switch (type)
       {
           case 'I':
               //BOUND MISMATCH: The method put(String, ? extends
Object)
               //of type HashMap<String, ? extends Object> is not
               //applicable for the arguments (String, Integer). The
               //wildcard parameter ? has no lower bound and may
actually
               //be more restrictive than argument Integer.
               map.put(stringIn, new Integer(stringIn.trim()));
               break;
           case 'S':
               //BOUND MISMATCH: The method put(String, ? extends
Object)
               //of type HashMap<String, ? extends Object> is not
               //applicable for the arguments (String, String). The
               //wildcard parameter ? has no lower bound and may
actually
               //be more restrictive than argument String.
               map.put(stringIn.trim(), stringIn.trim());
               break;
       }
   }
}
Ross Bamford - 02 May 2005 12:09 GMT
> Even HashMap<String, ? extends Object> gives the following errors:

Hmm, Now I see what you're saying.

It will compile if you change your method;

// ---
   public void add(String stringIn)
   {
     switch (type)
     {
       case 'I': {
         Map<String,Integer> tMap = (Map<String,Integer>)map;
         tMap.put(stringIn, new Integer(stringIn.trim()));
         break;
       }
       case 'S': {
         Map<String,String> tMap = (Map<String,String>)map;
         tMap.put(stringIn.trim(), stringIn.trim());
         break;
       }
     }
   }
// ---

But this of course generates two unchecked exceptions, rendering the
whole thing pointless.

There are others who know more about this that I do (John?) so perhaps
there is another way to do it, but I think you would need to create a
generic class, such as:

<T extends Object> class MyValue<T>
{
 public void set(<T> val)
 public <T> get()
}

(thats paraphrased btw but you get the idea). This you could then add to
your map, creating your instances as new MyValue<String>,
MyValue<Integer>, and so on, and setting the value appropriately
(possibly via constructor).

Hope this helps,
Ross

Signature

  [Ross A. Bamford]     [ross AT the.website.domain]
Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
http://www.roscopec0.f9.co.uk/ + info@the.website.domain

MrFredBloggs@hotmail.com - 02 May 2005 15:02 GMT
...that's great !!

I see what you mean.

However, having written your generic entry class as advised it appears
that Eclipse 3.16M won't compile it, it doesn't seem to understand any
of the <T> tokens. Anyway I see what you mean and will keep trying with
this approach.

Regards,

Fred.
Ross Bamford - 02 May 2005 17:01 GMT
> ...that's great !!
>
[quoted text clipped - 8 lines]
>
> Fred.

Sorry it was a typo - the tokens should be <T> in signatures, but just
straight T when referenced within the class:

class MyValue<T extends Object>
{
 T value = null;
 public void set(T val) { value = val; }
 public T get() { return value; }
}

Signature

  [Ross A. Bamford]     [ross AT the.website.domain]
Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
http://www.roscopec0.f9.co.uk/ + info@the.website.domain

MrFredBloggs@hotmail.com - 02 May 2005 01:18 GMT
These are the errors I get if I use HashMap<String, Object>.

import java.util.HashMap;

public class GenericMapTest
{
   private HashMap<String, Object > map  = null;
   private char                     type = '\0';

   public GenericMapTest(char charIn)
   {
       super();

       switch (charIn)
       {
           case 'S':
               type = charIn;
               //TYPE MISMATCH: Cannot convert from
               //HashMap<String,String>
               //to HashMap<String, Object>.
               map  = new HashMap<String, String>();
               break;
           case 's':
               type = 'S';
               //TYPE MISMATCH: Cannot convert from
               //HashMap<String,String>
               //to HashMap<String, Object>.
               map  = new HashMap<String, String>();
               break;
           case 'I':
               type = charIn;
               //TYPE MISMATCH: Cannot convert from
               //HashMap<String,Integer>
               //to HashMap<String, Object>.
               map  = new HashMap<String, Integer>();
               break;
           case 'i':
               type = 'I';
               //TYPE MISMATCH: Cannot convert from
               //HashMap<String,Integer>
               //to HashMap<String, Object>.
               map  = new HashMap<String, Integer>();
               break;
       }
   }

   public void add(String stringIn)
   {
       switch (type)
       {
           case 'I':
               map.put(stringIn, new Integer(stringIn.trim()));
               break;
           case 'S':
               map.put(stringIn.trim(), stringIn.trim());
               break;
       }
   }
}
Chris Uppal - 02 May 2005 14:36 GMT
> Can the above errors be solved using the new Java5 generic coding
> techniques or is what I am trying to do just too silly in the first
> place.

I don't know whether it's /silly/ because I don't know what you are trying to
achieve, but it does seem pretty weird to me.

Anyway, you can't make dynamically typed operations pass a static type check
like that provided by Java generics.  So you have two options: give up on
static type checking (in this instance), or give up on the idea of using /one/
collection for two different purposes.  I'm no great fan of static type
checking, but in this case it does seem likely that the latter option makes
more sense.

   -- chris
John C. Bollinger - 02 May 2005 17:01 GMT
> import java.util.HashMap;
>
[quoted text clipped - 63 lines]
> techniques or is what I am trying to do just too silly in the first
> place.

What you are trying to do is OK, but your approach is largely missing
the point of generics.

You have declared variable "map" to be of type HashMap<String, ?>,
which, according to the Generics tutorial, should be read something like
"HashMap from Strings to unknowns".  It is important to understand that
"unknown" does not mean "any type"; rather it means "some specific type
that is not known at compile time".  That's why you get type safety
warnings when you try to put values into the map.  Note also that that
makes complete sense: nothing in the code you provided enables the
compiler to verify that you didn't assign a HashMap<String, String> to
map and then try to add an Integer to it.

To solve the problem you have to devise a way to "capture" the
appropriate type information via the type declarations.  Because your
class wraps a Map that multiple methods use, the variable type
parameters of the Map are going to need to be connected with type
parameters of the class.  That means that a particular instance of the
class will be associated with a particular value type for the Map.  Here
is an example:

import java.util.HashMap;
import java.util.Map;

public class GenericMapTest<T> {
    Map<String, T> map;

    GenericMapTest() {
        map = new HashMap<String, T>();
    }

    public void add(T value) {  // NOTE: important difference here
        map.put(value.toString(), value);  // and here
    }
}

To create on of these, you would use "new GenericMapTest<Integer>()"
(for instance).  Note the simplicity of the example compared to yours:
one of the positive joys of generics is that they completely sidestep
the kind of complicated type handling that so dominated your example.
(At the expense of introducing sometimes-cryptic declarations.)

Signature

John Bollinger
jobollin@indiana.edu



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.