How preserve order of LinkedHashMap while serializing to GWT AutoBean? - java

I've tried using Map, HashMap and LinkedHashMap as a type for AutoBean factory and always after serializing it's changing initial elements order.
I don't want to send additional ArrayList that will hold the order data. Is there a way to force AutoBean to keep order in a Map?

http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
The order of a map is defined as the order in which the iterators on
the map's collection views return their elements. Some map
implementations, like the TreeMap class, make specific guarantees as
to their order; others, like the HashMap class, do not.
GWT doesn't make any alterations to Map-based classes. Map and many of its subclasses do not keep order of insertion for performance reasons. LinkedHashMap, by design, does keep its insertion order. That is, of course, assuming you're starting with a LinkedHashMap and not constructing it from another type of Map which may not actually preserve its order during the insertion, causing the LinkedHashMap to have a different order than you're expecting.
I'm wondering why you need to keep the initial order anyway, and why are you using Map if that's what you want?

Apparently, and at least in GWT 2.4, LinkedHashMap.clone() in GWT returns a HashMap, in contrast to pure Java behavior. AutoBean probably relies on clone() which messes up the order in the end.

Related

Problems that we use a BiMap to solve

I'm reviewing the capabilities of Googles Guava API and I ran into a data structure that I haven't seen used in my 'real world programming' experience, namely, the BiMap. Is the only benefit of this construct the ability to quickly retrieve a key, for a given value? Are there any problems where the solution is best expressed using a BiMap?
Any time you want to be able to do a reverse lookup without having to populate two maps. For instance a phone directory where you would like to lookup the phone number by name, but would also like to do a reverse lookup to get the name from the number.
Louis mentioned the memory savings possible in a BiMap implementation. That's the only thing that you can't get by wrapping two Map instances. Still, if you let us wrap the Map instances for you, we can take care of a few edges cases. (You could handle all these yourself, but why bother? :))
If you call put(newKey, existingValue), we'll error out immediately to keep the two maps in sync, rather than adding the entry to one map before realizing that it conflicts with an existing mapping in the other. (We provide forcePut if you do want to override the existing value.) We provide similar safeguards for inserting null or other invalid values.
BiMap views keep the two maps in sync: If you remove an element from the entrySet of the original BiMap, its corresponding entry is also removed from the inverse. We do the same kind of thing in Entry.setValue.
We handle serialization: A BiMap and its inverse stay "connected," and the entries are serialized only once.
We provide a smart implementation of inverse() so that foo.inverse().inverse() returns foo, rather than a wrapper of a wrapper.
We override values() to return a Set. This set is identical to what you'd get from inverse().keySet() except that it maintains the same iteration order as the original BiMap.

Java map content comparison

Here is a tricky data structure and data organization case.
I have an application that reads data from large files and produces objects of various types (e.g., Boolean, Integer, String) that are categorized in a few (less than a dozen) groups and then stored in a database.
Each object is currently stored in a single HashMap<String, Object> data structure. Each such HashMap corresponds to a single category (group). Each database record is built from the information in all the objects contained in all categories (HashMap data structures).
A requirement has appeared for checking whether subsequent records are "equivalent" in the number and type of columns, where equivalence must be verified across all maps by comparing the name (HashMap key) and the type (actual class) of each stored object.
I am looking for an efficient way of implementing this functionality, while maintaining the original object categorization, because listing objects by category in the fastest possible way is also a requirement.
An idea would be to just sort the keys (e.g., by replacing each HashMap with a TreeMap) and then walk over all maps. An alternative would be to just copy everything in a TreeMap for comparison purposes only.
What would be the most efficient way of implementing this functionality?
Also, if how would you go about finding the difference (i.e., the fields added and those removed), between successive records?
Create a meta SortedSet in which you store all the created maps.
Means SortedSet<Map<String,Object>> e.g. a TreeSet which as a custom Comparator<Map<String,Object>> which does check exactly your requirements of same number and names of keys and same object type per value.
You can then use the contains() method of this meta set structure to find out if a similar record does already exist.
==== EDIT ====
Since I've misundertood the relation between database records and the maps in the first place, I've to change some semantics my answer now of course a little bit.
Still I'would use the mentioned SortedSet<Map<String,Object>> but of course the Map<String,Object> would now point to that Map you and havexy suggested.
On the other hand could it be a step forward to use a Set<Set<KeyAndType>> or SortedSet<Set<KeyAndType>> where your KeyAndType will only contain the key and the type with appropriate Comparable implementation or equals with hashcode.
Why? You asked how to find the differences between two records? If each record relates to one of those inner Set<KeyAndType> you can easily use retainAll() to form the intersection of two successive Sets.
If you would compare this to the idea of a SortedSet<Map<String,Object>>, in both ways you would have the logic which differenciates between the fields within the comparator, one time comparing inner sets, one time comparing inner maps. And since this information gets lost when the surrounding set is constructed, it will be hard to get the differences between two records later on, if you do not have another reduced structure which is easy to use to find such differences. And since such a Set<KeyAndType> could act as key as well as as easy base for comparison between two records, it could be a good candidate to be used for both purposes.
If furthermore you wanna keep the relation between such a Set<KeyAndType> to your record or the group of Map<String,Object> your meta structure could be something like:
Map<Set<KeyAndType>,DatabaseRecord> or Map<Set<KeyAndType>,GroupOfMaps> implemented by a simple LinkedHashMap which allows simple iteration in original order.
One soln is to keep both category based HashMap and combined TreeMap. This will have slight more memory requirement, not much though, as you ll just keep the same reference in both of them.
So whenever you are adding/removing to HashMap you will do the same operation in the TreeMap too. This way both will always be in sync.
You can then use TreeMap for comparison, whether you want comparison of type of object or actual content comparison.

Using HashMap as Collection in Java

JAXB doesn't let you unmarshal already existing xml structures into HashMaps if they are not exactly the way JAXB expects them.
JAXB is fine with handling e.g. LinkedLists and filling them.
I was thinking of creating a interface with a getKey() method and a wrapper around the HashMap taking all objects that implement that interface. The wrapper can then use the getKey() method for all key related features of the map. The wrapper could then easily implement the Collection or List interface.
Because this idea doesn't seem to innovative to me I presume that it already exists in some package, but I'm not googling correctly for it... Can someone please name a good lib that can do this, or do I have to code this myself?
You might consider extending ForwardingList of guava, and using a HashMap in the back. I don't know of any implementation that will leave you only the actual mapping.
Another alternative is creating JAXB XmlAdapter to adapt the values to your map. I think this one is more appropriate.
If all you are trying to pass the information content of a Map as a Collection, use Map.entrySet(). That gives you a Set<Map.EntrySet<K,V>> object; i.e. a collection whose elements are the key/value pairs of the Map. To reconstruct a Map from the collection, you will need to iterate the set and perform an put for each element.

Java TreeMap alternative

I am in need of a data structure that has fast insert, fast retrieve, and can be returned in order. This sounds like a tree map but I need the order of the elements to be based on a creation time NOT on the order of the keys I am storing.
In other words, I still want to be able to insert and retrieve based on a key (which is a string) but I want to get the items back in order of creation time (which is a date). Of course I want this to be as fast as possible and not to have to create my own data type.
The tree map will not work in this case because it uses the key for insert and retrieve AND for ordering the results. Is there another standard data type that would satisfy my requirements?
Sounds like you want a LinkedHashMap.
use a Map and a TreeSet?
One Map<String,Object> just to store the key/value pairs. It doesn't have to be a TreeMap. Because you're not using that map for its sorting.
The TreeSet<Object> is use for its sorting.
You can always wrap 2 collection instances in one wrapper Map class that you create yourself. If you really need it to look like one map. Make sure your chosen Comparator uses the creation date.
The other guys are suggesting a LinkedHashMap. But I don't think you want to maintain "insert order". But instead you want it sorting by a comparator of some type (maybe Object.equals).
If I understand your question correctly, you can create your own Comparator and use public TreeMap(Comparator<? super K> comparator) constructor.

Looking for Java Map implementation that supports getKeysForValue

I'm looking for an implementation of java.util.Map that has a method that will return all they keys mapped to a given value, that is, there are multiple keys map to the same value. I've looked at Google Collections and Apache Commons and didn't notice anything. Of course, I could iterate through the keyset and check each corresponding value or use two maps, but I was hoping there was something available already built.
I don't know if that solution is good for you, but you can implement easily that by using a standard map from keys to values and a MultiMap from values to key.
Of course you'll have to take care of the syncronization of the two structures, IE when you remove a key from the map, you have to remove the key itself from the set of keys mapped to the value in the multimap.
It doesn't seems difficult to implement, maybe a bit heavy from the memory overhead aspect.
What you're looking for here is a bidirectional map, for which there is an implementation in commons collections.
Your value objects could have a property (of type ArrayList maybe) that holds all the keys.
Then you extend HashMap (or whatever Map impl you use) and override put so that when you put and object for a key you also add the key to your object's list of keys.
I can't find a ready made class that supports values with multiple keys. However you could re-implement the Apache Commons DualHashBidiMap using a MultiHashMap in place of one of the HashMaps.

Categories