1

I have the following code and I'd like to get able to get the first and last element from the Map and assign each to a String.

String result1stElement = null;
String resultLastElement = null;

Map<String, String> result = new HashMap<String, String>();
result = myModel.getSampleResults();

Any ideas.

Thanks in advance.

xm21
  • 11
  • 2
  • 2
  • 5
  • 2
    A HashMap does not maintain a specific order, so you will essentially get random elements. You should clarify what you are trying to achieve and what you mean by first and last (is it based on alphabetical order? insertion order? some other criteria?). – assylias Sep 09 '14 at 10:20
  • Thanks everyone for your suggestions – xm21 Sep 10 '14 at 09:11
  • I would use the `NavigableMap` interface (`TreeMap` implementation), as explained [here](https://stackoverflow.com/a/3549555/136285) – malat May 24 '17 at 08:26

6 Answers6

6

First of all, Maps are not ordered so you wont really have a first and last element.

However, if you wish to get the first and last element of this anyways you could just get the values and convert this into an array. This isn't really pretty, but it'll work.

Map<String, String> result = new HashMap<String, String>();
result = myModel.getSampleResults();
map.values().toArray()[0]; //First result
map.values().toArray()[result.size()-1]; //Last result

Note: This is not tested with a compiler.

Sander
  • 1,264
  • 1
  • 16
  • 26
2

First and last element concepts not applicable to Hash-based structures like HashMap and HashSet. Insertion or deletion of key may cause element reordering on-the-fly.

I guess your model results is an key-value pairs list, not hash map. In this case element ordering is in place. LinkedHashMap keeps insertion order of elements.

Replace HashMap to LinkedHashMap (and modify .getSampleResults()) to return LinkedHashMap and check this question for futher details Java LinkedHashMap get first or last entry .

Community
  • 1
  • 1
Nikolay
  • 1,949
  • 18
  • 26
  • Thanks @Nikolay for that suggestion. My code above is for a JUnit, so the actual method I am testing has HashMap. I don't want to modify the actual code. Is there any other way around it? – xm21 Sep 10 '14 at 09:14
  • @xm21 sorry for late answer, I think it is not possible based on definition of Map. – Nikolay Sep 15 '14 at 15:57
0

There is no such a thing as a first and last element in a HashMap. This is the price you have to pay for O(1) lookup: internally the implementation will chuck your entries into a list of buckets in no easily identifiable (but deterministic) order. This process puts the Hash in HashMap, and in fact the more chaotic it is, the better the performance.

You can use a TreeMap if you want a map sorted by the natural order of its keys (or a custom comparator) or you can have a LinkedHashMap if you want the elements to be arranged in the order of insertion.

P.s.: even if you choose a Map implementation that maintains some kind of order, calling toArray() just to get the first and last elements is a massive overkill, I wouldn't do it. TreeMap has firstEntry() and lastEntry() methods, and even with LinkedHashMap, it's a lot cheaper to just manually iterate across the elements and keep the first and last one instead of allocating a potentially huge array.

biziclop
  • 48,926
  • 12
  • 77
  • 104
0

HashMap has no such thing as order. From HashMap javadoc:

This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

You'll have to use LinkedHashMap. Take a look at entrySet() method and this question+answer

Community
  • 1
  • 1
Arek
  • 3,106
  • 3
  • 23
  • 32
0

"toArray" method of Set interface can be used.

But iterating over the entries in the entry set and getting the first and last entry is a better approach.

This example might be helpful:

public static void main(final String[] args) {
        final Map<Integer,String> orderMap = new LinkedHashMap<Integer,String>();
        orderMap.put(6, "Six");
        orderMap.put(7, "Seven");
        orderMap.put(3, "Three");
        orderMap.put(100, "Hundered");
        orderMap.put(10, "Ten");

        final Set<Entry<Integer, String>> mapValues = orderMap.entrySet();
        final int maplength = mapValues.size();
        final Entry<Integer,String>[] test = new Entry[maplength];
        mapValues.toArray(test);

        System.out.print("First Key:"+test[0].getKey());
        System.out.println(" First Value:"+test[0].getValue());

        System.out.print("Last Key:"+test[maplength-1].getKey());
        System.out.println(" Last Value:"+test[maplength-1].getValue());
    }

// the output geneated is :
First Key:6 First Value:Six
Last Key:10 Last Value:Ten
VedantK
  • 9,728
  • 7
  • 66
  • 71
0

Your comment to @Nikolay's answer shows an important detail of your question that was hidden until now.

So, you want to test a method which uses a HashMap structure for refering to some added objects and you want to test, if this method delivers some ordering in this structure? First added object shall remain at a "first position", last added object at a "last position"?

As the other answers already show, there is no way without refactoring that method. HashMap doesn't deliver any meaningful ordering at all and if that method should deliver some ordering, it is simply broken - implementation is faulty.

Of course, you can write a unit test using the algorithm provided by @Sander. This test will fail most of the time. And this again shows the fact, that the tested method has to be refactured like @Nikolay showed in his answer, for instance.

codefan-BK
  • 310
  • 2
  • 9