I have two hashmaps:
Map<String, String> mapA = new HashMap<String, String>();
Map<String, String> mapB = new HashMap<String, String>();
TreeSet<String> uniquekeys = new TreeSet<String>();
mapA.put("1","value1");
mapA.put("2","value2");
mapA.put("3","value3");
mapA.put("4","value4");
mapA.put("5","value5");
mapA.put("6","value6");
mapA.put("7","value7");
mapA.put("8","value8");
mapA.put("9","value9");
mapB.put("1","value1");
mapB.put("2","value2");
mapB.put("3","value3");
mapB.put("4","value4");
mapB.put("5","value5");
To get the common key value pairs from the two hashmaps, I have written the below logic:
uniquekeys.addAll(mapA.keySet());
uniquekeys.addAll(mapB.keySet());
and then use the keys from the treeset: uniquekeys to retrieve unique key value pairs from mapA & mapB.
But this is not giving me the details of all the keys from mapA. I understand this way is flawed but I couldn't come up with a proper logic.
Could anyone let me know how can I retrieve key value pairs that are common in mapA and mapB into a new HashMap ?
Try below logic :
Map<String, String> common = new HashMap<String, String>();
for(String key : mapA.keySet()) {
if(mapB.get(key) !=null ) {
if(mapA.get(key).equals(mapB.get(key))) {
common.put(key, mapA.get(key));
}
}
}
You can do it with Java 8 Streams in the following way:
Map<String, String> commonMap = mapA.entrySet().stream()
.filter(x -> mapB.containsKey(x.getKey()))
.collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue()));
Instead of adding all keys to a TreeSet, you can fill the TreeSet with common values:
uniquekeys.addAll(mapA.keySet());
uniquekeys.retainAll(mapB.keySet());
This way, the keys contained in A but not B will be removed. Know you've got your TreeSet, you can do what you want.
However, you can also create your HashMap without TreeSet, as #Ramesh and #NiVeR suggest
Use Guava Util Sets
Set<String> intersectionSet = Sets.intersection(firstSet, secondSet);
Related
I have two Maps that I need to compare and merge them into a result map. I need to remove all the elements that either have the same key or the same value.
Basically, say I have two Maps:
Map<String, String> map1 = new HashMap<>();
map1.put("1", "A");
map1.put("2", "A");
map1.put("3", "B");
map1.put("4", "C");
map1.put("5", "D");
map1.put("6", "E");
Map<String, String> map2 = new HashMap<>();
map2.put("1", "B");
map2.put("2", "A");
map2.put("4", "F");
map2.put("6", "C");
map2.put("7", "G");
map2.put("8", "H");
I need to remove all the entries that have either the same keys or the same values and need to retain back only bidirectional unique entries. So after merge, I need to have the following result map in which every key maps to a unique value and every value has a unique key:
("5", "D"), ("7", "G"), ("8", "H")
What's the best way to do this in Java?
I would create another map that contains all the values and keys from map1 and map2, and then I would go through a loop deleting the duplicates keys and values
Map<String, String> map3 = new HashMap<>();
map3.putAll(map1);
map3.putAll(map2);
for(String a: map1.keySet()){
if(map2.containsKey(a) || map2.containsValue(map1.get(a))){
map3.remove(a);
}
}
Hope this is useful!
Below code will do this
Map map3 = new HashMap<>(map1);
map3.keySet().removeAll(map2.keySet());
map3.values().removeAll(map2.values());
map2.keySet().removeAll(map1.keySet());
map2.values().removeAll(map1.values());
map3.putAll(map2);
System.out.println(map3);
This will result {7=G, 5=D, 8=H}
Interesting problem. I can't think of a particularly neat way of doing it but here's a potential solution using Java 8 - I'm pretty sure it could be simplified somewhat. I don't like these sorts of stateful operations mid stream but the only way I can see to avoid it is to split it into two operations.
Set<Map.Entry<String, String>> values = new HashSet<>();
Map<String,String> mergedMap =
Stream.concat(map1.entrySet().stream(), map2.entrySet().stream)
.filter(e -> !values.keySet().contains(e.getKey()))
.filter(e -> !values.valueSet().contains(e.getValue()))
.peek(e -> values.add(e))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
I have two hash maps: one contains an Integer key and String value.
The other contains an Integer key and float value.
Code
Map<Integer,String> mapA = new HashMap<>();
mapA.put(1, "AS");
mapA.put(2, "Wf");
Map<Integer,Float> mapB = new HashMap<>();
mapB.put(2, 5.0f);
mapB.put(3, 9.0f);
My question is how to compare the two hash maps using the integer key value? I want to print the bitmap value when the key values are the same.
You can just iterate on the keys of mapA and check if it is present in mapB then add the value to a third mapC for example.
Map<String, float> mapC = new HashMap<String, float>();
for (Integer key : mapA.keySet()) {
if (mapB.containsKey(key)) {
mapC.put(mapA.get(key), mapB.get(key));
}
}
Compare keys in two map by using mapB iterator.
Iterator<Entry<Integer, Float>> iterator = mapB.entrySet().iterator();
while(iterator.hasNext()) {
Entry<Integer, Float> entry = iterator.next();
Integer integer = entry.getKey();
if(mapA.containsKey(integer)) {
System.out.println("Float Value : " + entry.getValue());
}
}
If you are allowed to modify mapB, then the solution is as simple as mapB.keySet().retainAll(mapA.keySet());.
This will only leave those entries in mapB that have a corresponding key in mapA, because the set returned by keySet() is backed by the map itself, any changes made to it will be reflected to the map.
yes i got solution...
if(mapB.containsKey(position)){
Log.e("bucky",mapB.get(position));}
position means integer value.
With Java 8 Streams API:
Map<Integer, Object> matchInBothMaps = mapA
.entrySet()
.stream()
.filter(map -> mapB.containsKey(map.getKey()))
.collect(Collectors.toMap(map -> map.getKey(),
map -> map.getValue()));
System.out.println(matchInBothMaps);
I am using Java 1.7. I have below map.
Map<String, String> keyValues = new HashMap<>();
But map can contain values as below.
keyValues.put("one", "value1");
keyValues.put("two", "value2");
OR
keyValues.put("four", "value1");
keyValues.put("two", "value2");
keyValues.put("seven", "value3");
OR
keyValues.put("one", "value1");
keyValues.put("two", "value2");
keyValues.put("three", "value3");
Basically the map can contain N values where is N is generic it can contain any number of values.
I have one more value for group of keys as below.
keys one, two belongs to 12345SRT
keys one, two, three, four belongs to 12345SRTSSS
keys four, two, seven belongs to 764RTYL87
Now map can contain any one of above key sets.
In that case based on the key set in the map it has to return corresponding value.
Ex:
If map contains one and two then it should return 12345SRT.
If map contains four,two and seven then logic should return 764RTYL87.
What is the best place to keep above key sets and corresponding values?
Shall i consider enum?
The logic has to take map and return value.
What is the best way to do that?
You can use Apache MultiKeyMap
Example
MultiKeyMap multiKeyMap = new MultiKeyMap();
multiKeyMap.put("New York","IBM","Sam");
multiKeyMap.put("Sydney","Infosys","Honey");
multiKeyMap.put("Prague","JP Morgan","Peter");
multiKeyMap.put("Scotland","RBS","Deny");
multiKeyMap.put("Paris","Nomura","Lily");
multiKeyMap.put("Melbourne","Citi Bank","Sandy");
multiKeyMap.put("Aukland","Bank of America","Tommy");
Resultant map
Similar question: How to implement a Map with multiple keys?
EDIT :
You can have a custom key class which can have N number of keys.
Something like
Class MyKey{
List<String> keys;
}
Map<MyKey, String> keyValues = new HashMap<>();
Also override appropriate methods of Map like equals,hashcode,get etc.
Maybe this?
HashMap<Set<String>, String> multiMap = new HashMap<Set<String>, String>();
Set<String> mk1 = new HashSet<String>();
mk1.add("one");
mk1.add("two");
mk1.add("three");
multiMap.put(mk1, "derp");
Set<String> checker = new HashSet<String>();
checker.add("two");
checker.add("three");
checker.add("one");
if(multiMap.containsKey(checker))
System.out.println(multiMap.get(checker));
Try running this and see if it's the behavior you're wanting.
You can use as below :
Map<String, ArrayList<String>> keyValues = new HashMap<String, ArrayList<String>();
keyValues.put("12345SRT",["one","two"]);
keyValues.put("12345SRTSSS",["one", "two", "three", "four"]);
keyValues.put("764RTYL87",["four", "two", "seven"]);
Ex:if you have a map object with keys as "one" and "two"
String getKey(map){
for (Map.Entry<String, Object> e : keyValues.entrySet()) {
String key = e.getKey();
ArrayList<string> value = e.getValue();
if(value.containsAll(map.keySet())){
return key;
}
}
}
I need to copy all keys and values from one A HashMap onto another one B, but not to replace existing keys and values.
Whats the best way to do that?
I was thinking instead iterating the keySet and checkig if it exist or not, I would
Map temp = new HashMap(); // generic later
temp.putAll(Amap);
A.clear();
A.putAll(Bmap);
A.putAll(temp);
It looks like you are willing to create a temporary Map, so I'd do it like this:
Map tmp = new HashMap(patch);
tmp.keySet().removeAll(target.keySet());
target.putAll(tmp);
Here, patch is the map that you are adding to the target map.
Thanks to Louis Wasserman, here's a version that takes advantage of the new methods in Java 8:
patch.forEach(target::putIfAbsent);
Using Guava's Maps class' utility methods to compute the difference of 2 maps you can do it in a single line, with a method signature which makes it more clear what you are trying to accomplish:
public static void main(final String[] args) {
// Create some maps
final Map<Integer, String> map1 = new HashMap<Integer, String>();
map1.put(1, "Hello");
map1.put(2, "There");
final Map<Integer, String> map2 = new HashMap<Integer, String>();
map2.put(2, "There");
map2.put(3, "is");
map2.put(4, "a");
map2.put(5, "bird");
// Add everything in map1 not in map2 to map2
map2.putAll(Maps.difference(map1, map2).entriesOnlyOnLeft());
}
Just iterate and add:
for(Map.Entry e : a.entrySet())
if(!b.containsKey(e.getKey())
b.put(e.getKey(), e.getValue());
Edit to add:
If you can make changes to a, you can also do:
a.putAll(b)
and a will have exactly what you need. (all the entries in b and all the entries in a that aren't in b)
You can make it in just 1 line if you change maps order in #erickson's solution:
mapWithNotSoImportantValues.putAll( mapWithImportantValues );
In this case you replace values in mapWithNotSoImportantValues with value from mapWithImportantValues with the same keys.
Java 8 solution using Map#merge
As of java-8 you can use Map#merge(K key, V value, BiFunction remappingFunction) which merges a value into the Map using remappingFunction in case the key is already found in the Map you want to put the pair into.
// using lambda
newMap.forEach((key, value) -> map.merge(key, value, (oldValue, newValue) -> oldValue));
// using for-loop
for (Map.Entry<Integer, String> entry: newMap.entrySet()) {
map.merge(entry.getKey(), entry.getValue(), (oldValue, newValue) -> oldValue);
}
The code iterates the newMap entries (key and value) and each one is merged into map through the method merge. The remappingFunction is triggered in case of duplicated key and in that case it says that the former (original) oldValue value will be used and not rewritten.
With this solution, you don't need a temporary Map.
Let's have an example of merging newMap entries into map and keeping the original values in case of the duplicated antry.
Map<Integer, String> newMap = new HashMap<>();
newMap.put(2, "EVIL VALUE"); // this will NOT be merged into
newMap.put(4, "four"); // this WILL be merged into
newMap.put(5, "five"); // this WILL be merged into
Map<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
newMap.forEach((k, v) -> map.merge(k, v, (oldValue, newValue) -> oldValue));
map.forEach((k, v) -> System.out.println(k + " " + v));
1 one
2 two
3 three
4 four
5 five
public class MyMap {
public static void main(String[] args) {
Map<String, String> map1 = new HashMap<String, String>();
map1.put("key1", "value1");
map1.put("key2", "value2");
map1.put("key3", "value3");
map1.put(null, null);
Map<String, String> map2 = new HashMap<String, String>();
map2.put("key4", "value4");
map2.put("key5", "value5");
map2.put("key6", "value6");
map2.put("key3", "replaced-value-of-key3-in-map2");
// used only if map1 can be changes/updates with the same keys present in map2.
map1.putAll(map2);
// use below if you are not supposed to modify the map1.
for (Map.Entry e : map2.entrySet())
if (!map1.containsKey(e.getKey()))
map1.put(e.getKey().toString(), e.getValue().toString());
System.out.println(map1);
}}
With Java 8 there is this API method to accomplish your requirement.
map.putIfAbsent(key, value)
If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value.
As others have said, you can use putIfAbsent. Iterate over each entry in the map that you want to insert, and invoke this method on the original map:
mapToInsert.forEach(originalMap::putIfAbsent);
I need to call an external API with an ArrayList of HashMaps holding several predefined key-value pairs each. An example:
ArrayList<HashMap<String, String>> arrayListHashMap = new ArrayList<HashMap<String, String>>();
{
HashMap hashMap = new HashMap<String, String>();
hashMap.put("key", "A key");
hashMap.put("value", "B value");
arrayListHashMap.add(hashMap);
}
{
HashMap hashMap = new HashMap<String, String>();
hashMap.put("key", "B key");
hashMap.put("value", "A value");
arrayListHashMap.add(hashMap);
}
Now I need to sort this construct on the contents of the "value" key. This sort would result in the "key=B key/value=A value" entry as the first one in the arrayListHashMap.
Any help is highly appreciated.
HJW
You need to implement a Comparator<HashMap<String, String>> or more generally Comparator<Map<String, String>> which just extracts the value assocated with the value key, then use Collections.sort. Sample code (with generalization for whatever key you want to sort on):
class MapComparator implements Comparator<Map<String, String>>
{
private final String key;
public MapComparator(String key)
{
this.key = key;
}
public int compare(Map<String, String> first,
Map<String, String> second)
{
// TODO: Null checking, both for maps and values
String firstValue = first.get(key);
String secondValue = second.get(key);
return firstValue.compareTo(secondValue);
}
}
...
Collections.sort(arrayListHashMap, new MapComparator("value"));
You can use the below solution to achieve it:
arrayListHashMap.sort(Comparator.comparing(m -> m.get("value"), Comparator.nullsLast(Comparator.naturalOrder())));
(This is not an answer to the asked question - Jon did this already -, but the comment field is too small for this.)
Your data structure looks like you misunderstood the key-value structure of maps (and Hash maps in your example).
A Map can contain any number of keys, and for each key also a value. A pair of key and value is given by a Map.Entry (which can be obtained by the entrySet() method of the map). If you then want to sort by key, simply use a SortedMap (like TreeMap) instead of the usual HashMap.
You are emulating the individual entries by a HashMap each, then putting them all in a ArrayList ... :-/
Here what I would have done in your example:
Map<String, String> map = new TreeMap<String, String>();
map.put("B key", "B value");
map.put("A key", "B value");
System.out.println(map); // already sorted