Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Inverse get() for a Map

Reply
Thread Tools

Inverse get() for a Map

 
 
Larry Coon
Guest
Posts: n/a
 
      07-07-2004
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
 
Reply With Quote
 
 
 
 
Tor Iver Wilhelmsen
Guest
Posts: n/a
 
      07-07-2004
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);
}
}
 
Reply With Quote
 
 
 
 
Filip Larsen
Guest
Posts: n/a
 
      07-07-2004
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


 
Reply With Quote
 
Cristiano Sadun
Guest
Posts: n/a
 
      07-07-2004
"Filip Larsen" <(E-Mail Removed)> 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)
 
Reply With Quote
 
Larry Coon
Guest
Posts: n/a
 
      07-07-2004
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
 
Reply With Quote
 
Larry Coon
Guest
Posts: n/a
 
      07-07-2004
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
 
Reply With Quote
 
Jesper Nordenberg
Guest
Posts: n/a
 
      07-07-2004
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
 
Reply With Quote
 
Angus
Guest
Posts: n/a
 
      07-07-2004
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.
 
Reply With Quote
 
Larry Coon
Guest
Posts: n/a
 
      07-11-2004
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!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
fmap(), "inverse" of Python map() function vasudevram Python 9 10-06-2012 10:07 PM
Frame-relay map and inverse-arp allangiganson@yahoo.com Cisco 7 04-03-2009 06:06 PM
Query about tan inverse function jahaya@gmail.com VHDL 1 07-17-2005 01:27 PM
Inverse of 'chop @array' gusmeister Perl 1 03-06-2004 01:28 AM
CEF vs MLPPP vs Inverse Multiplex SysAdmin Cisco 1 11-20-2003 01:51 PM



Advertisments