When using the apache commonds bidimap, how do you handle synchronization. For example, if I create the map as shown below
BidiMap oneWay = new DualHashBidiMap();
BidiMap theOtherWay = oneWay.inverseBidiMap();
So if I am going to add/access/remove a key/value pair to one of the above variables, to I need to synchronize both (thread synchronization). Seems like I am not gaining anything over implementing this functionality with 2 maps if I need to do this.
Thanks for you time in looking at this problem.
By synchronization, are you referring to accessing the two from different threads or are you thinking that if you add a key/value pair to the inverse map you would need to add it to the forward map as well? If it's the latter, you don't have to do that. The inverse map is a view of the forward map, so changing one will always affect the other as well.
If you're asking about thread synchronization... well, I'm not sure what commons collections provides for that. My recommendation would be to use Guava and its BiMap interface instead of apache commons. In addition to using generics, Guava has a Maps.synchronizedBiMap(BiMap) method that creates a synchronized wrapper.
Related
I work in payment gateway company and while analyzing the code I came across
ImmuatbleMap objects. I want to know all the details about. What is it?
What are its advantages over the map? Does core java has its support for ImmuatbleMap?
ImmutableMaps are introduced in Guava, they comply to Java's Map API, but with additional guarantees.
In a nutshell:
you cannot add, replace or remove entries
they are "fully immutable" if entry objects do not have mutable state
as a consequence, they are thread safe
nulls are forbidden
(slightly) more time- and space-efficient compared to usual Java's collections
iteration order is predictable
For full info see Guava's guide and javadoc for ImmutableCollection which applies to maps and other Guava's immutable collections.
How do I get a ConcurrentHashMap with weak keys and identity hashes in Java? I think Google Guava Collections can give such a thing, but can I get it from the standard library? What other options do I have?
I think Google Guava Collections can give such a thing, but can I get it from the standard library?
The short answer to that is No. Java SE does not implement this particular combination.
You could instantiate a java.util.concurrent.ConcurrentHashMap with WeakReference keys, and do some extra work to implement removal of map entries for broken references, but that won't give you identity hash semantics.
You could instantiate a java.util.IdentityHashMap with WeakReference keys, and do some extra work to implement removal of map entries for broken references, but that won't give you concurrent behaviour.
Using a java.util.WeakHashMap won't give you either concurrency or identity hashing.
You could (in theory) wrap the key class in something that overrode the natural equals and hashcode methods. But that is most likely to be unusable.
I don't think it would be possible to do this by overriding methods in either ConcurrentHashMap or IdentityHashMap.
Maybe the only viable option would be to change the key classes equals and hashcode methods to be identity based. But that won't work for "built in" key types (especially final ones) or for cases where you need value-based equals/hashcode in other parts of the application.
The Google Guava implementation appears the easiest way to go. One may initialize the required map with new MapMaker().weakKeys().makeMap() and use just as one would use java.util.concurrent.ConcurrentHashMap. See the apidoc for more details.
if your application is under spring framework ( version is gt 3.2 ), you can consider to use org.springframework.util.ConcurrentReferenceHashMap. Below is its description:
A ConcurrentHashMap that uses soft or weak references for both keys and values.
This class can be used as an alternative to Collections.synchronizedMap(new WeakHashMap>()) in order to support better performance when accessed concurrently. This implementation follows the same design constraints as ConcurrentHashMap with the exception that null values and null keys are supported.
NOTE: The use of references means that there is no guarantee that items placed into the map will be subsequently available. The garbage collector may discard references at any time, so it may appear that an unknown thread is silently removing entries.
If not explicitly specified, this implementation will use soft entry references.
search ConcurrentWeakIdentityHashMap, you will get many examples. I wrote an implement myself, for I think the hashCode of org/ehcache/core/internal/util/ConcurrentWeakIdentityHashMap$WeakReference is so bad.
Example of ehcache3
Example I wrote
Pull Rquest to fix the ehcache3 ConcurrentWeakIdentityHashMap Key hashCode
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.
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>>)...
Let's say I want to put words in a data structure and I want to have constant time lookups to see if the word is in this data structure. All I want to do is to see if the word exists. Would I use a HashMap (containsKey()) for this? HashMaps use key->value pairings, but in my case I don't have a value. Of course I could use null for the value, but even null takes space. It seems like there ought to be a better data structure for this application.
The collection could potentially be used by multiple threads, but since the objects contained by the collection would not change, I do not think I have a synchronization/concurrency requirement.
Can anyone help me out?
Use HashSet instead. It's a hash implementation of Set, which is used primarily for exactly what you describe (an unordered set of items).
You'd generally use an implementation of Set, and most usually HashSet. If you did need concurrent access, then ConcurrentHashSet provides a drop-in replacement that provides safe, concurrent access, including safe iteration over the set.
I'd recommend in any case referring to it as simply a Set throughout your code, except in the one place where you construct it; that way, it's easier to drop in one implementation for the other if you later require it.
Even if the set is read-only, if it's used by a thread other than the one that creates it, you do need to think about safe publication (that is, making sure that any other thread sees the set in a consistent state: remember any memory writes, even in constructors, aren't guaranteed to be made available to other threads when or in the otder you expect, unless you take steps to ensure this). This can be done by both of the following:
making sure the only reference(s) to the set are in final fields;
making sure that it really is true that no thread modifies the set.
You can help to ensure the latter by using the Collections.unmodifiableSet() wrapper. This gives you an unmodifiable view of the given set-- so provided no other "normal" reference to the set escapes, you're safe.
You probably want to use a java.util.Set. Implementations include java.util.HashSet, which is the Set equivalent of HashMap.
Even if the objects contained in the collection do not change, you may need to do synchronization. Do new objects need to be added to the Set after the Set is passed to a different thread? If so, you can use Collections.synchronizedSet() to make the Set thread-safe.
If you have a Map with values, and you have some code that just wants to treat the Map as a Set, you can use Map.entrySet() (though keep in mind that entrySet returns a Set view of the keys in the Map; if the Map is mutable, the Map can be changed through the set returned by entrySet).
You want to use a Collection implementing the Set interface, probably HashSet to get the performance you stated. See http://java.sun.com/javase/6/docs/api/java/util/Set.html
Other than Sets, in some circumstances you might want to convert a Map into a Set with Collections.newSetFromMap(Map<E,Boolean>) (some Maps disallow null values, hence the Boolean).
as everyone said HashSet is probably the simplest solution but you won't have constant time lookup in a HashSet (because entries may be chained) and you will store a dummy object (always the same) for every entry...
For information here a list of data structures maybe you'll find one that better fits your needs.