Sorting a Guava BiMap - java

I am new to the Guava library, but have found that the BiMap fits my needs nicely. My one issue is that I need to sort the values in my BiMap. Normally, I would have used a TreeMap due to its inherit sorting, but being able to invert the map to look at the keys as if they are values is a must.
So I was looking for advice from you experts about going about this. The solutions I see are:
1. Create a BiMap comparator and use my own map sorting utility.
2. Build my own 'BiTreeMap' data structure.
Is there a solution I haven't considered? Is there a 'Guava way' to do this that I missed? Thanks!

We don't currently have a sorted BiMap type because it's a little ambiguous how it would work: would the entries be sorted by the keys? By the values? Would the forward entries be sorted by the keys, and the inverse entries be sorted by the values?
Currently, the only real available alternative is ImmutableBiMap, which retains the ordering that you put the entries in -- so ImmutableBiMap.copyOf(Maps.newTreeMap(map)) would give you a BiMap sorted by the keys.
(We might more seriously consider providing a directly sorted BiMap if you filed a feature request with more details on your use case, though.)

Related

Using a HashMap as a Key for another HashMap

I have a requirement where I need to map a set of configurations with a set of values, ideally denoted by a Map<Map<String, Object>, Map<String, Object>> structure.
Both the configurations & the values part of the main Map are arbitrary & hence, I am unable to use a concrete class.
Please provide some feedback on this structure. Can a Map be used as a key for another Map. Doing a bit of research, I was able to establish that the Map's equals method utilizes all underlying Keys & Values to deem two Maps as equal. Also, the HashCode of a Map is based on the Hashcodes of the Map's Keys. This IMO should suffice the minimum requirements of using a Map as a key.
I would still like someone to validate this before I go ahead with the implementation. In case there is a better solution / design that someone can suggest, please feel free to do so.
EDIT
I ended up using a simple tilde ('~') & pipe ('|') separated String as the key & deconstructed it whenever needed. Thanks to all who helped.
Yes, a HashMap can be used as a key to another map, as the class properly overrides .equals() and .hashCode().
However it's broadly speaking a bad idea to use mutable types (such as HashMap) as Map keys or Set elements, because you violate the invariants these classes expect if the objects are mutated while in the collection.
While not quite what you're looking for, Guava offers several additional data structures such as Multiset, MultiMap, BiMap, Table which may be useful. They also offer immutable collections such as ImmutableMap which (because they can't be mutated) are safer to use as a Map key. Which isn't to say you should do so, simply that it's safe (if the keys and values are also immutable).
Consider posting a question exploring the problem that lead you to conclude a Map<Map<K, V>, Map<K, V>> structure was what you needed. You may get better answers to that question.

Collection Map in Java

I want to write my own Map in Java. I know how map works, but i don't really know where you can keep keys and values. Can i keep them for example in List? So the keys would be store in the list and values would be store in another list?
Best would be if you checked out some of the concepts behind HashMap, TreeMap, HeapMap etc.
Once you understand those concepts, you're far better prepared for writing your own map when it comes to speed.
In other words: unless you know the concepts of all available implementations, it is very unlikely your wheel-re-invention will be a better solution.
Also be sure to test your implementations very thoroughly, as Collection are the backbone and heart of any good application.
Two very very simple (but slow) solutions are these:
1) As suggested above, you can use an ArrayList<Pair> and add your custom getItemByKey() (in Java commonly named 'get') method.
2) You can use two arrays, both keeping the same size, and keeping keys and values matched by their respective indices.
For choosing the data structure there's not better than Array (not all time but almost) of Entries (key/value) because the main goal of map is to map objects for objects, so mapping keys to values.
Using arrays for fast and constant access O(1), but you have a little problem, when your map is full, you have to create new Array and copy old entries.
Note: HashMap works in the same way.

Is there a good Java library for generation of order preserving O(1) hash codes, based on a set of attributes and a comparator?

Given set of attributes and a comparator I'd like to generate an order preserving hash code that provides O(1) access. Is there a Java library for this sort of thing or would I have to design the hash function myself?
Try:
java.util.LinkedHashMap()
There is no single collection that will do this. Depending on the detail requirements there are several options to chose from.
For simplicity, I would just use a HashMap for lookups and when I need the sorted data, I'd make a copy of the values and sort it:
List<?> sorted = new ArrayList<?>(hashMap.values());
Collections.sort(sorted, Comparator<?>);
This suffices for most real world use cases.
You could also write your own super-container that internally holds the elements in two collections, one HashMap and maybe a TreeSet. You can then easily provide access methods that make use of the collection better for the purpose of the method. Just make sure you make additions and removals affect both the contained collections.

Key that yields multiple Results

I'm pretty new to programming so I'm sorry if this is a stupid question. I was wondering if there was a type of data that returns (possibly) more than one answer per key. For example:
TestType<int,String> test = new TestType<int,String>();
So if you typed, test.getKey(1), you could get {"hello","this","is","a","test"}.
Basically, is there a type of data that can return multiple answers, sort of like a HashMap and List combined?
Not in standard Java. However, you can use the Guava MultiMap collection type. There are other libraries that also provide a multi-map collection.
If for some reason you don't want to use a third-party library, you can also roll your own data structure. However, it is definitely reinventing the wheel and it's a bit of a pain. You would define test to be a Map<Integer, Set<String>> and then write access methods to initialize the key entry with an empty set under appropriate conditions.
Note that Java does not allow primitive types (e.g., int, as you are using) to be used as generic type parameter values. You'll have to use Integer. Because of autoboxing, you can still use test.get(1) to retrieve the values stored under the key 1.
You might want to use MultiMap from apache commons collections, and its specific implementation MultiHashMap
You could also use a Map<Integer,List<String>> - as you suggested.
What you're asking for is called a multimap, there are several implementations in Guava and another one in Apache commons collections.
Java does not offer a multimap since it is not used frequently (their statement). But SUN offers a small example on how to create a multimap yourself using a Map and a List as follows:
Map<String, List<String>> m = new HashMap<String, List<String>>();
You can see an example here in Java Collections/Maps. Check the paragraph on multimaps for example code
Amit's on the right track. You can also create a class for the answer. This could help you increase encapsulation.
Map<Integer, MyAnswer>
where MyAnswer could include attributes for the data you wish to manage. Implementing your own class here gives you a world of possibilities.

MultiMap vs MultiValue Map

At one place i have to use a map with many values mapped to a single key, so i was wondering whether there is any significant performance distinction between using HashMap of key, list and MultiMap of key , values in java.
You can try it but I doubt there is much difference as it does much the same thing.
IMHO The advantage is simpler/clearer code which is usually more important than performance.
I'd recommend to use google collections if you want to use a more convenient implementation of a Multimap. In case you don't want to introduce a new dependency, HashMap<Key, Collection<Value>> should do the trick which is pretty much what apache.collections HashMultiMap does.
If it is a Map Key-> Values, use a Map implementation.
As you will have some Values with the same Keys, use the http://guava-libraries.googlecode.com/svn/tags/release09/javadoc/com/google/common/collect/HashMultiset.html from the Google Collection (now guava library, http://code.google.com/p/guava-libraries/ ) for your task.
Hash provides O(1) which is fast and does nothing with the size of elements.
Regarding to Multimap, you could put values in dependent collection (List, Set). Different collection implementations provides different performance.
EDIT: As I commented on Sebastian's answer. You could use Guava which provides different value collection implemantions: HashMultiMap (HashMap<KEY, HashSet<VALUE>>), ArrayListMultiMap (HashMap<KEY, ArrayList<VALUE>>)...

Categories