I want to loop through all entries of AbstractMap.SimpleEntry type and Map type using the same function. Is there a way to do it?
You cannot iterate through what you are asking. I am guessing you mean the following:
for(Map.Entry<K, V> entry : AbstractMap.entrySet()) {
K key = entry.getKey();
V value = entry.getValue();
}
This example will not run; you'll need to alter it to your concrete implementations of the Abstract classes and Key/Value definitions.
Oracle Java Docs
Another Example
Related
Ex. I have the following HashMap, and how to get the entry 'b'=6 if I know the key 'b'. Is there any way to do it?
Map<Character, Integer> map=new HashMap<>();
map.put('a',7);
map.put('b',6);
map.put('c',5);`
By the way, I want to do this is because all those entries are in a priority queue. I have to remove that entry from the priority queue and re-insert it to make sure it is in order.
Thanks.
If you know the key, simply get the value using Map#get(Object). As long as you know both, you have the entry. The Map interface doesn't provide a specific method that returns a certain entry.
Map<Character, Integer> map = ...
Character key = 'b';
Integer value = map.get(key);
// now with the 'key' and 'value' that make TOGETHER an entry.
If you really somehow need an Entry<Character, Integer> construct it like this:
Map.Entry<Character, Integer> entry = new SimpleEntry<>(key, value);
There is no better way. One would say you can use Stream API to iterate through the entries and return the first one found, however, you lose the main benefit of the HashMap which is the constant-time look-up.
// DON'T DO THIS!
Entry<Character, Integer> entry = map.entrySet().stream()
.filter(e -> key.equals(e.getKey()))
.findFirst()
.orElse(null);
You could do something like this
public Entry<Character, Integer> entry_return(Map<Character, Integer> map) {
for(Map.Entry<Character, Integer> entry : map.entrySet()) {
if(entry.getKey() == 'b')
return entry;
}
}
or use a stream API if you really need the entry but i don't know if that is very common/usefull
Since Java 9, you can use static method Map.entry(K k, V v), which:
returns an unmodifiable Map.Entry containing the given key and value.
So, you can obtain your Entry<K, V> instance, as:
Map.Entry<Character, Integer> entry = Map.entry(key, map.get(key));
where map stores a reference to your Map<K, V> instance.
Based on the following code snippet :
Hashtable balance = new Hashtable();
Enumeration names;
String str;
double bal;
balance.put("Zara", new Double(3434.34)); //first entry for Zara
balance.put("Mahnaz", new Double(123.22));
balance.put("Zara", new Double(1378.00)); //second entry for Zara
balance.put("Daisy", new Double(99.22));
balance.put("Qadir", new Double(-19.08));
System.out.println(balance.entrySet());
.
Output : [Qadir=-19.08, Mahnaz=123.22, Daisy=99.22, Zara=1378.0]
Why isn't chaining happening here? When I re-enter with Zara as key the old value is overwritten. I expected it to be added at the end of the Linked List at Zara".hashcode() index.
Does Java use separate chaining only for collision handling?
If I can't use chaining( as I'v tried above) please suggest a common method to do so.
Does Java use separate chaining only for collision handling?
Yes. You can only have one entry per key in a Hashtable (or HashMap, which is what you should probably be using - along with generics). It's a key/value map, not a key/multiple-values map. In the context of a hash table, the term "collision" is usually used for the situation where two unequal keys have the same hash code. They still need to be treated as different keys, so the implementation has to cope with that. That's not the situation you're in.
It sounds like you might want a multi-map, such as one of the ones in Guava. You can then ask a multimap for all values associated with a particular key.
EDIT: If you want to build your own sort of multimap, you'd have something like:
// Warning: completely untested
public final class Multimap<K, V> {
private final Map<K, List<V>> map = new HashMap<>();
public void add(K key, V value) {
List<V> list = map.get(key);
if (list == null) {
list = new ArrayList();
map.put(key, list);
}
list.add(value);
}
public Iterable<V> getValues(K key) {
List<V> list = map.get(key);
return list == null ? Collections.<V>emptyList()
: Collections.unmodifiableList(list);
}
}
Quote from the documentation of Map (which Hashtable is an implementation of):
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
(emphasis mine)
The documentation of put() also says:
If the map previously contained a mapping for the key, the old value is replaced by the specified value
So if you want multiple values associated with a key, use a Map<String, List<Double>> instead of a Map<String, Double>. Guava also has a Multimap, which does what you want without having to deal with Lists explicitely as with a Map<String, List<Double>>.
I have a question about hashmaps with multiple keys to value. Let's say I have (key / value )
1/a, 1/b, 1/3, 2/aa, 2/bb, 2/cc.
Would this work?
If it does, could I have a way to loop through it and display all values for only either key 1 or 2?
You can use a map with lists as values, e.g.:
HashMap<Integer, List<String>> myMap = new HashMap<Integer, List<String>>();
java.util.HashMap does not allow you to map multiple values to a single key. You want to use one of Guava's Multimap's. Read through the interface to determine which implemented version is suitable for you.
A simple MultiMap would look something like this skeleton:
public class MultiMap<K,V>
{
private Map<K,List<V>> map = new HashMap<K,List<V>>();
public MultiMap()
{
// Define constructors
}
public void put(K key, V value)
{
List<V> list = map.get(key);
if (list == null)
{
list = new ArrayList<V>();
map.put(key, list);
}
list.add(value);
}
public List<V> get(K key)
{
return map.get(key);
}
public int getCount(K key)
{
return map.containsKey(key) ? map.get(key).size() : 0;
}
}
It cannot directly implement Map<K,V> because put can't return the replaced element (you never replace). A full elaboration would define an interface MultiMap<K,V> and an implementation class, I've omitted that for brevity, as well as other methods you might want, such as V remove(K key) and V get(K key, int index)... and anything else you can think of that might be useful :-)
Maps will handle multiple keys to one value since only the keys need be unique:
Map(key, value)
However one key to multiple values requires s multimap of a map strict of :
Map(key, list(values))
Also, whatever you use as a key really should implement a good hadhCode() function if you decide to use a HashMap and/or HashSet
Edit: had to use() instead of <> because my mobile or sof's mobile site editor clobbered the <> symbols....odd
I want to go through every items in a dictionary in java. to clarify what I want to do, this is the C# code
Dictionary<string, Label> LableList = new Dictionary<string, Label>();
foreach (KeyValuePair<string, Label> z in LabelList);
I don't know how to do this is java, for example I did this
for(Object z: dic)
but it says it's not iterable. Please advise......
I'm assuming you have a Map<String, Label> which is the Java built-in dictionary structure. Java doesn't let you iterate directly over a Map (i.e. it doesn't implement Iterable) because it would be ambiguous what you're actually iterating over.
It's just a matter of choosing to iterate through the keys, values or entries (both).
e.g.
Map<String, Label> map = new HashMap<String, Label>();
//...
for ( String key : map.keySet() ) {
}
for ( Label value : map.values() ) {
}
for ( Map.Entry<String, Label> entry : map.entrySet() ) {
String key = entry.getKey();
Label value = entry.getValue();
}
Your C# code seems to be the same as iterating over the entries (the last example).
java.util.Map is the Dictionary equvivalent and below is an example on how you can iterate through each entry
for(Map.Entry<K, V> e : map.entrySet())
{
System.out.println(e.getKey()+": "+e.getValue());
}
Your best bet is to use this:
for (String key : LableList.keys()) {
Label value = LableList.get(key);
// do what you wish with key and value here
}
In Java however, a better bet is to not use Dictionary as you would in .NET but to use one of the Map subclasses, e.g. HashMap. You can iterate through one of these like this:
for (Entry<String, Label> e : myMap.entrySet()) {
// Do what you wish with e.getKey() and e.getValue()
}
You are also advised against using Dictionary in the official javadoc.
I was trying to add the contents of one HashMap (a) into another HashMap (b).
I found it simple to iterate through HashMap a this way:
a.forEach((k, v) -> b.put(k, v));
You can manipulate my example to do what ever you want on the other side of "->".
Note that this is a Lambda expression, and that you would have to use Java 1.8 (Java 8) or later for this to work. :-)
I am sick of the following pattern:
value = map.get(key);
if (value == null) {
value = new Object();
map.put(key, value);
}
This example only scratches the surface of the extra code to be written when you have nested maps to represent a multi-dimensional structure.
I'm sure something somewhere exists to avoid this, but my Googling efforts yielded nothing relevant. Any suggestions?
The
java.util.concurrent.ConcurrentMap
and from Java 8
Java.util.Map
has
putIfAbsent(K key, V value)
which returns the existing value, and if that is null inserts given value. So if no value exists for key returns null and inserts the given value, otherwise returns existing value
If you need lazy evaluation of the value there is
computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
Java 8 adds nice method to the Map: compute, computeIfPresent, computeIfAbsent
To achieve what you need:
Object existingOrCreated = map.computeIfAbsent(key, (k) -> new Object());
The problem with this pattern is that you'd have to somehow define the value that should be used in case the get() returns null.
There certainly are libraries out there and IIRC there are also some newer collections that do that, but unfortunately I don't remember which those were.
However, you could write a utility method yourself, provided you have a standard way of creating the new values. Something like this might work:
public static <K, V> V safeGet(K key, Map<K,V> map, Class<V> valueClass) throws /*add exceptions*/ {
V value = map.get(key);
if( value == null ) {
value = valueClass.newInstance();
map.put( key, value );
}
return value;
}
Note that you'd either have to throw the reflection exceptions or handle them in the method. Additionally, this requires the valueClass to provide a no-argument constructor. Alternatively, you could simply pass the default value that should be used.
Java 8 update
It has already been mentioned in other answers but for the sake of completeness I'll add the information here as well.
As of Java 8 there is the default method computeIfAbsent(key, mappingFunction) which basically does the same, e.g. if the value class was BigDecimal it could look like this:
BigDecimal value = map.computeIfAbsent(key, k -> new BigDecimal("123.456"));
The implementation of that method is similar to the safeGet(...) defined above but more flexible, directly available at the map instance and better tested. So when possible I'd recommend using computeIfAbsent() instead.
You can use MutableMap and getIfAbsentPut() from Eclipse Collections which returns the value mapped to the key or inserts the given value and returns the given value if no value is mapped to the key.
You can either use a method reference to create a new Object:
MutableMap<String, Object> map = Maps.mutable.empty();
Object value = map.getIfAbsentPut("key", Object::new);
Or you can directly create a new Object:
MutableMap<String, Object> map = Maps.mutable.empty();
Object value = map.getIfAbsentPut("key", new Object());
In the first example, the object will be created only if there is no value mapped to the key.
In the second example, the object will be created regardless.
Note: I am a contributor to Eclipse Collections.
If in any case you need to get a default data in your map if it's not existing
map.getOrDefault(key, defaultValue);
javadocs
EDIT : Note that the feature mentioned below is long deprecated, and a CacheBuilder should be used instead.
The Guava library has a "computing map", see MapMaker.makeComputingMap(Function).
Map<String, Object> map = new MapMaker().makeComputingMap(
new Function<String, Object>() {
public String apply(Stringt) {
return new Object();
}
});
If you need the Function several times, extract it into a utility class, and then create the Map like this (where MyFunctions.NEW_OBJECT is the static Function instance):
Map<String, Object> map = new MapMaker()
.makeComputingMap(MyFunctions.NEW_OBJECT);
Maybe I'm not seeing the whole problem, but how about using inheritance or composition to add this behavior to the Map object?