Retrieve an ArrayListMultimap Key - java

I'm using Guava's ArrayListMultimap<K,V> collection to map Integers to Strings. The class provides a method called containsValue(Object value) which checks if the Multimap contains the specified value for any key. Once I determine that is true, what's the best way to retrieve said key?
ArrayListMultimap<String, Integer> myMap = ArrayListMultimap.create();
if (myMap.containsValue(new Integer(1))
{
// retrieve the key?
}

Instead of using containsValue you could iterate over myMap.entries() which returns a collection of all key-value pairs. The iterator generated by the returned collection traverses the values for one key, followed by the values of a second key, and so on:
Integer toFind = new Integer(1);
for (Map.Entry<String, Integer> entry: myMap.entries()) {
if (toFind.equals(entry.getValue())) {
// entry.getKey() is the first match
}
}
// handle not found case
If you look at the implementation of containsValue it just iterates over the map's values so the performance of doing this with map.entries() instead of map.values() should be about the same.
public boolean containsValue(#Nullable Object value) {
for (Collection<V> collection : map.values()) {
if (collection.contains(value)) {
return true;
}
}
return false;
}
In the general case of course there isn't necessarily a unique key for a given value so unless you know that in your map each value only occurs against a single key you would need to specify the behaviour e.g. if you wanted the first key or last key.

Related

How to return a Key from HashMap based on its Value in Java

Consider the following:
for (Boolean i: x.values()) {
if (i == false) {
return // KEY;
}
}
In the above code, I am trying to iterate through the HashMap. And I want to return a Key when the value is false.
How can I do it?
You need to loop through the HashMap's entrySet:
for (Map.Entry<Object, Boolean> entry : x.entrySet()) {
if(entry.getValue() == false){
return entry.getKey();
}
}
In order to find first a key that is mapped to a particular value you need to iterate either over the key set or over the entry set.
The latter option is preferred because at each iteration step you will have a key-value pair on your hands. Therefore, it would be slightly faster than interrogating the map at every iteration (remainder: there could be collisions in a real hashmap, and finding the target node can take more time than accessing the value on a map-entry).
But you definitely can't use a collection of map values returned by a method values() like you're doing in the code-snippet you've posted. There's no fast way of retrieving a key when you have only a value on your hands.
In the example below, ill show how to obtain a key from a map of arbitrary type that matches the condition (a Predicate) provided dynamically at runtime using Stream API.
There's one important thing to consider: target value might not be present in the map. And the code should handle this case. We can provide a default value (either directly or via Supplier), throw an exception (if according to the application logic the given value is always expected to be present), or by utilizing methods ifPresent(), ifPresentOrElse() provided by the Optional class. In the example below, I've chosen to provide a default value.
Take a look at these tutorials for more information on lambda expressions and streams
public static void main(String[] args) {
Map<String, Boolean> sourceMap =
Map.of("A", true, "B", false, "C", true);
String result = getFirstKey(sourceMap, entry -> !entry.getValue(), "");
System.out.println(result);
}
public static <K, V> K getFirstKey(Map<K, V> map,
Predicate<Map.Entry<K, V>> condition,
K defaultKey) {
return map.entrySet().stream()
.filter(condition) // Stream<Map.Entry<K, V>>
.findFirst() // Optional<Map.Entry<K, V>>
.map(Map.Entry::getKey) // Optional<K>
.orElse(defaultKey); // or apply .orElseThrow() depending on your needs
}
Output
B // key assosiated with a value of `false`

How can each element in Set be a Map.Entry object?

I am a bit confused. i was reading the map interface. It has to use entrySet() method for collection view to use iterator. entrySet() return a Set that contains the elements of map. Again, each of this Set element is a Map.Entry object. how is that possible? as Set contains only one field, whereas Map.Entry is a key value pair?
A map is basically a set of key => value mappings. In addition, the keys are unique and the values don't have to be. A key-value pair is encapsulated within a Map.Entry object. When you iterate over the entries of a map (= the set of key-value pairs), for each entry you can get the key with entry.getKey() and the value with entry.getValue().
In addition to the set of entries, a map also provides the set of keys, and the collection of values. For example, in a Map<String, Date>, you have the set of key-value pairs as Set<Map.Entry<String, Date>>, the set of keys as Set<String> and the collection of values as Collection<Date>.
A concrete example of iterating over entries:
Map<String, Date> map = new HashMap<String, Date>();
map.put("now", new Date());
map.put("now+", new Date());
for (Map.Entry<String, Date> entry : map.entrySet()) {
String key = entry.getKey();
Date value = entry.getValue();
System.out.println(String.format("%s => %s", key, value));
}
Another way to iterate is by keys:
for (String key : map.keySet()) {
Date value = map.get(key);
System.out.println(String.format("%s => %s", key, value));
}
But this is less efficient because for each key you have to perform a lookup to get the value, in contrast with using entries with direct access to values.
Set elements are objects, Map.Entry instance is also an object. All correct.
Consider the following: You can create your own Cat class with whichever properties you like. E.g.:
public class Cat {
private String name;
private String type;
private boolean isGrumpy;
// etc...
}
As long as you implement equals(Object) and hashCode(), instances of this class can be put in a Set, right?
So why should Map.Entry be different? Just think of it as a class with two members - key and value.

check if hashmap contains value other than certain value

I am trying to implement HashMap in JAVA, in my algorithm, i have to find if any of the keys contain values other than a specific value....for instance, lets say, all the keys in the map should have value 0 stored in them.
How can i check if, the map contains value which is not equal to 0.
I tried this but logically it isn't correct i know :
if(!hm.containsValue(0)) /* where hm is hashmap object*/
You have to iterate over all the values and check each one to see if it's not equal to zero, and that's O(n). There's no alternative using a Map, a Map is efficient for finding keys, not for finding something in the values. For example, using the standard Map implementation in Java:
Integer zero = new Integer(0);
for (Integer i : hm.values()) {
if (!zero.equals(i)) {
System.out.println("found one non-zero value");
break;
}
}
you can define the map as follows:
Map<String, Integer> map = new HashMap<String, Integer>();
And check if it contains a non-zero value as follows :
for ( Integer value: map.values()) {
if ( value != 0) {
// non-zero value found in the map
}
}

Swapping value in Map

There are two maps: Master Map and Modified Map.
if modifiedmap.key == mastermap.key
then set mastermap.value = modifiedmap.value
Here is what doing right now
for (Map.Entry<String, String> entry : modified_map.entrySet())
{
for(Map.Entry<String,String> entry1:master_map.entrySet())
{
if(entry.getKey().equalsIgnoreCase(entry1.getKey()))
{
entry1.setValue(entry.getValue());
}
}
}
I am using two nested loops.
How ever map has a method called containsKey()
so I was try to use master_map.containsKey()modified_map) then assign the value
however i am not getting how to get mastermap Value corresponding to the matching key while trying to do with a single loop
something like this
for (Map.Entry<String, String> entry : modified_map.entrySet())
{
if(master_map.containsKey(entry.getKey()))
then get the corresponding value then swap it
}
If I understood correctly, you need something like this:
for (Map.Entry<String, String> entry : modified_map.entrySet()) {
if (master_map.containsKey(entry.getKey())
master_map.put (entry.getKey(),entry.getValue());
}
This would modify the value of each entry in master_map that has a key that appears in modified_map.
V put(K key,
V value)
Associates the specified value with the specified key in this map
(optional operation). If the map previously contained a mapping for
the key, the old value is replaced by the specified value. (A map m is
said to contain a mapping for a key k if and only if m.containsKey(k)
would return true.)

Using the keySet() method in HashMap

I have a method that goes through the possible states in a board and stores them in a HashMap
void up(String str){
int a = str.indexOf("0");
if(a>2){
String s = str.substring(0,a-3)+"0"+str.substring(a-2,a)+str.charAt(a-3)+str.substring(a+1);
add(s,map.get(str)+1);
if(s.equals("123456780")) {
System.out.println("The solution is on the level "+map.get(s)+" of the tree");
//If I get here, I need to know the keys on the map
// How can I store them and Iterate through them using
// map.keySet()?
}
}
}
I'm interested in the group of keys. What should I do to print them all?
HashSet t = map.keySet() is being rejected by the compiler as well as
LinkedHashSet t = map.keySet()
Use:
Set<MyGenericType> keySet = map.keySet();
Always try to specify the Interface type for collections returned by these methods. This way regardless of the actual implementation class of the Set returned by these methods (in your case map.keySet()) you would be ok. This way if the next release the jdk guys use a different implementation for the returned Set your code will still work.
map.keySet() returns a View on the Keys of the map. Making changes to this view results in changing the underlying map though those changes are limited. See the javadoc for Map:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Map.html#keySet%28%29
Map<String, String> someStrings = new HashMap<String, String>();
for(Map.Entry<String, String> entry : someStrings.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
}
This is how I like to iterate through Maps. If you specifically want just the keySet(), that answer is elsewhere on this page.
for ( String key : map.keySet() ) {
System.out.println( key );
}
Set t = map.ketSet()
The API does not specify what type of Set is returned.
You should try to declare variables as the interface rather than a particular implementation.
Just
Set t = map.keySet();
Unless you're using an older JDK, I think its a little cleaner to use generics when using the Collections classes.
So thats
Set<MyType> s = map.keySet();
And then if you just iterate through them, then you can use any kind of loop you'd like. But if you're going to be modifying the map based on this keySet, you you have to use the keySet's iterator.
All that's guaranteed from keySet() is something that implements the interface Set. And that could possibly be some undocumented class like SecretHashSetKeys$foo, so just program to the interface Set.
I ran into this trying to get a view on a TreeSet, the return type ended up being TreeSet$3 on close examination.
Map<String, Object> map = new HashMap<>();
map.put("name","jaemin");
map.put("gender", "male");
map.put("age", 30);
Set<String> set = map.keySet();
System.out.println("this is map : " + map);
System.out.println("this is set : " + set);
It puts the key values in the map into the set.
From Javadocs HashMap has several methods that can be used to manipulate and extract data from a hasmap.
public Set<K> keySet()
Returns a Set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation), the results of the iteration are undefined. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.
Specified by:
keySet in interface Map
Overrides:
keySet in class AbstractMap
Returns:
a set view of the keys contained in this map
so if you have a map myMap of any datatype , such that the map defined as map<T> , if you iterate it as follows:
for (T key : myMap.keySet() ) {
System.out.println(key); // which represent the value of datatype T
}
e.g if the map was defined as Map<Integer,Boolean>
Then for the above example we will have:
for (Integer key : myMap.keySet()){
System.out.println(key) // the key printed out will be of type Integer
}

Categories

Resources