1

I need to have a resultset converted into a Map of Maps. The reason why I'm not using a List of Maps is because I don't want to iterate through the entire List to get a specific row.

The problem I am facing now is that the HashMap's entries aren't ordered anymore if the index is greater than 16.

Now I tried the following for a simple test:

    public static void main(String[] args) {

    Map<Integer, String> map = new HashMap<Integer, String>();

    //creating 20 rows from 1 to 20
    for (int i = 1; i <= 20; i++){
        map.put(i, "ROW "+i);   
    }


    //returning all the rows the map contains. Look at position 16.
    for(int key : map.keySet()){
        System.out.println(key);    
    }
}

And the output is the following (look at position 16 to 20. They are totally unordered):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 16 19 18 20

I would really appreciate it, if someone can explain why that happens.

And by the way:

i cant use something like this:

for (int i = 0; i < map.size; i++){
    map.get(i) //...and so on

}

because I don't know if the index exists. It may be that that the index from 200 to 800 doesnt exist. So it would be better only to iterate through exisiting entries of the map.

Mattias Isegran Bergander
  • 11,811
  • 2
  • 41
  • 49
Chris
  • 566
  • 1
  • 8
  • 20

6 Answers6

6

A HashMap is not ordered or sorted. If you need an insertion ordered Mapuse java.util.LinkedHashMap. If you need a Mapsorted by the key, use a SortedMapsuch as java.util.TreeMap

Mattias Isegran Bergander
  • 11,811
  • 2
  • 41
  • 49
4

You should use either a TreeMap or a LinkedHashMap instead of a HashMap depending on if you want elements sorted by their natural order or insertion order respectively.

A HashMap makes no guarantees about the ordering of keys. The other two Map implementations I referenced do.

A TreeMap will sort keys based on their natural order which means the keys must implement Comparable or you have to provide your own comparator in order to determine the ordering.

A LinkedHashMap will keep the keys ordered based on when they are inserted.

Since they behavior you're looking for is for the keys to be naturally ordered and you happen to be inserting the keys in order yourself, either implementation would work for this case.

Mike Deck
  • 18,045
  • 16
  • 68
  • 92
3

You can use a LinkedHashMap to keep order of insertion instead since basic maps do not guarantee the order of keys.

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
3

How about using TreeMap? Instead of HashMap. You can provide even your own ordering.

Xeon
  • 5,949
  • 5
  • 31
  • 52
  • TreeMap wastes more resources, it doesn't sound like the OP needs custom sorting, just keeping insertion order. – Ruan Mendes May 19 '12 at 05:33
2

The reason why I'm not using a List of Maps is because I don't want to iterate through the entire List to get a specific row.

So make it an ArrayList instead of a LinkedList. That way, list.get(1234) will go straight to that entry -- it won't iterate over the 1234 entries before it.

yshavit
  • 42,327
  • 7
  • 87
  • 124
1

I think the problem you are facing is because of the default size of HashMap.

According to standard java documentation,

/**
 * The default initial capacity - MUST be a power of two.
 */
static final int DEFAULT_INITIAL_CAPACITY = 16;
/**
 * The load factor used when none specified in constructor.
 */
static final float DEFAULT_LOAD_FACTOR = 0.75f;

/**
 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
 * (16) and the default load factor (0.75).
 */
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR;
    threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
    table = new Entry[DEFAULT_INITIAL_CAPACITY];
    init();
}

So, you are not getting proper output after 16th element.

According to JavaDoc,

/**
 * Constructs an empty <tt>HashMap</tt> with the specified initial
 * capacity and the default load factor (0.75).
 *
 * @param  initialCapacity the initial capacity.
 * @throws IllegalArgumentException if the initial capacity is negative.
 */
public HashMap(int initialCapacity) {
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

try the following (Parameterized constructor with initial capacity),

Map<Integer, String> map = new HashMap<Integer, String>(32);
Priyank Doshi
  • 12,895
  • 18
  • 59
  • 82