Java Map question - java

I have one Map that contains some names and numbers
Map<String,Integer> abc = new HashMap<String,Integer>();
It works fine. I can put some values in it but when I call it in different class it gives me wrong order. For example:
I putted
abc.put("a",1);
abc.put("b",5);
abc.put("c",3);
Iterator<String> iter = abc.keySet().iterator();
while (iter.hasNext()) {
String name = iter.next();
System.out.println(name);
}
some time it returns the order (b,a,c) and some time (a,c,b).
What is wrong with it? Is there any step that I am missing when I call this map?
Edit:
I changed to HashMap and result is still same

The only thing that's wrong is your expectations. The Map interface makes no guarantees about iteration order, and the HashMap implementation is based on hash functions which means the iteration order is basically random, and will sometimes change completely when new elements are added.
If you want a specific iteration order, you have thee options:
The SortedMap interfaces with its TreeMap implementation - these guarantee an iteration order according to the natural ordering of the keys (or an ordering imposed by a Comparator instance)
The LinkedHashMap class iterates in the order the elements were added to the map.
Use a List instead of a Map - this has a well-defined iteration order that you can influence in detail.

I think you need LinkedHashMap.

A TreeMap will always have keys in their natural order (unless you provide a comparator) If you are seeing the order any differently it will be the way you are looking at the map and what you are doing with it. If in doubt, use a debugger and you will see the order is sorted.

If you wish to get map values in the same order you used to insert them use LinkedHashMap instead.

Related

Navigable Map - Sorted Map yet un-ordered

Hi everyone please help, I discovered the NavigableMap today and initially it worked for me until I did the following.
When I populate the NavigableMap, notice from the end of the string value, I have added the values 1-4 and then 5.
The string layout is for example "23816012269<1>", the last value <#> makes this unique because I am using it later in the code.
All values up until 4 are duplicates (23816012269) , then 23806012269<5> is a new value prefixed with a different string/number and I will continue with new duplicates (suffixed with the next sequence <5> <#> number etc).
The problem is, when I populate the NavigableMap in the order that you see below, it puts ("238060122695",...) at the first entry of the NavigableMap, even though this was added to the NavigableMap very last.
Now when I use the NavigableMap.firstEntry().getKey() it reads "238060122695" as the first entry.
I need to read 238160122691 as the first entry because this was added to the map as the first entry.
Delving into the string value I know that 2380 comes before 2381, regardless, why does it treat it as the first entry when I added it last, is it because of the SortedMap interface that does this.? How do I avoid
This is code in the order being executed:
NavigableMap.put("238160122691", arrayListValue);
NavigableMap.put("238160122692", arrayListValue);
NavigableMap.put("238160122693", arrayListValue);
NavigableMap.put("238160122694", arrayListValue);
NavigableMap.put("238060122695", arrayListValue);
A NavigableMap is sorted:
A SortedMap extended with navigation methods returning the closest matches for given search targets. [...]
A NavigableMap may be accessed and traversed in either ascending or descending key order.
If you want entries to be in insertion order, use a LinkedHashMap:
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order).
Delving into the string value I know that 2380 comes before 2381, regardless, why does it treat it as the first entry when I added it last, is it because of the SortedMap interface that does this?
There seems to be a misunderstanding of what NavigableMap and its implementing classing like TreeMap are doing. They do not sort the elements in order of insertion, but by their natural order (i.e. how they compareTo each other), or given another Comparator.
How do I avoid?
Well, you could wrap your string keys into a data structure that also has a number showing when it was inserted into the map, and provide a Comparator or compareTo method that sorts by that number. But more likely, NavigableMap is just not the right data structure for you. Have you considered just using a List or Queue, or maybe a LinkedHashMap as suggested in comments.
Thank you All, I have moved back to the LinkedList as suggested by everyone.
I then found the use of the ListIterator to find the the next entry and stored that in a variable to compare to the next Iteration.
ListIterator<Map.Entry<String, ArrayList<DataModel>>> listIterator = new LinkedList(myHashMap.entrySet()).listIterator();
String previousk, nextk = null;
Boolean entered = false;
while (listIterator.hasNext())
{
if(entered){
previousk = nextk.substring(0,12);
if(previousk != nextk.substring(0,12)){
*Set the flag here to be used*
}
}
nextk = listIterator.next().getKey();
entered = true;
System.out.println(nextk);
}

ArrayMap put method pushes elements in strange order

I am using ArrayMap for first time in my project and I thought it works just like an array. I expected when I use .put method it inserts it at next index.
But in my case this is not true - after I added all elements one by one the first element I added ended up at index 4 which is kind of strange.
Here are the first three steps which I add elements:
1 - Salads:
2 - Soups:
3 - Appetizers:
So somehow on second step "Soup" element was inserted in index 0 instead of 1 as I was expecting, but strangely on third step "Appetizers" was inserted as expected after "Soup".
This is the code I am using to push key and value pair:
function ArrayMap<String, DMType> addElement(String typeKey, DMType type) {
ArrayMap<String, DMType> types = new ArrayMap<>();
types.put(typeKey, type);
return types;
}
Am I missing something about the behavior of ArrayMap?
Yeah it is misleading because of the name but ArrayMap does no gurantee order unlike arrays.
ArrayMap is a generic key->value mapping data structure that is
designed to be more memory efficient than a traditional HashMap.
ArrayMap is actually a Map:
public class ArrayMap extends SimpleArrayMap implements Map
If you want the Map functionality with order guranteed use LinkedHashMap instead.
LinkedHashMap defines the iteration ordering, which is normally the
order in which keys were inserted into the map (insertion-order).
documentation
I thought it works just like an array
No, it works like a map, because it is a map. It is similar to a HashMap, but more memory efficient for smaller data sets.
It's order shouldn't and doesn't matter. Under the hood, it is implemented using
an array which has an order since arrays do. This inherently gives the ArrayMap an order, but that is not part of it's API anyway. Just like which memory slot your Java objects are in, you shouldn't care about the order here either.
It doesn't work as an array, I don't see Array in the name but Map and the documentation clearly states that behaves as a generic key->value mapping, more efficient (memory wise) than traditional HashMap implementation.
Actually I don't see why you care about the order compared to the insertion one. Data is private inside the class and you have no way to obtain the element by the index, so you are basically wondering about a private implementation which is irrelevant for its usage.
If you really want to understand how it stores its data you should take a look at the source code.
ArrayMap does NOT work like an Array, instead, it works like a HashMap with performance optimizations.
The internal sequence of the key-value pair is not guaranteed as it is NOT part of the contract.
In your case, what you really want to use is probably an ArrayList<Element>, where the Element class is defined like this:
public class Element{
private final String typeKey;
private final DMType type;
public Element(String typeKey, DMType type){
this.typeKey = typeKey;
this.type = type;
}
}
If you don't want a new Class just to store the result, and you want to keep the sequence, you can use a LinkedHashMap<String, DMType>. As the document specifies:
Class LinkedHashMap
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order). Note that insertion order is not affected if a key is re-inserted into the map. (A key k is reinserted into a map m if m.put(k, v) is invoked when m.containsKey(k) would return true immediately prior to the invocation.)

Are there any map implementations in Java that will give me a map where the entries are ordered in the same way I put them in?

What I would like to do is this:
for (Entry<Foo, Foo> myEntry : myMap.entryList())
{
if (someCondition(myEntry.getKey()))
{
doSomething(myEntry.getValue())
}
}
The order is important because myEntry.getValue() will point to a key that will be reached later on. Is there a Map implementation that guarantees the order of the entries and allows me to iterate over the entries in that order? I found SortedMap, but it looks like SortedMaps sort the keys. This isn't quite what I need. I simply want to get my entries out of my map in the same order that I put them in.
For those wondering what I'm trying to do, myMap represents a hierarchy of Foo objects. When the condition is met in 'someCondition', I mark the parent of the Foo (which happens to be the value of the entry). Later on when the parent becomes a key, I'll know that I've marked it before and will take action accordingly. Right now I've created a recursive 'markParent' call, but if I could iterate over the map in a known order, I wouldn't need to do that.
You mean like LinkedHashMap? ;-)
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order). Note that insertion order is not affected if a key is re-inserted into the map. (A key k is reinserted into a map m if m.put(k, v) is invoked when m.containsKey(k) would return true immediately prior to the invocation.)
(My emphasis)
FWIW, how I got there, to help if you need to find similar information in the future: I had a vague recollection one of the JDK classes did that, so went to Map and read through the list of "Known Implementing Classes." In this case, I knew the name when I saw it, but I figure even if I hadn't known it, LinkedHashMap suggests order, so... :-)
LinkedHashMap will maintain the order of insertion which using LinkedList internally. And if you want to define any custom order, you can use SortedMap like TreeMap instead.

How to avoid items being re-ordered when put into java HashMap

I'm creating a new Map and pushing strings into it (no big deal) -but I've noticed that the strings are being re-ordered as the map grows. Is it possible to stop this re-ordering that occurs so the items in the map retain the order the were put in with?
Map<String,String> x = new HashMap<String, String>();
x.put("a","b");
x.put("a","c");
x.put("a","d");
x.put("1","2");
x.put("1","3");
x.put("1","4");
//this shows them out of order sadly...
for (Map.Entry<String, String> entry : x.entrySet()) {
System.out.println("IN THIS ORDER ... " + entry.getValue());
}
If you care about order, you can use a SortedMap. The actual class which implements the interface (at least for most scenarios) is a TreeMap. Alternatively, LinkedHashMap also maintains its order, while still utilizing a hashtable-based container.
You can keep it with LinkedHashMap.
A HashMap in java is not sorted http://download.oracle.com/javase/1,5.0/docs/api/java/util/HashMap.html. If you want predictable iteration order use a LinkedHashMap instead: http://download.oracle.com/javase/1.4.2/docs/api/java/util/LinkedHashMap.html
Heres a good discussion on the difference: How is the implementation of LinkedHashMap different from HashMap?
The previous answers are correct in that you should use an implementation of Map that maintains ordering. LinkedHashMap and SortedMap each do these things.
However, the takeaway point is that not all collections maintain order and if order is important to you, you should choose the appropriate implementation. Generic HashMaps do not maintain order, do not claim to do so and cannot be set to do so.

hashtable values reordered

I have a hashtable, which contains strings for example, when I use put method as below
hashtable.put("1","A");
hashtable.put("1","B");
hashtable.put("1","C");
hashtable.put("1","D");
hashtable.put("1","E");
Then when I try to print it back it doesn't print in same order, Any one knows why would something like this happen?
Collection c = ht.values();
Iterator itr = c.iterator();
while(itr.hasNext())
System.out.println(itr.next());
Thanks
Max
A Hashtable does not guarantee any kind of ordering.
If you want to preserve insertion order, use a LinkedHashMap. However, the contract is slightly different than a Hashtable in that it allows null elements.
you should use LinkedHashMap if you want to print items in order.
That is simply the property of a hash table -- it makes no guarantee about ordering. Do you want to use a LinkedHashMap instead?
HashTable doesnot keep order.It will print randomly.You should go for LinkedHashMap.You can use LinkedHashMap in the same manner as you did for HashMap.Just put LinkedHashMap in place of HashMap.LinkedHashMap keeps the order of data in which you enter into it.

Categories

Resources