2

A method of mine returns a Map<A,B>. In some clearly identified cases, the map only contains one key-value pair, effectively only being a wrapper for the two objects.

Is there an efficient / elegant / clear way to access both the key and the value? It seems overkill to iterate over the one-element entry set. I'm looking for somehing that would lower the brain power required for people who will maintain this, along the lines of:

(...)
// Only one result.
else {
    A leKey = map.getKey(whicheverYouWantThereIsOnlyOne); // Is there something like this?
    B leValue = map.get(leKey); // This actually exists. Any Daft Punk reference was non-intentional.
}

Edit: I ended up going with @akoskm solution's below. In the end, the only satisfying way of doing this without iteration was with a TreeMap, and the overhead made that unreasonable.

It turns out there is not always a silver bullet, especially as this would be a very small rabbit to kill with it.

Silver Quettier
  • 2,045
  • 2
  • 26
  • 53
  • Is this overkill for you: `final Map.Entry singleEntry = (new HashMap()).entrySet().iterator().next();`? – Smutje Aug 22 '14 at 07:07
  • The normal use-case for a Map are multiple key=value. Yours is an exception and need some code that seems to be too much. – PeterMmm Aug 22 '14 at 07:08
  • No since it's not part of map's contract: 1) map can hold the same value for multiple keys, no reason why it should make any exceptions 2) internally it would have to iterate over all values anyway, again no reason to maintain a reverse index – Mateusz Dymczyk Aug 22 '14 at 07:09
  • @Smutje Not exactly overkill, but maybe not very readable. I'll go with this and add a comment if there is no "magic trick" that I did not know about. :) – Silver Quettier Aug 22 '14 at 07:10
  • Wrap the map with a lightweight Object that has the methods `getKey()` and `getVal()` and implement them anyway you want (i.e. `map.keySet().toArray()[0]` etc). It'll be both readable and easy to maintain. – Nir Alfasi Aug 22 '14 at 07:12
  • On a different angle, probably it is feasible to treat a return size of 1 exactly as a return size of > 1 which would make the distinction obsolete? – Smutje Aug 22 '14 at 07:13
  • 1
    If your Map has only one key (and always is this way), it isn't probably the better structure to store your data – Miguel Prz Aug 22 '14 at 07:16
  • 1
    Have you checked this [post](http://stackoverflow.com/questions/1509391/how-to-get-the-one-entry-from-hashmap-without-iterating) by the way?? – Daniel Aug 22 '14 at 07:28

4 Answers4

5

If you need both key/value then try something like this:

Entry<Long, AccessPermission> onlyEntry = map.entrySet().iterator().next();
onlyEntry.getKey();
onlyEntry.getValue();
Akos K
  • 7,071
  • 3
  • 33
  • 46
  • 3
    *It seems overkill to iterate over the one-element entry set.* – TheLostMind Aug 22 '14 at 07:11
  • 1
    The OP is asking for an efficient / elegant / clear way. I think this satisfies at least two of these. Of course you can always invent your own wheel and write some shiny logic in a few lines of code, which won't necessarily _lower the brain power required for people who will maintain this_. – Akos K Aug 22 '14 at 07:15
  • 1
    I assume that this would have been the first answer to be posted if the OP hadn't said *It seems overkill to iterate over the one-element entry set.*. The answer is right, but not what the OP wants. (I didn't downvote BTW) – TheLostMind Aug 22 '14 at 07:17
  • 1
    I can not wait to see the solutions which doesn't iterate over the one-element set. – Akos K Aug 22 '14 at 07:20
  • 1
    Thank you, @TheLostMind, for trying to stick to my demands - but I think I overthought this. This question is probably going to become an example of "think of the maintainers", and KISS principles. Writing "clever" code is satisfying for the ego, but sometimes misguided. Thank you all for your suggestions. – Silver Quettier Nov 05 '14 at 10:56
  • @Akos – if to avoid the iteration is the only goal, try this: `Entry onlyEntry = new ArrayList<>( map.entrySet() ).get( 0 );` – No iteration!! Ok, perhaps clear, perhaps elegant, but definitely not very efficient. – tquadrat Mar 21 '22 at 16:24
2

You can use TreeMap or ConcurrentSkipListMap.

TreeMap<String, String> myMap = new TreeMap<String, String>();
String firstKey   = myMap.firstEntry().getKey();
String firstValue = myMap.firstEntry().getValue();

Another way to use this:

String firstKey   = myMap.firstKey();
String firstValue = myMap.get(myMap.firstKey());

This can work as an alternate solution.

Abhishek
  • 422
  • 4
  • 13
0

There is a method called keySet() to get set of keys. read this thread.

else {
    A leKey=map.keySet().iterator().next();

    B leValue; = map.get(leKey); // This actually exists. Any Daft Punk reference was non-intentional.
}
Community
  • 1
  • 1
user3717646
  • 436
  • 3
  • 10
  • Why iterating when the map has only one key? – Smutje Aug 22 '14 at 07:14
  • it's not necessary. Otherwise you need to create a variable for storing the Keys list in to array and access it. As you know that there is one key per Map. The Map returns the Key as a Set – user3717646 Aug 22 '14 at 07:18
  • You iterate and at the accusation of iteration are saying "iteration is not necessary"? – Smutje Aug 22 '14 at 07:19
  • if you didn't use for each loop, you need to create a variable for storing the Keys list, convert them in to an array and access it (one way of doing it). – user3717646 Aug 22 '14 at 07:25
  • No, you can simply access the entry set and obtain the only map entry from it w/o a for loop and a variable which increases code complexity. – Smutje Aug 22 '14 at 07:26
  • I think your'e thinkin about iterator(). I changed the code. @Smutje – user3717646 Aug 22 '14 at 07:39
0

Using for-each loop and var :

for(var entry : map.entrySet()){
   A key = entry.getKey();
   B value = entry.getValue();
}
MWiesner
  • 8,868
  • 11
  • 36
  • 70