Have a two list of Map, should do the dataset joins on those two lists, leftJoin, rightJoin, outerJoin and innerJoin
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
public class JoinMap {
public static List<Map<String, Object>> getFirstMap() {
List<Map<String, Object>> data = new ArrayList<>();
Map<String, Object> dataMap2 = new HashMap<>();
dataMap2.put("user", "vs");
dataMap2.put("data1", 12.0);
dataMap2.put("data2", 42.0);
dataMap2.put("data3", 32.0);
data.add(dataMap2);
Map<String, Object> dataMap1 = new HashMap<>();
dataMap1.put("user", "samraj");
dataMap1.put("data1", 11.0);
dataMap1.put("data2", 41.0);
dataMap1.put("data3", 31.0);
data.add(dataMap1);
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("user", "varghees");
dataMap.put("data1", 10.0);
dataMap.put("data2", 40.0);
dataMap.put("data3", 30.0);
data.add(dataMap);
return data;
}
public static List<Map<String, Object>> getSecondMap() {
List<Map<String, Object>> data = new ArrayList<>();
Map<String, Object> dataMap2 = new HashMap<>();
dataMap2.put("user", "vs");
dataMap2.put("test1", 12.0);
dataMap2.put("test2", 42.0);
dataMap2.put("test3", 32.0);
data.add(dataMap2);
Map<String, Object> dataMap1 = new HashMap<>();
dataMap1.put("user", "samraj");
dataMap1.put("test1", 11.0);
dataMap1.put("test2", 41.0);
dataMap1.put("test3", 31.0);
data.add(dataMap1);
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("user", "varghees");
dataMap.put("test1", 10.0);
dataMap.put("test2", 40.0);
dataMap.put("test3", 30.0);
data.add(dataMap);
return data;
}
public static List<Map<String, Object>> leftJoin(List<Map<String, Object>> map1, List<Map<String, Object>> map2) {
}
public static List<Map<String, Object>> rightJoin(List<Map<String, Object>> map1, List<Map<String, Object>> map2) {
}
public static List<Map<String, Object>> innerJoin(List<Map<String, Object>> map1, List<Map<String, Object>> map2) {
}
public static List<Map<String, Object>> outerJoin(List<Map<String, Object>> map1, List<Map<String, Object>> map2) {
}
public static void main(String[] argv) {
List<Map<String, Object>> firstMap = getFirstMap();
List<Map<String, Object>> secondMap = getSecondMap();
}
}
Is there any easy functions available in Java8 to accomplish these methods? I am trying to avoid iterating over data and populate new dataset.
Sure there is. Here’s an example using streams for the inner join. I am assuming we know for a fact that we should join on "user" (if not, it’s getting more complicated, but it still can be done).
public static List<Map<String, Object>> innerJoin(List<Map<String, Object>> map1, List<Map<String, Object>> map2) {
return map1.stream().flatMap(m1 ->
map2.stream()
.filter(m2 -> m1.get("user").equals(m2.get("user")))
.map((Map<String, Object> m2) -> {
Map<String, Object> mr = new HashMap<>();
mr.putAll(m1);
mr.putAll(m2);
return mr;
})
).collect(Collectors.toList());
}
I hope and think you will be able to take the inspiration and do the others yourself.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have a list of maps
List<Map<String, Object>> myList = [{value1=3, value2=11},{value1=8, value2=16},{value1=3, value2=11},{value1=10, value2=11} ...]
and I want to extract value2 to a new list of maps but have only unique values there:
List<Map<String, Object>> res = [{value2=11},{value2=16} ...]
What id the best way to do it?
Try this. Here first I am creating a list of Entry<value2, anyUniqueValue> by using 2 functions.
First filtering only those Entries which has key value2 by using function filterFunction
Secondly by filtering unique value by using function distinctByValue
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Demo{
public static void main(String[] args) {
List<Map<String, Object>> myList = new ArrayList<>();
Map<String, Object> map1 = new HashMap<>();
map1.put("value1", 3);
map1.put("value2", 11);
Map<String, Object> map2 = new HashMap<>();
map2.put("value1", 8);
map2.put("value2", 16);
Map<String, Object> map3 = new HashMap<>();
map3.put("value1", 3);
map3.put("value2", 11);
Map<String, Object> map4 = new HashMap<>();
map4.put("value1", 10);
map4.put("value2", 11);
myList.add(map1);
myList.add(map2);
myList.add(map3);
myList.add(map4);
List<Entry<String, Object>> list = myList.stream().flatMap(map -> map.entrySet().stream())
.filter(s -> filterFuction(s)).filter(distinctByValue(entry -> entry.getValue()))
.collect(Collectors.toList());
List<Map<String, Object>> list1 = list.stream().map(t -> {
Map<String, Object> map = new HashMap<>();
map.put(t.getKey(), t.getValue());
return map;
}).collect(Collectors.toList());
System.out.println(list1);
}
public static <T> Predicate<T> distinctByValue(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
public static boolean filterFuction(Entry<String, Object> entry) {
if (entry.getKey().equals("value2"))
return true;
return false;
}
}
I am not able get the code to go to else block. The code always goes inside if block. Is there a way to validate the value of a Map<String, Map<String,String>>.
I get compile warning Map<String, Map<String, String>> may not contain values of type String.
Could anyone please tell me how to validate this?
public class TestClass {
Map<String, String> map = new HashMap<String, String>();
Map<String, Map<String, String>> val= new HashMap<String, Map<String, String>>();
public void setData() {
map = new HashMap<String, String>();
map.put("10", "1000");
map.put("11", "alphabet");
map.put("12", "1002");
map.put("13", "1003");
val.put("1", map);
val.put("2", map);
val.put("3", map);
val.put("4", map);
}
public void showData() {
if (!this.val.containsValue("alphabet")) {
System.out.println("inside if ");
} else {
System.out.println("else");
}
}
public static void main(String args[]) {
TestClass obj = new TestClass();
obj.setData();
obj.showData();
}
}
I have a hashmap used to store the platform details
I need to iterate Map<String, Map<String, String>> finalmapWin8
and get the values and keys of mapWin8
values 33,8 and key BrowserType.CHROME, BrowserType.FIREFOX and BrowserType.IE
Also i want to get the key of 'finalmapWin8' "WIN8_1"
How can i iterate Map<String, Map<String, String>> finalmapWin8
static Map<String, Map<String, String>> finalmapWin8 = new HashMap<Platform, Map<String, String>>();
public static final Map<String, String> mapWin8 = new HashMap<String, String>();
static {
mapWin8.put(BrowserType.CHROME, "33");
mapWin8.put(BrowserType.FIREFOX, "33");
mapWin8.put(BrowserType.IE, "8");
}
static {
finalmapWin8.put("WIN8_1", mapWin8);
}
iteration for Map is the same. since your value for your map is also a Map then you just need another iteration to iterate through it.
for(String s: finalmapWin8.keySet()){
System.out.println(s + " : ");
for(Entry<String, String> entry : finalmapWin8.get(s).entrySet()){
System.out.println(entry);
}
}
You can use a for loop for loop for Map of type Map.Entry<String, Map<String, String>> ... well, that's it.. See the code snippet below -
import java.util.HashMap;
import java.util.Map;
public class Test {
static Map<String, Map<String, String>> finalmapWin8 = new HashMap<String, Map<String,String>>();
public static final Map<String, String> mapWin8 = new HashMap<String, String>();
static {
mapWin8.put("CHROME", "33");
mapWin8.put("FIREFOX", "33");
mapWin8.put("IE", "8");
}
static {
finalmapWin8.put("WIN8_1", mapWin8);
}
public static void main(String[] args) {
for(Map.Entry<String, Map<String, String>> entry : finalmapWin8.entrySet()) {
System.out.println(entry.getValue());
}
}
}
// get the keysets or outer map and then again run a secound loop for inner map.
for (Map.Entry<String, Map<String, String>> entry : firstMap) {
system.out.println("entry="+entry );
}
Refer to How to efficiently iterate over each Entry in a Map?
You can use below code for iterating through HashMap
for (Map.Entry<String, Map<String, String>> entry : finalmapWin8.entrySet()) {
System.out.println("Key:"+entry.getKey());
for (Map.Entry<String, String> entry1 : mapWin8.entrySet()) {
System.out.println("Keys in Second:"+ entry1.getKey()+" Values:"+ entry1.getValue());
}
}
I have a List<Map<String, Object>> which contains the following maps.
Map:{clusterList=[71051], senseId=65786, totalCluster=1}
Map:{clusterList=[71051], senseId=65787, totalCluster=1}
Map:{clusterList=[4985, 71052], senseId=65788, totalCluster=2}
Map:{clusterList=[125840,153610,167812, 65787, 204091, 32586, 65786], senseId=71051, totalCluster=7}
Map:{clusterList=[11470, 65788], senseId=71052, totalCluster=2}
I have traversed the map and checked if senseId is present in the clusterList. But traversing each clusterList with senseId is taking long time with traditional for loop and also I am unable to get the merged list as the following
Map:{clusterList=[125840,153610,167812, 65787, 204091, 32586, 65786], senseId=71051, totalCluster=7}
Map:{clusterList=[4985,11470, 65788], senseId=71052, totalCluster=2}
I cant even remove the map with sensId present in the clusterList as it throws as concurrent operation exception.
Any ideas how to get to the result other than for loop as this list is very small so for loop still works. But I have list with 180 map entries and its hard to traverse the whole list and merge the maps.
I am stuck because the senseId of one map is present in clusterList of other map. So not able to merge them with simple search.
I'm rather sure that the problem is still underspecified. For example, it is not clear how to decide about the final senseId. When you have two maps
Map:{clusterList=[123,456,789], senseId=123, totalCluster=1}
Map:{clusterList=[123,456,666], senseId=456, totalCluster=1}
then (if I understood you correctly) they should be merged. But it is not clear whether the result should be a map
Map:{clusterList=[123,456,789,666], senseId=123, totalCluster=1}
or a map
Map:{clusterList=[123,456,789,666], senseId=456, totalCluster=1}
Apart from that, it seems like the "totalCluster" is the size of the cluster list. This means that it is most likely unnecessary, and if it is not unnecessary, you'd have to specify how it should be treated when two maps are merged.
However, here is a basic approach: One can create a map from senseId to maps with this senseId, and afterwards collect the maps that contain a certain senseId in their cluster list in order to find out which maps have to be merged.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapMergeTest
{
public static void main(String[] args)
{
List<Map<String, Object>> maps = createInput();
System.out.println("Input:");
for (Map<String, Object> map : maps)
{
System.out.println(map);
}
List<Map<String, Object>> result = createMergedMapsList(maps);
System.out.println("Result:");
for (Map<String, Object> map : result)
{
System.out.println(map);
}
}
private static List<Map<String, Object>> createInput()
{
List<Map<String, Object>> maps = new ArrayList<Map<String, Object>>();
// senseId clusterList...
maps.add(createMap(65786, 71051));
maps.add(createMap(65787, 71051));
maps.add(createMap(65788, 4985, 71052));
maps.add(createMap(71051, 125840, 153610, 167812,
65787, 204091, 32586, 65786));
maps.add(createMap(71052, 11470, 65788));
return maps;
}
private static Map<String, Object> createMap(
Integer senseId, Integer ... clusters)
{
Map<String, Object> result = new LinkedHashMap<String, Object>();
result.put("senseId", senseId);
result.put("clusterList", new ArrayList<Integer>(Arrays.asList(clusters)));
return result;
}
private static List<Map<String, Object>> createMergedMapsList(
List<Map<String, Object>> maps)
{
Map<Integer, Map<String, Object>> senseIdToMap =
createSenseIdToMap(maps);
Map<Integer, Map<String, Object>> copy =
new LinkedHashMap<Integer, Map<String,Object>>(senseIdToMap);
for (Entry<Integer, Map<String, Object>> e : copy.entrySet())
{
Integer senseId = e.getKey();
Map<String, Object> map = e.getValue();
List<Integer> clusterList = getClusterList(map);
List<Map<String, Object>> mapsToMerge =
new ArrayList<Map<String,Object>>();
mapsToMerge.add(map);
for (Integer cluster : clusterList)
{
Map<String, Object> mapToMerge =
senseIdToMap.get(cluster);
if (mapToMerge != null)
{
mapsToMerge.add(mapToMerge);
senseIdToMap.remove(cluster);
}
}
if (mapsToMerge.size() > 1)
{
Map<String, Object> mergedMap = mergeMaps(mapsToMerge);
List<Integer> mergedClusterList = getClusterList(mergedMap);
mergedClusterList.remove(senseId);
senseIdToMap.put(senseId, mergedMap);
}
}
return new ArrayList<Map<String,Object>>(senseIdToMap.values());
}
private static Map<Integer, Map<String, Object>> createSenseIdToMap(
List<Map<String, Object>> maps)
{
Map<Integer, Map<String, Object>> senseIdToMap =
new LinkedHashMap<Integer, Map<String,Object>>();
for (Map<String, Object> map : maps)
{
Integer senseId = (Integer)map.get("senseId");
senseIdToMap.put(senseId, map);
}
return senseIdToMap;
}
private static Map<String, Object> mergeMaps(List<Map<String, Object>> list)
{
Map<String, Object> mergedMap = new LinkedHashMap<String, Object>();
Map<String, Object> firstMap = list.get(0);
mergedMap.put("senseId", firstMap.get("senseId"));
Set<Integer> mergedClusterList = new LinkedHashSet<Integer>();
for (Map<String, Object> map : list)
{
List<Integer> clusterList = getClusterList(map);
mergedClusterList.addAll(clusterList);
}
mergedMap.put("clusterList", new ArrayList<Integer>(mergedClusterList));
return mergedMap;
}
private static List<Integer> getClusterList(Map<String, Object> map)
{
Object object = map.get("clusterList");
return (List<Integer>)object;
}
}
Map<String, String> listOfIndexes = INDEXED_TABLES.get(tableName);
Iterator it = listOfIndexes.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println(pairs.getKey());
}
My Hashmap is like this :
public static Map<String, Map<String, String>> INDEXED_TABLES = new HashMap<String, Map<String, String>>()
{{
put("employee", EMPLOYEE);
}};
public static Map<String, String> EMPLOYEE = new HashMap<String, String>()
{{
put("name", "Test");
put("age", "Test");
put("sex", "test");
}};
This is because you outsmarted yourself: your initializers depend on the order of execution. At the time this line runs
put("employee", EMPLOYEE);
EMPLOYEE is still null, so that's what gets put into your Map<String,Map<String,String>>.
You can switch the order of initializers to fix this problem. However, you would be better if you put initialization code into a separate initializer, rather than using anonymous classes with custom initializers:
public static Map<String, Map<String, String>> INDEXED_TABLES = new HashMap<String, Map<String, String>>();
public static Map<String, String> EMPLOYEE = new HashMap<String, String>();
static {
EMPLOYEE.put("name", "Test");
EMPLOYEE.put("age", "Test");
EMPLOYEE.put("sex", "test");
INDEXED_TABLES.put("employee", EMPLOYEE);
}
It looks like you are putting EMPLOYEE into the map before it has been initialized, so it will be null (and remain so, even if you assign something to EMPLOYEE later).
Reverse the order of the two statements.
Or, while in general I disapprove of the double-brace-initializer (hopefully, we'll get proper Collection literals in Java 8):
public static Map<String, Map<String, String>> INDEXED_TABLES =
new HashMap<String, Map<String, String>>(){{
put("employee", new HashMap<String, String>(){{
put("name", "Test");
put("age", "Test");
put("sex", "test");
}}
}}