Is the decision by Google similar to the one for SortedMultiSet (stackoverflow question)
or is it because there is no use of MultiKeyMap?
I am aware that an alternate for MultiKeyMap can be to use a custom Class as a key which contains the multiple keys as its class members. On the contrary, I like the concept of specifying multiple keys when calling the get of the MultiKeyMap.
Apache's version of MultiKeyMap is great but I'm severely missing Generics and therefore looked into Google Collections for a modern implementation of it. If someone has any idea why Google hasn't supported it yet or there's a better alternative for it then please respond.
FYI, the accepted answer was answered in March 2010, but as of September 2010 Guava included Table.
Collections explained - Table
Tables utility class
Table javadoc
We have a very nice implementation of a two-tiered map , which we call a "table" (K1 is the "row key" and K2 is the "column key"), and we just haven't gotten it released yet. Past two keys, though, is diminishing returns.
I think generics might be the showstopper for implementation here. If you look at just the Map interface there are generic specifiers for the key type (K) and the value type (V). I don't believe it would be possible to specify it using generics easily without separating the implementations into multiple classes (one for each number of key components).
You would need a class for each:
MultiKeyMap2<K1,K2,V>
MultiKeyMap3<K1,K2,K3,V>
MultiKeyMap4<K1,K2,K3,K4,V>
MultiKeyMap5<K1,K2,K3,K4,K5,V>
The underlying implementation is basically doing what you suggest (using a custom class). However, it doesn't formally create a class for it, everything is inlined. It's really an implementation detail. But to use the Google collections a custom class to perform the same thing would operate much the same way I'm sure to implement hashCode() and equals().
Related
Why NavigableMap interface was created with additional method definitions and extended with SortedMap, while they could have added it in SortedMap interface and as usual implemented them in TreeMap?
The internet is filled with answers that it was included to navigate across the map. Here what does navigate mean?
SortedMap interface is already published (since 1.2). That means that there are maybe hundreds or thousands classes somewhere out there that rely on SortedMap. If you would add new methods to SortedMap in 1.6, without providing default method implementations, this would break all those classes that implement SortedMap. Given that so much stuff relies on Java, this would break literally everything on the planet. I hope that it is obvious that "not breaking everything on the entire planet" is a good enough reason for not adding some obscure methods willy-nilly (It's obviously an overly dramatic and tongue-in-cheek description of what would actually happen. If the maintainers of the Java standard library did that, then nobody would use the new version, and someone would probably file a bug report, that's it).
The documentation states quite clearly what "to navigate" means:
Methods lowerEntry, floorEntry, ceilingEntry, and higherEntry
https://docs.oracle.com/javase/7/docs/api/java/util/NavigableMap.html
It means that you can not only lookup and traverse, but also find entries which are "close" to the requested key.
I won't speak to what uses NavigateMap has but in terms of why the SortedMap interface was not modified instead of adding a new interface; that was because it would break existing implementations. As you point out TreeMap etc. could be updated to implement the new methods but what about custom implementations of SortedMap? So any legacy code out there that upgrades to JRE 1.6+ would need to search the code base and implement these new methods, but Java advertises itself as being backwards compatible (for Java 6 at least when NavigateMap was added)
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.
Given an object we will call loc that simply holds 2 int member values, I believe I need to come up with a mechanism to generate a hashcode for the object. What I tried below doesn't work as it uses an object reference, and the 2 references will be different despite having the same members variables.
Map<Loc,String> mapTest = new HashMap<Loc,String>();
mapTest.put(new Loc(1,2), "String 1");
mapTest.put(new Loc(0,1), "String 2");
mapTest.put(new Loc(2,2), "String 3");
System.out.println("Should be String 2 " + mapTest.get(new Loc(0,1)));
After some reading it seems I need to roll my own hashcode for this object, and use that hashcode as the key. Just wanted to confirm that I am on the right track here, and if someone could guide me to simple implementations to look at that would be excellent.
Thanks
Yes, you need to override equals() and hashCode() and they need to behave consistently (that is, equal objects have to have the same hash code). No you do not use the hash coe directly; Map uses it.
Yes, you're on the right track.
See articles like this for more details.
There are a lot of different ways to implement a hashcode, you'll probably just want to combine the hashcodes of each integer primitive.
Writing correct equals and hashcode methods can be tricky and the consequences of getting it wrong can be subtle and annoying. If you are able to, I would use the apache commons-lang library and take advantage of the HashCodeBuilder and EqualsBuilder classes. They will make it much easier to get the implementations right. The benefit of using these libraries is that it is much harder to get the boiler plate wrong, they hide the visual noise these methods tend to create and they make it harder for someone to come a long later and mess it up. Of course another alternative is to let your IDE generate those methods for you which works but just creates more of the noisy code vomit Java is known for.
If you want to use your type as a key type in a map, it's essential that it provides sane implementations of equals and hashCode. Fortunately, you don't have to write these implementations manually. Eclipse (and I guess other IDEs as well) can generate this boilerplate for you. Or you can even use Project Lombok for that.
Ideally the object to be used as a key in a map should be immutable. This can save you from many bugs led to by the equality issues in the context of mutation.
You need to implement both hashCode() and equals(). Joshua Bloch's Effective Java should be the definitive source on the "how" part of your question, and I'm not sure if it's okay to reproduce it here, so I'll just refer you to it.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have had a quick scan of the Guava API and the new collection types it provides(Multimap and BiMap for example appear useful) and I am thinking of including the library in the project(s) I work on.
However, I also have a reticence to include libraries willy-nilly if they are of no great benefit and learning the features wastes valuable time.
Have you included the Guava library in your project and has it proved useful in any unexpected way? Would you always use it in the future? What has been its main benefit/time saver? What are its hidden features?
Seriously, everything in Guava is useful. I've been using it for quite a while, and am still always discovering something new I can do with it that takes less code than doing it by hand.
Some things others have not really mentioned that I love:
Multimaps are just great. Any time you would use something like Map<Foo, Collection<Bar>>, use a multimap instead and save yourself a ton of tedious checking for an existing collection mapped to a key and creating and adding it if it isn't there.
Ordering is great for building Comparators that behave just how you want.
Maps.uniqueIndex and Multimaps.index: these methods take an Iterable and a Function and build an ImmutableMap or ImmutableListMultimap that indexes the values in the Iterable by the result of applying the function to each. So with a function that retrieves the ID of an item, you can index a list of items by their ID in one line.
The functional stuff it provides... filter, transform, etc. Despite the verbosity of using classes for Functions and Predicates, I've found this useful. I give an example of one way to make this read nicely here.
ComparisonChain is a small, easily overlooked class that's useful when you want to write a comparison method that compares multiple values in succession and should return when the first difference is found. It removes all the tedium of that, making it just a few lines of chained method calls.
Objects.equal(Object,Object) - null safe equals.
Objects.hashCode(Object...) - easy way to get a hash code based on multiple fields of your class.
Objects.firstNonNull(Object,Object) - reduces the code for getting a default value if the first value is null, especially if the first value is the result of a method call (you'd have to assign it to a variable before doing this the normal way).
CharMatchers were already mentioned, but they're very powerful.
Throwables lets you do some nice things with throwables, such as Throwables.propagate which rethrows a throwable if it's a RuntimeException or an Error and wraps it in a RuntimeException and throws that otherwise.
I could certainly go on, but I have to get to work. =) Anyway, despite my having listed some things I like here, the fact is that everything in Guava is useful in some situation or another. Much of it is useful very often. As you use it, you'll discover more uses. Not using it will feel a bit like having one hand tied behind your back.
I've been effectively using Guava for a couple of years, inside Google - and it's wonderful.
The parts I'm particularly fond of are:
Charsets.* - so simple, so useful
Collections
IO handling (read a resource completely in a single line, etc)
Splitter/Joiner
Preconditions
I initially used it for collections shorthands. For example, instead of:
Map<String, Map<Long, List<String>>> map = new HashMap<String, Map<Long, List<String>>>();
you can do this:
Map<String, Map<Long, List<String>>> map = Maps.newHashMap();
It's also easy to populate maps:
ImmutableMap<String,String> map = ImmutableMap.of("key1", "value1", "key2", "value2");
Now, I have discovered some other useful utilities present in Guava. For example, the CharMatcher class allows you to match sequences of characters. You can do:
CharMatcher.inRange('a','z').or(inRange('A','Z'));
or
String phoneNumber = CharMatcher.DIGIT.retainFrom("my phone number is 123456789");
CharMatcher's precomputed() method (source) is a nice "hidden feature" I stumbled upon the other day.
It's really just an optimization, that creates a lookup table (using a bit array), and then simply looks up characters to see if they "match".
It's the kind of hidden optimization you can leverage when you use a library, that you might not have thought of yourself in your own code.
Of course,
if you create a complex CharMatcher, which you plan to use many times, you must remember to call the precomputed() method, like:
CharMatcher complexMatcher = CharMatcher.anyOf("cat")
.or(CharMatcher.DIGIT)
.or(CharMatcher.WHITESPACE)
.precomputed();
Here's a YouTube video from Google (speaker: Kevin Bourrillion, lead engineer for Google's core Java libraries) which shows the beauty of Google Collections. One thing Google did, which I believe is brilliant, is guarantee Immutability in collections.
Google Guava is a utility library, so I doubt that there is a killer class inside it. The whole things about utility is you almost use that in every projects you have. I can't remember any project I've done that doesn't use Java collection. And truth is, the collection utility of Google Guava is wonderful and should be in the Java SDK itself.
I've written three articles about classes on Google Guava:
Using CheckedFuture: http://blog.firdau.si/2010/07/07/guava-using-checkedfuture/
Using ListenableFuture: http://blog.firdau.si/2010/07/05/guava-using-listenablefuture/
ComputingMap on Google Collection (now Guava) http://blog.firdau.si/2009/11/13/computing-map-on-google-collections/
And this is not all, there are many other things you can do with Guava.
Absolutely very super useful. It's almost invariably the first library added to a new project.
We're very fond of Iterators/Iterables and the Function interface.
The Service family of interfaces are great abstractions
We're so committed we've started to use the ImmutableXXX classes our API types to communicate that it can't be changed.
Computing maps (from MapMaker) are wonderful in certain situations.
Overall, the library is very high quality. The API is well thought out, the implementation solid. Highly recommended.
MapMaker now offers bounded LRU caches - that's some substantial machinery hidden behind a tiny API. This has the potential for huge utility, and I'm still all over the code.
Since everyone praises Google Collections (e.g. in here)
How come I can't find the equivalent of ArrayUtils.toObject() and ArrayUtils.toPrimitive()? is it that unusable? did I miss it?
To be honest I'm not sure if either of those methods should even qualify as a collection-related operation and as such I'd wonder why they're even there in the first place.
To clarify a bit, collections are generically a group of objects with some semantic data binding them together while arrays are just a predetermined set of something. This semantic data may be information about accepting or rejecting nulls, duplicates, objects of wrong types or with unacceptable field values etc.
Most -if not all- collections do use arrays internally, however array itself isn't a collection. To qualify as a collection it needs some relevant magic such as removing and adding objects to arbitrary positions and arrays can't do that. I very much doubt you'll ever see any kind of array support in Google Collections since arrays are not collections.
However since Google Collections is going to be part of Google's Guava libraries which is a general purpose utility class library/framework of sorts, you may find what you want from com.google.common.primitives package, for example Booleans#asList(boolean... backingArray) and Booleans#toArray(Collection<Boolean> collection).
If you absolutely feel they should include equal methods to Apache Commons Collection's .toObject() and .toPrimitive() in there, you can always submit a feature request as new issue.