How to get a HashMap value with three values

101,897

Solution 1

I just faced the same issue and decided to map my key to an Entry. This allows for the same indexing features provided by a map while having more than one property associated with a key. I think it's a much neater solution that creating a separate class or nesting maps.

Map<String, Entry<Action, Boolean>> actionMap = new HashMap<String, Entry<Action, Boolean>>();

actionMap.put("action_name", new SimpleEntry(action, true));

To use the data later:

Entry<Action, Boolean> actionMapEntry = actionMap.get("action_name");

if(actionMapEntry.value()) actionMapEntry.key().applyAction();

My personal use of this was a map of named functions. Having selected the function by name, the function would be run and the boolean would determine whether or not cleanup was needed in processing.

Solution 2

You create an object that holds all three subkeys of the key as attributes. Make sure to implement equals and hashCode properly.

public class MyKey {
  public MyKey(String subkey1, String subkey2, String subkey3) {
    ...
  }
}

Use such object as a key of your map:

Map<MyKey, String> myMap = ....;
myMap.get(new MyKey("Thu", "03 Jan 2013 21:50:02 +0100", "Transferts - YBX"));

Have fun!

Solution 3

You could also try to use a nested hashmap, of the type HashMap<String, HashMap<String, HashMap<String, String>>>, where you would then formulate your query as map.get(date).get(title).get(link)

The best solution would then be to encapsulate this nested hashmap in your own class as such:

public class NestedHashmap {
    private Map<String, Map<String, Map<String, String>>> map;

    public NestedHashMap() { 
        map = new HashMap<String, HashMap<String, HashMap<String, String>>>;
    }

    public put(String date, String title, String link, String value){
        if(map.get(date) == null) { 
            map.put(date, new HashMap<String, HashMap<String, String>>;
        }
        if(map.get(date).get(title) == null){
            map.get(date).put(new HashMap<String, String>);
        }
        map.get(date).get(title).put(link, value);
    }

    public get(String date, String title, String link) {
        // ...mostly analogous to put...
    }
}

Solution 4

You could create a compound key which contains all of the values you want in the key. A simple way to do this could be to concatenate the together the values that make up your key, delimited by a value you are sure won't appear in the key values.

E.g.:

String makeCompoundKey(String pubDate, String title) {
  return pubDate + "|" + title;
}

HashMap<String,String> map = new HashMap<String,String>();

map.put(makeComoundKey(pubDate,title), link)

To avoid the problem of having to choose a character which doesn't appear in any of the key values, to handle non-String keys and likely for better performance, you can declare a new class to contain your key values and override the equals and hashCode methods:

final class DateAndTitle {
  private final Date pubDate;
  private final String title;

  @Overrde
  boolean equals(Object rhs) {
    // let eclipse generate this for you, but it will probably look like ...
    return rhs != null && rhs.getClass() == getClass() &&
      pubDate.equals(rhs.pubDate) && title.equals(rhs.title);
  }

  @Overrde
  int hashCode(Object) {
    // let eclipse generate this for you...
    ...
  }
}

Then you can define your map like:

HashMap

and use DateAndTitle object to index your map.

Share:
101,897
androniennn
Author by

androniennn

Updated on November 05, 2020

Comments

  • androniennn
    androniennn over 3 years

    If I have a HashMap with a such key: [pubDate, title, link] and such value(example):

    [Thu, 03 Jan 2013 21:50:02 +0100, Transferts - YBX : ''Je change de dimension'', http://www.link.fr/info/link_informations.html]
    

    Can I retrieve the link http://www.link.fr/info/link_informations.html ? Code:

        for (int i = 0; i < nl.getLength(); i++) {
                        // creating new HashMap
                        map = new HashMap<String, String>();
                        Element e = (Element) nl.item(i);
                        // adding each child node to HashMap key => value
                        map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
                        map.put(KEY_LINK, parser.getValue(e, KEY_LINK));
    
                        map.put(KEY_DATE, parser.getValue(e, KEY_DATE));
                        //map.put(KEY_DESC, parser.getValue(e, KEY_DESC));
    
                        // adding HashList to ArrayList
                        menuItems.add(map);
     }
    
  • androniennn
    androniennn over 11 years
    You create an object that holds all three values of the key as attributes. How to retrieve the three values one by one. Put value1 in a, value2 in b, value3 in c (example). ?
  • SJuan76
    SJuan76 over 11 years
    Where I said "values" it should read "subkeys" (corrected now)
  • Israelm
    Israelm about 10 years
    Worked for me very good, thanks!!, to retrieve the three values one by one you can do something like this, on your class MyKey add the getters for the values, for example: getName() { return this.name; } Once you have all the getters on your key class you can iterate your map like this and access its properties: for (MyKey key : map.keySet()) {key.getName();key.getLastName();etc..}
  • ndm13
    ndm13 over 8 years
    I know it's been a few years, but I feel that this information is useful for those still looking for solutions.
  • pikimota
    pikimota almost 6 years
    Worked perfectly for me.
  • olyv
    olyv almost 6 years
    IMO, Map<String, Map<String, Map<String, String>>> map is VERY hard to read
  • Hatefiend
    Hatefiend almost 5 years
    @SJuan76 This is horrible for complexity and speed. Every time you need to lookup a value in your map, you need to construct a new key. Likely after doing so, you'll throw away the key you just made and have it garbage collected. This is not at all an ideal solution.