Generic Newbie HashMap Query

Discussion in 'Java' started by MrFredBloggs@hotmail.com, May 2, 2005.

  1. Guest

    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.
     
    , May 2, 2005
    #1
    1. Advertising

  2. Ross Bamford Guest

    On Sun, 2005-05-01 at 16:23 -0700, wrote:
    > 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?

    --
    [Ross A. Bamford] [ross AT the.website.domain]
    Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
    http://www.roscopec0.f9.co.uk/ + in
     
    Ross Bamford, May 2, 2005
    #2
    1. Advertising

  3. Ross Bamford Guest

    On Mon, 2005-05-02 at 01:09 +0100, Ross Bamford wrote:
    > On Sun, 2005-05-01 at 16:23 -0700, wrote:
    > > 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?
    >


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


    --
    [Ross A. Bamford] [ross AT the.website.domain]
    Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
    http://www.roscopec0.f9.co.uk/ + in
     
    Ross Bamford, May 2, 2005
    #3
  4. Guest

    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;
    }
    }
    }
     
    , May 2, 2005
    #4
  5. Guest

    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;
    }
    }
    }
     
    , May 2, 2005
    #5
  6. Ross Bamford Guest

    On Sun, 2005-05-01 at 17:30 -0700, wrote:
    > 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

    --
    [Ross A. Bamford] [ross AT the.website.domain]
    Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
    http://www.roscopec0.f9.co.uk/ + in
     
    Ross Bamford, May 2, 2005
    #6
  7. Chris Uppal Guest

    wrote:

    > 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
     
    Chris Uppal, May 2, 2005
    #7
  8. Guest

    ....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.
     
    , May 2, 2005
    #8
  9. Ross Bamford Guest

    On Mon, 2005-05-02 at 07:02 -0700, wrote:
    > ...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.
    >


    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; }
    }



    --
    [Ross A. Bamford] [ross AT the.website.domain]
    Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
    http://www.roscopec0.f9.co.uk/ + in
     
    Ross Bamford, May 2, 2005
    #9
  10. wrote:

    > 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.


    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.)

    --
    John Bollinger
     
    John C. Bollinger, May 2, 2005
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Miguel Angel
    Replies:
    9
    Views:
    13,864
    Christian Kaufhold
    Apr 15, 2004
  2. Vince Darley
    Replies:
    4
    Views:
    4,432
    emilchacko
    Mar 2, 2010
  3. Murat Tasan
    Replies:
    1
    Views:
    8,051
    Chaitanya
    Feb 3, 2009
  4. Rakesh
    Replies:
    10
    Views:
    12,182
    Mike Schilling
    Apr 8, 2008
  5. Chris Riesbeck

    nested generic HashMap problem

    Chris Riesbeck, Apr 26, 2010, in forum: Java
    Replies:
    18
    Views:
    967
    Arne Vajhøj
    Apr 28, 2010
Loading...

Share This Page