Java - How to create new Entry (key, value)
You can just implement the Map.Entry<K, V>
interface yourself:
import java.util.Map;
final class MyEntry<K, V> implements Map.Entry<K, V> {
private final K key;
private V value;
public MyEntry(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
V old = this.value;
this.value = value;
return old;
}
}
And then use it:
Map.Entry<String, Object> entry = new MyEntry<String, Object>("Hello", 123);
System.out.println(entry.getKey());
System.out.println(entry.getValue());
How to put an Entry into a Map?
I have searched on the Map interface methods but there is no method that
takes an entry and puts it in the map. Therefore I have implemented it
by myself using a little bit of inheritance and Java 8 interfaces.
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class Maps {
// Test method
public static void main(String[] args) {
Map.Entry<String, String> entry1 = newEntry("Key1", "Value1");
Map.Entry<String, String> entry2 = newEntry("Key2", "Value2");
System.out.println("HashMap");
MyMap<String, String> hashMap = new MyHashMap<>();
hashMap.put(entry1);
hashMap.put(entry2);
for (String key : hashMap.keySet()) {
System.out.println(key + " = " + hashMap.get(key));
}
System.out.println("\nTreeMap");
MyMap<String, String> treeMap = new MyTreeMap<>();
treeMap.put(entry1);
treeMap.put(entry2);
for (String key : treeMap.keySet()) {
System.out.println(key + " = " + treeMap.get(key));
}
}
/**
* Creates a new Entry object given a key-value pair.
* This is just a helper method for concisely creating a new Entry.
* @param key key of the entry
* @param value value of the entry
*
* @return the Entry object containing the given key-value pair
*/
private static <K,V> Map.Entry<K,V> newEntry(K key, V value) {
return new AbstractMap.SimpleEntry<>(key, value);
}
/**
* An enhanced Map interface.
*/
public static interface MyMap<K,V> extends Map<K,V> {
/**
* Puts a whole entry containing a key-value pair to the map.
* @param entry
*/
public default V put(Entry<K,V> entry) {
return put(entry.getKey(), entry.getValue());
}
}
/**
* An enhanced HashMap class.
*/
public static class MyHashMap<K,V> extends HashMap<K,V> implements MyMap<K,V> {}
/**
* An enhanced TreeMap class.
*/
public static class MyTreeMap<K,V> extends TreeMap<K,V> implements MyMap<K,V> {}
}
The MyMap
interface is just an interface that extends the Map
interface
by adding one more method, the public default V put(Entry<K,V> entry)
.
Apart from just defining the method, a default implementation is coded
too. Doing that, we can now add this method to any class that implements
the Map
interface just by defining a new class that implements the MyMap
interface and extending the map implementation class of our choice. All
of that in one line! This is demonstrated in the bottom of the code above where two
classes are created each extending the HashMap and the TreeMap
implementations.
List of entries, how to add a new Entry?
Do you mean Map.Entry
? That is an interface (so you can't instantiate without an implementation class, you can learn about interfaces in the Java Tutorial). Entry
instances are usually only created by Map
implementations and only exposed through Map.entrySet()
Of course, since it's an interface you could add your own implementation, something like this:
public class MyEntry<K, V> implements Entry<K, V> {
private final K key;
private V value;
public MyEntry(final K key) {
this.key = key;
}
public MyEntry(final K key, final V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(final V value) {
final V oldValue = this.value;
this.value = value;
return oldValue;
}
}
That way you could do listObjects.add(new MyEntry<String,Integer>("abc", 1))
But that doesn't really make sense outside of a map context.
How to get or create new map entry
You should ckeck out Map::getOrDefault
and Map::computeIfAbsent
(added in Java 8); those do pretty much exactly what your function is supposed to do. The difference between the two is that getOrDefault
will accept an existing instance (created before the method is invoked) and return it if needed, but will not add it to the map, while computeIfAbsend
accepts a function for lazily creating a new value, and will also add that value to the map.
Map<String, List<Integer>> map = new HashMap<>();
List<Integer> list1 = map.getOrDefault("foo", Collections.emptyList());
System.out.println(list1); // empty list
System.out.println(map); // map is still empty
List<Integer> list2 = map.computeIfAbsent("bar", s -> new ArrayList<Integer>());
System.out.println(list2); // empty list
System.out.println(map); // entry added to map
Assuming that you always want to create a new instance of the Value class with the key as parameter, and assuming that that class actually has such a constructor) you could e.g. use this:
YourClass obj = map.computeIfAbsent(key, YourClass::new);
How to update a value, given a key in a hashmap?
map.put(key, map.get(key) + 1);
should be fine. It will update the value for the existing mapping. Note that this uses auto-boxing. With the help of map.get(key)
we get the value of corresponding key, then you can update with your requirement. Here I am updating to increment value by 1.
How to get a specific Map.EntryK, V for a specific key?
@Sweeper's comment on his answer got me thinking. The solution I came up with was to maintain a Map
from Key
to Entry
inside my class. That way I have a way of having O(1)
access to the entrySet
. Like so:
Map<K, Map.Entry<K, V>> entryMap = new HashMap<>();
for(final currentEntry : entrySet())
{
entryMap.put(currentEntry.getKey(), currentEntry);
}
I just need to update this Map
every time an operation runs which changes the keySet
. I only need to update the one entry in this Map
that would be affected. That sounds like it wouldn't be very expensive.
HashMap - getting First Key value
You can try this:
Map<String,String> map = new HashMap<>();
Map.Entry<String,String> entry = map.entrySet().iterator().next();
String key = entry.getKey();
String value = entry.getValue();
Keep in mind, HashMap
does not guarantee the insertion order. Use a LinkedHashMap
to keep the order intact.
Eg:
Map<String,String> map = new LinkedHashMap<>();
map.put("Active","33");
map.put("Renewals Completed","3");
map.put("Application","15");
Map.Entry<String,String> entry = map.entrySet().iterator().next();
String key= entry.getKey();
String value=entry.getValue();
System.out.println(key);
System.out.println(value);
Output:
Active
33
Update:
Getting first key in Java 8
or higher versions.
Optional<String> firstKey = map.keySet().stream().findFirst();
if (firstKey.isPresent()) {
String key = firstKey.get();
}
Create new Map.Entry - seems harder than it needs to be
With Java 9+, you can use Map.entry
as:
static <E, T> void done(E e, Map.Entry<String, T> m) {
// do something
}
// using immutable entry
static <E, T> void done(E e, String k, T v) {
done(e, Map.entry(k, v));
}
// using mutable entry
static <E, T> void done(E e, String k, T v) {
done(e, new AbstractMap.SimpleEntry<>(k, v));
}
MapString, ListString, Object add new list entry when key exists
So, let's assume there is a map of some ids to objects of type ObjectOne
: Map<ID, ObjectOne>
.
The key IDs are converted to some Code
type by a database call, and the ObjectOne
values of the first map are just collected into another map using Collectors.groupingBy
and Collectors.mapping
as intended initially:
Map<ID, ObjectOne> initialMap = ...;
Map<Code, List<ObjectOne>> mapByCode = initialMap
.entrySet()
.stream() // Stream<Map.Entry<ID, ObjectOne>>
.collect(Collectors.groupingBy(
e -> repository.getCodeById(e.getKey()),
Collectors.mapping(Map.Entry::getValue, Collectors.toList())
));
Also, a keySet
of the initial map may be iterated upon:
// or using keySet()
Map<Code, List<ObjectOne>> mapByCode2 = initialMap
.keySet()
.stream() // Stream<ID>
.collect(Collectors.groupingBy(
repository::getCodeById,
Collectors.mapping(initialMap::get, Collectors.toList())
));
Related Topics
How to Fix a Compilation Error for Unhandled Exception on Call to Thread.Sleep()
How to Hide Cursor in a Swing Application
Maximum Size of Hashset, Vector, Linkedlist
How to Use 3Rd Party Library in Java9 Module
Httpclient 4.0.1 - How to Release Connection
Jdbc Driver Throws "Resultset Closed" Exception on Empty Resultset
Pdfbox - Signature Validity Checkmark Not Visible in Acrobat Reader
Junit - Run Set Up Method Once
Advantage of Set and Get Methods VS Public Variable
How to Pass Parameter to Jsp:Include via C:Set? What Are the Scopes of the Variables in Jsp
What's the Use of Session.Flush() in Hibernate
How Does the JPA @Sequencegenerator Annotation Work