6

I need to read two columns (both String) from a file and keep the values of the first column in a HashMap where the Integer is the counter.

For example if the file I am reading is

Apple Fruit
PC    Device
Pen   Tool
...

and the code is

    String line="";
    int counter=1;
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("test.txt"),"Unicode"));
    while ((line = reader.readLine()) != null)
    {
        String[] words;
        words= st.split(" ");
            tokens.put(counter, words[0]);
        counter+=1;
    }

The problem is when I print The HashMap values, I found the values are in different order of that in the origianl file

        for (Map.Entry<Integer, String> token:tokens.entrySet())
    {
        System.out.println(token.getKey() + token.getValue());
    }

I got the following

1   Apple
3   Pen
4   whatever
2   ..etc

I do not know what is the problem?! can you please help me with that

Grzegorz Piwowarek
  • 13,172
  • 8
  • 62
  • 93
Wahedsaw
  • 397
  • 1
  • 6
  • 17

4 Answers4

26

As the documentation clearly states, HashMaps are unordered.
The enumeration order is determined by the hascodes of the keys.

If you want to preserve insertion order when enumerating the map, use LinkedHashMap.
If you want enumeration order to follow the natural ordering of the keys, use TreeMap.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Ok, on which basis the elements are ordered in HashMap? why this order !!!! why 4 coming before 2 – Wahedsaw May 31 '13 at 18:07
  • @Wahedsaw: It's based on the hashcodes. http://en.wikipedia.org/wiki/Hashtable – SLaks May 31 '13 at 18:10
  • @Wahedsaw Order of elements is based on hashcode value of keys. Take a look [[here](http://stackoverflow.com/questions/11596549/how-does-javas-hashmap-work-internally)] for more details about HashMap. – Pshemo May 31 '13 at 18:10
  • @Wahedsaw The order you see is the the standard sorting of the hashes of the keys. – Aleks G May 31 '13 at 18:10
  • A `HashMap` stores its data in a bunch of lists called buckets. When you add a key-value pair, the map calls `key.hashCode()`, takes it modulo the number of buckets, and puts it into that numbered bucket. When a bucket gets too big, the map creates more buckets, and adjusts *all* of the pairs in the map. This is one reason why you can't mutate a map while you iterate over it. As you see, the order of the buckets and the items in each bucket will change with time. Because of the modular reduction, not even the hash codes order the items. – Eric Jablow May 31 '13 at 18:13
6

HashMap is not ordered. You don't have any control over what order the items appear in. If you want an ordered map, you can use, for example, TreeMap.

EDIT: thanks to those that brought this up: TreeMap will keep items in the natural sorting order (i.e. in your case in alphabetical order). LinkedHashMap will preserve the order of insertion.

Aleks G
  • 56,435
  • 29
  • 168
  • 265
  • 1
    But that will use natural ordering or require a comparator. I would suggest `LinkedHashMap` for insertion order. – Paul Bellora May 31 '13 at 18:07
  • @PaulBellora Fair play. That's why I said _for example_ `TreeMap`. The OP didn't specify what order he/she is looking for. – Aleks G May 31 '13 at 18:08
3

Use LinkedHashMap , if you want insertion order back. By default HashMap's iterator doesn't guarantee insertion order.

Peeyush
  • 422
  • 3
  • 13
2

HashMap is not an ordered Collection. (It is not even a Collection) It is more like a dictionary.

If you want to perserve the order of the items you can either use a TreeMap or a LinkedHashMap.

The difference between these is that TreeMap keeps them ordered by their natural sort order while LinkedHashMap keeps the insertion order.

In most cases where you would like to have something like with using a List you can use the LinkedHashMap.

TreeMap uses a red-black tree for its internal implementation while LinkedHashMap uses doubly linked list.

My suggestion is that you should refer to the official documentation. There you will find thorough explanations.

Additionally the idiomatic way to iterate over Maps is this:

for(Integer key : map.keySet()) {
    String myString = map.get(key);
    // ...
}
Adam Arold
  • 29,285
  • 22
  • 112
  • 207