I just took the Google Collections Library and start playing with it. I discovered a class I needed in many and many situations in the past. I’m talking about Multimap. Actually Multimap is an interface having a few classes implementing it. Along with some other interfaces it comes to fulfill a gap in the Java Collections.
Before giving a few examples about it, a few words about Google Collections. This is a really light java framework, build in one jar of about 300 kb. Currently only the Alpha version is released, but it doesn’t mean it’s not tested. In the Google Collection FAQ on Google Code the authors explain what 0.5 Alpha means” “We already use this library extensively in production for services like GMail, Reader, Blogger, Docs & Spreadsheets, AdWords, AdSense and dozens more. We consider it to be pretty safe. However, during the alpha period, we do reserve the right to make changes of any kind to it at any time.”
All you have to do is to download the latest Google Snapshot, unzip google-collect-snapshot-20080321.jar and then add it to your classpath. In our sample we are going to use one class and one interface (classes link to javadocs): com.google.common.collect.HashMultimap, com.google.common.collect.Multimap. Here is an example of Google Collection in action:
Multimap multimap = new HashMultimap(); multimap.put("key1", "value1A"); multimap.put("key2", "value1A"); multimap.put("key1", "value1B"); System.out.println(multimap.get("key1").toString());
Something similar using Generics:
Multimap<String, Multimap<String,String>> peoples = new HashMultimap<String,Multimap<String,String>>(); Multimap<String,String> vehicles = new HashMultimap<String,String>(); vehicles.put("Ferrari", "Silver Ferrari"); vehicles.put("Ferrari", "Red Ferrari"); vehicles.put("Car", "Honda Civic"); vehicles.put("Bycicle", "33 Gears Bycicle"); peoples.put("Kevin S.", vehicles); System.out.println(peoples);
And the final snippet using some classes created by us. We use Google Collection to keep some existing ‘has’ relations:
Multimap<Person, Multimap<String,Vehicle>> samepeoples = new HashMultimap<Person,Multimap<String,Vehicle>>(); Multimap<String,Vehicle> newvehicles = new HashMultimap<String,Vehicle>(); newvehicles.put("Porsche", new Car("Silver Porsche")); newvehicles.put("Porsche", new Car("Red Porsche")); newvehicles.put("Car", new Car("Honda Civic")); newvehicles.put("Bycicle", new Bycicle("33 Gears Bycicle")); samepeoples.put(new Person("Kevin S."), newvehicles); System.out.println(samepeoples);
The result of the test program printed to the console:
[value1B, value1A] {Kevin S.=[{Car=[Honda Civic], Ferrari=[Red Ferrari, Silver Ferrari], Bycicle=[33 Gears Bycicle]}]} {Kevin S.=[{Car=[Honda Civic], Porsche=[Silver Porsche, Red Porsche], Bycicle=[33 Gears Bycicle]}]}
Here are the classes I created to for the previous snippet:
class Person { private String name; public Person(String name) { this.name = name; } public String toString() { return name; } } class Vehicle { private String name; public Vehicle(String name) { this.name = name; } public String toString() { return name; } } class Car extends Vehicle { public Car(String name) { super(name); } } class Bycicle extends Vehicle { public Bycicle(String name) { super(name); } }
Many situations occurred in the past when I had to organize some data in some hierarchical structures. I didn’t want to create some classes keep hierarchical structures so I used hashmaps, hashtables or even sets or lists, storing Set or some other collection as values. Some sort of sets of sets, maps of lists and so on. The Multimap comes to fulfill this need and opens the way for a multitude of uses of collections. Until now, when I thought how I used the collections I felt a little bit that I'm doing something wrong since is not something that Java Collection was providing. Now, that I know that Google has this class I feel better.
Just think to the coupling degree if we modify the classes to keep association relations. For example a Person class should be enhanced to keep collection of Vehicles so the person class will be coupled with the Vehicle interface. If we just want to add some 1-to-many relations between some existing classes, changing them might not be the best way of doing it.