How to correctly use HashMap?

37,866

Solution 1

I'm not sure what you're trying to do, but since the example you provided uses hard-coded strings to index the data, it seems like you know what data you want to group together. If that's the case, then a Map is probably not a good choice. The better approach would be to make a class out of the commonly grouped data:

public class SavedStuff {
  private int index;
  private String symbol;

  public SavedStuff(int index, String symbol) {
    this.index = index;
    this.symbol = symbol;
  }

  public int getIndex() {
    return index;
  }

  public String getSymbol() {
    return symbol;
  }
}

This allows your client code to do this:

SavedStuff savedStuff = ...
String symbol = savedStuff.getSymbol();

Rather than this:

Map<String, Object> savedStuff = ...
String symbol = savedStuff.get("symbol");

The former example is much less fragile because you're not indexing data with String constants. It also gives you a place to add behavior on top of your grouped data, which makes your code much more object oriented.

Solution 2

HashMap<String, Object> savedStuff = new HashMap<String, Object>();

Of course, you will still have to be careful to use the right type when extracting elements.

Solution 3

You need to use generics as shown below :

Map<String, Object> savedStuff = new HashMap<String, Object>();

Solution 4

Using HashMap<String, Object> is probably the best you can do if you insist on having heterogeneous values in the same map -- you'll need to cast those to do anything useful when you retrieve them (and how are you going to know what type to cast them to...?), but at least you'll be typesafe with respect to the keys.

Solution 5

Here is a different Approach:

A Helper class that contains a map and provides different views of it:

public class ValueStore {


    /**
     * Inner map to store values.
     */
    private final Map<String,Object> inner = new HashMap<String,Object>();

    /**
     * Returns true if the Value store contains a numeric value for this key.
     */
    public boolean containsIntValue(final String key){
        return this.inner.get(key) instanceof Integer;
    }


    /**
     * Returns true if the Value store contains a String value for this key.
     */
    public boolean containsStringValue(final String key){
        return this.inner.get(key) instanceof String;
    }

    /**
     * Returns the numeric value associated with this key.
     * @return -1 if no such value exists
     */
    public int getAsInt(final String key){
        final Object retrieved = this.inner.get(key);
        return retrieved instanceof Integer ? ((Integer) retrieved).intValue() : -1;
    }


    /**
     * Returns the String value associated with this key.
     * @return null if no such value exists
     */
    public String getAsString(final String key){
        final Object retrieved = this.inner.get(key);
        return retrieved instanceof String ? (String) retrieved : null;
    }

    /**
     * Store a string value.
     */
    public void putAsInt(final String key, final int value){
        this.inner.put(key, Integer.valueOf(value));
    }


    /**
     * Store an int value.
     */
    public void putAsString(final String key, final String value){
        this.inner.put(key, value);
    }

    /**
     * Main method for testing.
     */
    public static void main(final String[] args) {
        final ValueStore store = new ValueStore();
        final String intKey = "int1";
        final String stringKey = "string1";
        final int intValue = 123;
        final String stringValue = "str";

        store.putAsInt(intKey, intValue);
        store.putAsString(stringKey, stringValue);

        assertTrue(store.containsIntValue(intKey));
        assertTrue(store.containsStringValue(stringKey));
        assertFalse(store.containsIntValue(stringKey));
        assertFalse(store.containsStringValue(intKey));
        assertEquals(123, store.getAsInt(intKey));
        assertEquals(stringValue, store.getAsString(stringKey));
        assertNull(store.getAsString(intKey));
        assertEquals(-1, store.getAsInt(stringKey));
    }

}

Before you would retrieve an int value, you would check the value of store.containsIntValue(intKey) and before you retrieve a String value, you would check store.containsStringValue(stringKey). That way you would never retrieve values of the wrong type.

(Can of course be extended to support other types as well)

Share:
37,866

Related videos on Youtube

Sheehan Alam
Author by

Sheehan Alam

iOS, Android and Mac Developer. i can divide by zero.

Updated on April 03, 2020

Comments

  • Sheehan Alam
    Sheehan Alam about 4 years
    HashMap savedStuff = new HashMap();
    savedStuff.put("symbol", this.symbol); //this is a string
    savedStuff.put("index", this.index); //this is an int
    

    gives me the warning:

    HashMap is a raw type. References to generic type HashMap<K,V> should be parameterized  
    
    • Lalith B
      Lalith B over 10 years
      apache commons Multivalue map may solve your problem.!