views:

165

answers:

6

I want to map integers to strings, they are one-to-one such as :

60 : c
61 : c#
62 : d
63 : d#
64 : e
65 : f
66 : f#

But I need to have the ability to do the following :

  1. Get a value from a key : "c" = getValue(60) [ give it a key 60, return string value ]
  2. get key from a value : 65 = getKey("f") [ give it a string value "f", return a key ]

Which collection model is best suited for this ? I'm asking because I've looked at several of them, none can do the <2> part. Or do I have to write code to go through every pair to find which key has value "f" ?

Edit : Nothing in jdk1.6 does this ?

+13  A: 

Commons Collections and Google Guava both have a bi-directional map.

Thilo
+5  A: 

what you need is a BiMap. google guava library provides this collection.

Pangea
+6  A: 

If you don't want to include commons collections or guava, just use two separate maps -- you can create the reverse mapping programmatically from the first with a simple foreach loop. I would suggest designing your code so that all the access to these maps is internal to a single class (since it's an implementation detail and should be hidden from the rest of the system). In other words, don't pass these maps to any methods. Then, you can very easily switch to a more appropriate collection should you later choose to.

Ben Taitelbaum
+1  A: 

Hi I'm would like to interject a couple of things The standards maps in Java work unidirectionally: give a key get the object(s) I'm not aware of a java jdk1.6 class that does it

a couple of ideas 1) create a class that has 2 maps one with the and the other with , this isn't so hard to implement ^^

2) IF your datas are like your posted AND IF this is a predefined associative list why not try and enumeration ? or a ArrayList?

Jason

+1  A: 

If these are musical notes with a fixed set of key-value pairs then you may consider using enum with a reverse-lookup map. You will still end up with two HashMaps but at least they are joined together within the enum.

enum Note {
    C("C",60), CSHARP("C#",61), D("D",62), DSHARP("D#",63); //etc..
    final int value;
    final String symbol;
    static final Map<Integer, Note> lookup = new HashMap<Integer, Note>();
    static {
        for(Note n : Note.values()) {
            lookup.put(n.value, n);
        }
    }

    Note(String symbol, int value) {
        this.symbol = symbol;
        this.value = value;
    }

    static Note get(int i) {
        return lookup.get(i);
    }
}

Then to get the values and symbols, use this

System.out.println(Note.get(61));
System.out.println(Note.get(61).symbol);
System.out.println(Note.CSHARP.value);
System.out.println(Note.CSHARP.symbol);

which will result to

CSHARP
C#
61
C#

PS. Modifiers are removed for brevity. PSS. Add the other lookup map for symbol.

Adrian M
A: 

Hi,

found this in another forum (link text)

    public class ReversibleMap {
       private final Map keyToValue = new HashMap(8);
       private final Map valueToKey = new HashMap(8);

       public void put(Integer key, String value) {
           keyToValue.put(key, value);
           valueToKey.put(value, key);
       }

       public String get(Integer key) {
           return (String) keyToValue.get(key);
       }

       public Integer getKey(String value) {
           return (Integer) valueToKey.get(value);
      }
   }

This should do

Florian Becke
`HashMap` would need to be a `LinkedHashMap` for bi-directional usage.
Coronatus
Simple and to the point answer to my question, thanks !
Frank