Java - How to Create New Entry (Key, Value)

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



Leave a reply



Submit