Inverse get() for a Map

Discussion in 'Java' started by Larry Coon, Jul 7, 2004.

  1. Larry Coon

    Larry Coon Guest

    Is there a convenient & clever way to get a key
    from a Map given a value (as opposed to the usual
    getting a value given a key)?

    I'm using a TreeMap, where the keys are Dates and the
    values are Strings which represent the dates. I have
    a JComboBox with the Strings. The JComboBox needs to
    display the Strings in Date order, which is why I'm
    using the Dates as the keys in the TreeMap -- the
    TreeMap orders on the keys.

    Here's a short example to illustrate what I'm doing.
    Where the println() is printing "???" I want the key
    associated with the selected item. Is there a better
    way than iterating through the entire Map?

    import java.awt.*;
    import java.awt.event.*;
    import java.text.*;
    import java.util.*;
    import javax.swing.*;

    public class TreeMapTest extends JFrame
    implements ActionListener {

    private JComboBox comboBox;

    public TreeMapTest() {
    super("TreeMapTest");

    Container container = getContentPane();
    container.setLayout(new GridLayout(2, 1, 0, 10));

    Map map = buildMap();

    comboBox = new JComboBox();
    comboBox.setModel(new DefaultComboBoxModel(map.values().toArray()));
    container.add(comboBox);

    JButton goButton = new JButton("Go");
    goButton.addActionListener(this);
    container.add(goButton);

    pack();
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
    String selectedValue = comboBox.getSelectedItem().toString();
    System.out.println("Selected value = " + selectedValue);

    // Here is where I want to get the key for the selected value.
    System.out.println("Selected key = ???");
    }

    private Map buildMap() {
    Map result = new TreeMap();
    SimpleDateFormat df =
    new SimpleDateFormat("MM/dd/yyyy", Locale.getDefault());

    try {
    result.put(df.parse("10/1/2003"), "Fall '03");
    result.put(df.parse("4/1/2004"), "Spring '04");
    result.put(df.parse("10/1/2004"), "Fall '04");
    result.put(df.parse("4/1/2005"), "Spring '05");
    }
    catch (ParseException e) {
    e.printStackTrace();
    }

    return result;
    }

    public static void main(String[] args) {
    new TreeMapTest();
    }
    }

    --

    Larry Coon
    University of California
     
    Larry Coon, Jul 7, 2004
    #1
    1. Advertising

  2. Larry Coon <lmcoon@nospam_cox.net> writes:

    > Is there a convenient & clever way to get a key
    > from a Map given a value (as opposed to the usual
    > getting a value given a key)?


    Yes, use a second Map with the reverse relationship in it.

    public class ReverseMap extends HashMap {
    private HashMap reverse = new HashMap();
    public Object put(Object key, Object value) {
    Object ret = super.put(key, value);
    reverse.put(value, key);
    return ret;
    }
    // putAll() left as an exercise etc.
    public Object getReverse(Object value) {
    return reverse.get(value);
    }
    }
     
    Tor Iver Wilhelmsen, Jul 7, 2004
    #2
    1. Advertising

  3. Larry Coon

    Filip Larsen Guest

    Larry Coon wrote

    > Is there a convenient & clever way to get a key
    > from a Map given a value (as opposed to the usual
    > getting a value given a key)?
    >
    > I'm using a TreeMap, where the keys are Dates and the
    > values are Strings which represent the dates. I have
    > a JComboBox with the Strings. The JComboBox needs to
    > display the Strings in Date order, which is why I'm
    > using the Dates as the keys in the TreeMap -- the
    > TreeMap orders on the keys.


    If you only use the TreeMap to sort the dates for the combo box you may
    want to consider to skip the map altogether and combine the date value
    and its textual representation into one object, something along the
    following lines:

    import java.util.Date;

    public class MyDate implements Comparable {
    public MyDate(Date date, String text) {
    this.date = date;
    this.text = text;
    }
    public Date getDate() {
    return date;
    }
    public String toString() {
    return text;
    }
    public int compareTo(Object o) {
    return getDate().compareTo(((MyDate)o).getDate());
    }
    final private Date date;
    final private String text;
    }

    Then you can put MyDate objects into a List like ArrayList, sort the
    list with Collections.sort and then give the sorted list to the
    combobox. When you need the date selected on the combobox you just use
    MyDate.getDate on the selected object. If you have more than one sort
    order then you may want to move the compare method into a Comparator
    class instead.


    Regards,
    --
    Filip Larsen
     
    Filip Larsen, Jul 7, 2004
    #3
  4. "Filip Larsen" <> wrote in news:ccgn2j$8uu$1
    @news.cybercity.dk:

    > Larry Coon wrote
    >
    >> Is there a convenient & clever way to get a key
    >> from a Map given a value (as opposed to the usual
    >> getting a value given a key)?


    Compose key and value:

    class ObjectWithKey {

    private Object object;
    private Object key;

    public ObjectWithKey(Object key, Object object) { ..assign as obvious.. }

    public int hashCode() { return object.hashCode(); }
    public boolean equals(Object obj) {
    return obj instanceof ObjectWithKey ?
    object.equals(((ObjectWithKey)obj).object) :
    object.equals(obj); // or "false" if u want strict equivalence
    }

    }

    (didnt code for the case when object == null but it's fairly obvious)
     
    Cristiano Sadun, Jul 7, 2004
    #4
  5. Larry Coon

    Larry Coon Guest

    Filip Larsen wrote:

    > If you only use the TreeMap to sort the dates for the combo box you may
    > want to consider to skip the map altogether and combine the date value
    > and its textual representation into one object, something along the
    > following lines:


    (snipped)

    Thanks for the suggestion -- I was stuck thinking about
    it as a map, and hadn't even considered alternatives
    like this.

    But I'll have to think about it more seriously before
    coding it your way. The example I gave was for one of
    several Maps this app is using which map display values
    to database values (to go into the "where" clause in
    a SQL select call via JDBC). In every case except this
    one I want the data sorted by the display value (the
    value that goes into the combo box). It's just this one
    oddball case where the data should be sorted by the
    database value. This makes Tor's idea of a second,
    reversed Map appealing -- in this one case I'd send the
    reversed map to the combo box, and the rest of the
    application logic would use the selected value in the
    combo box as the key to the Map (the non-reversed map in
    this case) where it does a map.get(key) to retrieve the
    value to stick in the SQL where clause.


    Larry Coon
    University of California
     
    Larry Coon, Jul 7, 2004
    #5
  6. Larry Coon

    Larry Coon Guest

    Tor Iver Wilhelmsen wrote:

    > Yes, use a second Map with the reverse relationship in it.


    Thanks. This makes sense for what I'm doing --
    this is one of several Maps where one value goes
    into a combo box and the other value is used for
    database lookups. This one is the only oddball,
    where the combo box values are sorted by the
    database values. Using two maps for this one
    case lets me encapsulate all the oddball behavior
    into a single method, so the front-end (UI) and
    back-end (database logic) can continue to be
    generic.


    Larry Coon
    University of California
     
    Larry Coon, Jul 7, 2004
    #6
  7. Larry Coon <lmcoon@nospam_cox.net> wrote in message news:<40EB935B.78EA@nospam_cox.net>...
    > Is there a convenient & clever way to get a key
    > from a Map given a value (as opposed to the usual
    > getting a value given a key)?


    If you don't want to use a reverse map, the only way to do it is to
    get the entrySet() and iterate over that until you find your key.

    /Jesper Nordenberg
     
    Jesper Nordenberg, Jul 7, 2004
    #7
  8. Larry Coon

    Angus Guest

    Tor Iver Wilhelmsen wrote:
    >
    > Larry Coon <lmcoon@nospam_cox.net> writes:
    >
    > > Is there a convenient & clever way to get a key
    > > from a Map given a value (as opposed to the usual
    > > getting a value given a key)?

    >
    > Yes, use a second Map with the reverse relationship in it.


    The Commons-Collections library, of the Jakarta project, boasts
    a "BidiMap" interface for maps that can be looked up from value
    to key as well as key to value.

    http://jakarta.apache.org/commons/collections/

    Good Luck,
    Avi.
     
    Angus, Jul 7, 2004
    #8
  9. Larry Coon

    Larry Coon Guest

    Filip Larsen wrote:

    > If you only use the TreeMap to sort the dates for the combo box you may
    > want to consider to skip the map altogether and combine the date value
    > and its textual representation into one object, something along the
    > following lines:


    (code snipped)

    > Then you can put MyDate objects into a List like ArrayList, sort the
    > list with Collections.sort and then give the sorted list to the
    > combobox.


    FOLLOW-UP: Many days and several refactorings later, this
    is exactly what I ended up doing, and it works great.
    Better than using Collections.sort(), the "order by" clause
    in my SQL select statement determines the ordering for the
    items in the combo box. I now have four distinct data types
    (with a common ancestor, so no duplicate code) feeding four
    combo boxes this way, and it all works great. Thanks!
     
    Larry Coon, Jul 11, 2004
    #9
    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. Replies:
    1
    Views:
    869
    David Bishop
    Jul 17, 2005
  2. gusmeister

    Inverse of 'chop @array'

    gusmeister, Mar 6, 2004, in forum: Perl
    Replies:
    1
    Views:
    692
    J├╝rgen Exner
    Mar 6, 2004
  3. Benjamin Johnston
    Replies:
    1
    Views:
    489
    Mike Schilling
    Jan 6, 2005
  4. =?iso-8859-1?B?bW9vcJk=?=

    Asking inverse() function for List and ArrayList

    =?iso-8859-1?B?bW9vcJk=?=, Dec 12, 2005, in forum: Java
    Replies:
    11
    Views:
    683
    andreaz
    Dec 13, 2005
  5. vasudevram
    Replies:
    9
    Views:
    250
    vasudevram
    Oct 6, 2012
Loading...

Share This Page