I have a HashSet of (a hashmap of (string and list of (hashmap of (two strings))))
HashSet<HashMap<String1,List<HashMap<String2,HashMap<String3,String4>>>>>
Now, I need to search with String inputs (StrA and StrB) and this should search the HashSet on
StrA-->String1
StrB-->String2
and it should return the hashMap of String 3 and String 4.
This is what I tried.
HashSet<HashMap<String,List<HashMap<String,HashMap<String,String>>>>> ObjList;
public void getElement(String strA, String strB) {
if(ObjList.contains(strA) && ObjList.contains(strB))
System.out.println("Yes");
}
A solution using Streams would be :
HashSet<HashMap<String, List<HashMap<String, HashMap<String, String>>>>> fooSet = //;
String string1 = "string1";
String string2 = "string2";
HashMap<String, String> mapFound;
mapFound = fooSet.stream() // iterate over HashSet
.filter(map -> map.containsKey(string1)) // keep maps that contains string1
.findFirst() // take first map that match
.orElseGet(HashMap::new) // take it really (or create new Map)
.getOrDefault(string1, new ArrayList<>()) // take the List associated as value,or new List if not exists
.stream() // iterate over the list
.filter(map -> map.containsKey(string2)) // keep maps that contains string2
.findFirst() // take first map that match
.orElseGet(HashMap::new) // take it really (or create new Map)
.getOrDefault(string2, new HashMap<>()); // take HashMap associated as value, or new Map if not found
Solution with classic for each loop would be :
HashMap<String, String> mapFound;
for (HashMap<String, List<HashMap<String, HashMap<String, String>>>> map : fooSet) {
if (map.containsKey(string1)) {
List<HashMap<String, HashMap<String, String>>> list = map.get(string1);
for(HashMap<String, HashMap<String, String>> map2 : list){
if(map2.containsKey(string2)){
mapFound = map2.get(string2);
}
}
}
}
There is no other choice than iterating both, the outer Set and the inner List (untested):
HashSet<HashMap<String1,List<HashMap<String2,HashMap<String3,String4>>>>> outer = //...
HashMap<String3,String4> result =
outer.stream()
.findFirst(map1-> map1.containsKey(string1))
.get()
.stream()
.findFirst(map2-> map2.containsKey(string2))
.get();
Related
I have a map that contains Integer as key and (List of Map of String as key and boolean as the value) as value. Map<Int, List<Map<String, Boolean>>>, I want to populate a set that has Int as key of the outer map based on condition.
MyService.java
public Set<Integer> getValue(String input){
Map<String, Boolean> in1 = new HashMap<>();
in1.put("test_1", true);
Map<String, Boolean> in2 = new HashMap<>();
in2.put("test_2", false);
Map<String, Boolean> in3 = new HashMap<>();
in2.put("test_3", false);
Map<String, Boolean> in4 = new HashMap<>();
in2.put("test_4", true);
List<Map<String, Boolean>> l1 = new ArrayList<>();
l1.add(in1);
l1.add(in2);
List<Map<String, Boolean>> l2 = new ArrayList<>();
l2.add(in3);
l2.add(in4);
Map<Integer, List<Map<String,Boolean>>> map = new HashMap();
map.put(123, l1);
map.put(345, l2);
Set<Integer> result = new HashSet<>();
for(Map.Entry<Integer, List<Map<String, Boolean>>> entry : map.entrySet()){
for(Map<String, Boolean> m: entry.getValue() ){
if(m.containsKey(input) && m.get(input) == true){
result.add(entry.getKey());
}
}
}
return result;
}
So, basically I want to iterate from first the exterior map to get the internal map and then iterate the internal map to check if the input is present and add it to a set. How can I do this using java 8 streams?
I tried with for loop, but I will like to replace it using Java streams.
This produced the same results as your code in a test that passed "test_1", etc. into it.
map.entrySet().stream()
.filter(entry -> entry.getValue().stream()
.anyMatch(m -> m.getOrDefault(input, false)))
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
It consists of a map in the list object. I try to match lists with the same id by comparing them through loop statements. How can I convert to lambda?
List<Map<String, String>> combineList = new ArrayList<>(); // Temp List
for(Map titleMap : titleList) { // Name List
for(Map codeMap : codeList) { // Age List
if(titleMap.get("ID").equals(codeMap.get("ID"))) { // compare Id
Map<String,String> tempMap = new HashMap<>();
tempMap.put("ID", titleMap.get("ID"));
tempMap.put("NAME", titleMap.get("NAME"));
tempMap.put("AGE", codeMap.get("AGE"));
combineList.add(tempMap);
}
}
}
You are already doing it in efficient manner. So if you want you could change same code to just use stream().forEach or if want to use streams more do it as below:
titleList.stream()
.forEach(titleMap ->
combineList.addAll(
codeList.stream()
.filter(codeMap -> titleMap.get("ID").equals(codeMap.get("ID")))
.map(codeMap -> {
Map<String, Object> tempMap = new HashMap<>();
tempMap.put("ID", titleMap.get("ID"));
tempMap.put("NAME", titleMap.get("NAME"));
tempMap.put("ID", codeMap.get("ID"));
tempMap.put("AGE", codeMap.get("AGE"));
return tempMap;
})
.collect(Collectors.toList())
)
);
Notice that you have to filter from the codeList each time because your condition is that way. Try using a class in place of Map to be more efficient, cleaner and effective.
I have a list of values which concatenates the method name with the class name.
Ex: method1#class1
Now, I want to create a map where the key is the class name and values is a list of method names. The sample code is as follows.
Map<String, List<String>> map = new HashMap<>();
List<String> name = new ArrayList<>();
name.add("method1#class1");
name.add("method2#class1");
name.add("method3#class2");
name.add("method4#class2");
So, based on the above example, I need to create a map that should contain
{class1 : [method1,method2]}
{class2 : [method3,method4]}
Can someone help to iterate the above list and add to the map?
You can use streams in combination with the groupingBy collector:
Map<String, List<String>> result = name.stream()
.map(s -> s.split("#")) // split string by '#'
.collect(
Collectors.groupingBy(arr -> arr[1], // second element is the key
Collectors.mapping(arr -> arr[0], // first element is the value
Collectors.toList()))); // collect values with the same key into a list
System.out.println(result); // {class2=[method3, method4], class1=[method1, method2]}
You could do something like this:
Map<String, List<String>> map = new HashMap<String, List<String>>();
List<String> name = new ArrayList<String>();
name.add("method1#class1");
name.add("method2#class1");
name.add("method3#class2");
name.add("method4#class2");
for (String item : name) {
String[] split = item.split("#");
String className = split[1];
if(!map.containsKey(className))
map.put(className, new ArrayList<String>());
map.get(className).add(split[0]);
}
Good luck!
Clue about extracting method names from a class:
Class c = Example.class;
Method[] m = c.getDeclaredMethods();
for (Method method: m) {
System.out.println(method.getName());
}
I made all explanations in comments to the code:
Map<String, List<String>> map = new HashMap<>();
List<String> name = new ArrayList<>();
name.add("method1#class1");
name.add("method2#class1");
name.add("method3#class2");
name.add("method4#class2");
for(String nm : name) { // for each String from name list...
String[] splitted = nm.split("#"); // split this string on the '#' character
if(map.containsKey(splitted[1])) { // if result map contains class name as the key...
map.get(splitted[1]).add(splitted[0]); // get this key, and add this String to list of values associated with this key
} else { // if result map doesn't contain that class name as key...
map.put(splitted[1], new ArrayList<String>()); // put to map class name as key, initialize associated ArrayList...
map.get(splitted[1]).add(splitted[0]); // and add method name to ArrayList of values
}
}
I have the following Map:
Map<Long, List<Address>> map = new HashMap<Long, List<Address>>();
which is filled with pairs of keys and values.
For example: key = student id and
value = list of Address.
In Address object I have country name(String).
I want to sort the total map by the country name. I have tried many ways but not getting the Idea. Any ideas?
Below is my tried code.
private static Map<Long, List<Address>> sortByValue(Map<Long, List<Address>> unsortMap) {
// Convert Map to List of Map
List<Map.Entry<Long, List<Address>>> unSortedList =
new ArrayList<Map.Entry<Long, List<Address>>>(unsortMap.entrySet());
// sort the List
Collections.sort(unSortedList, new Comparator<Map.Entry<Long, List<Address>>>() {
public int compare(Map.Entry<Long, List<Address>> object1,
Map.Entry<Long, List<Address>> object2) {
// sort by country name
return ???;
}
});
// Loop the sorted list and put it into a new insertion order Map LinkedHashMap
Map<Long, List<Address>> sortedMap = new LinkedHashMap<Long, List<Address>>();
for (Map.Entry<Long, List<Address>> entry : unSortedList) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
You can create a temporary TreeMap inside the method and store the reverse mappings (i.e. country -> keys) into it. Once done, you can iterate over it and fill the values in the result, e.g.:
public static Map<Long, List<Address>> sort(Map<Long, List<Address>> map){
//Create temporary map, sorted by countries
Map<String, List<Long>> countryMap = new TreeMap<>();
map.entrySet().stream()
.forEach(e -> {
e.getValue()
.stream()
.map(a -> a.country)
.forEach(c -> countryMap.computeIfAbsent(c, k -> new ArrayList<Long>()).add(e.getKey()));
});
//Iterate over treemap and populate the values in result
Map<Long, List<Address>> sortedMap = new LinkedHashMap<>();
countryMap.entrySet()
.stream()
.flatMap(e -> e.getValue().stream())
.forEach(k -> sortedMap.put(k, map.get(k)));
return sortedMap;
}
I have a Map with key String and values String and a list of Strings. i want to sort the Map with keys based on the order of values present in the list.
package da.fa;
public class MapSorted {
public static void main(String[] args) {
List<String> efgh = new ArrayList<String>();
efgh.add("ccc");
efgh.add("aaa");
efgh.add("ddd");
efgh.add("aaa");
Map<String, String> abcd = new HashMap<String, String>();
abcd.put("aaa", "1111");
abcd.put("bbb", "1111");
abcd.put("ccc", "1111");
abcd.put("ddd", "1111");
abcd.put("eee", "1111");
}
}
in this, abcd should be sorted by the order of what values are in the list efgh has.
HashMaps are non-sortable, use TreeMap instead :
public static void main(String[] args) {
// define the needed keys
List<String> neededKeys = new ArrayList<String>();
neededKeys.add("ccc");
neededKeys.add("aaa");
neededKeys.add("ddd");
neededKeys.add("aaa");
// build a simple hashmap (unsorted)
Map<String, String> unsortedMap = new HashMap<String, String>();
unsortedMap.put("aaa", "1111");
unsortedMap.put("bbb", "1111");
unsortedMap.put("ccc", "1111");
unsortedMap.put("ddd", "1111");
unsortedMap.put("eee", "1111");
// build a sorted TreeMap and pass only the necessary objects
TreeMap<String, String> sortedMap=new TreeMap<String, String>();
for(String key:unsortedMap.keySet()){
// copy needed keys ONLY to a new sorted map
if (neededKeys.contains(key)){
sortedMap.put(key, unsortedMap.get(key));
}
}
System.out.println(unsortedMap);
System.out.println(sortedMap);
}
If follow suggestion from the aforementioned post how to sort Map values by key in Java, you should write something like this:
Comparator<Foo> comparator = new Comparator<Foo>() {
List<String> final order = .. //Pass your list here;
public int compare(String o1, Stringo2) {
int i1 = order.ingexOf(o1);
int i2 = order.indexOf(o2);
return i1 > i2 ? 1 : (i1 < i1 ? -1 : 0);
}
}
Map<String, String> map = new TreeMap<>(comparator);
map.addAll(abcd);
But what do you need it for? If you want to iterate through this map latter, you can iterate through the list and then fetch value. It will be faster.
And you should remove duplicates from your list:
List<String> efgh = new ArrayList<String>();
...
efgh.add("aaa");
..
efgh.add("aaa");
Otherwise this solution wont work.