I have a LinkedHashMap and would like to do the following:
For example, if I have a LinkedHashMap like the below
HashMap<String, String> nameNum = new LinkedHashMap<String, String>();
nameNum.put("row 1", "data 1");
nameNum.put("Group_Colour_R", "Red");
nameNum.put("Group_Colour_B", "Blue");
nameNum.put("row 4", "data 4");
nameNum.put("row 5", "data 5");
nameNum.put("Group_Shape_R", "Rectangle");
nameNum.put("Group_Shape_T", "Triangle");
nameNum.put("Group_Shape_C", "Circle");
nameNum.put("row 9", "data 9");
nameNum.put("row 10", "data 10");
nameNum.put("row 11", "data 11");
After looping through the above HashMap, I should have 2 String[]
String[] colour = {"Red", "Blue"};
String[] shape = {"Rectangle", "Triangle", "Circle"};
I'm just not sure how to achieve it.
There is something related to what I want and found it here: Partial search in HashMap
Based on the above I implemented it like below but, as you would see, it runs the same values multiple times. I'm not sure when and how to break the loop so that it only gives the values once:
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
public class MainClass {
public static void main(String[] args) {
SortedMap<String, String> nameNum = new TreeMap<String, String>();
nameNum.put("row 1", "data 1");
nameNum.put("Group_Colour_R", "Red");
nameNum.put("Group_Colour_B", "Blue");
nameNum.put("row 4", "data 4");
nameNum.put("row 5", "data 5");
nameNum.put("Group_Shape_R", "Rectangle");
nameNum.put("Group_Shape_T", "Triangle");
nameNum.put("Group_Shape_C", "Circle");
nameNum.put("row 9", "data 9");
nameNum.put("row 10", "data 10");
nameNum.put("row 11", "data 11");
for (Map.Entry<String, String> entry : nameNum.entrySet()) {
String prefix = entry.getKey();
if (prefix.contains("Group")) {
prefix = prefix.substring(0, StringUtils.lastIndexOf(prefix, "_"));
System.out.println("******");
for (Map.Entry<String, String> entry1 : filterPrefix(nameNum, prefix).entrySet()) {
System.out.println(entry1);
}
System.out.println("******");
}
}
}
public static <V> SortedMap<String, V> filterPrefix(SortedMap<String,V> baseMap, String prefix) {
if(prefix.length() > 0) {
char nextLetter = (char) (prefix.charAt(prefix.length() -1) + 1);
String end = prefix.substring(0, prefix.length()-1) + nextLetter;
return baseMap.subMap(prefix, end);
}
return baseMap;
}
}
Ideally, I'd like to use a LinkedHashMap because I want to preserve the order. I'd highly appreciate any pointers/code on how to implement something similar. Any code snippet would be highly appreciated. Thanks in advance.
Perhaps Java 8 Stream
API could be helpful here. You can try to group the relevant entries together using Collectors.groupingBy
:
Map<String,List<String>> groups =
nameNum.entrySet()
.stream()
.filter(entry -> entry.getKey().contains("Group"))
.collect(Collectors.groupingBy(entry -> entry.getKey().substring(0, entry.getKey().lastIndexOf("_")),
Collectors.mapping(Map.Entry::getValue,
Collectors.toList()));
This produces a Map
the contains:
{Group_Shape=[Rectangle, Triangle, Circle], Group_Colour=[Red, Blue]}
You can also force the output Map
to be a LinkedHashMap
if you prefer:
Map<String,List<String>> groups =
nameNum.entrySet()
.stream()
.filter(entry -> entry.getKey().contains("Group"))
.collect(Collectors.groupingBy(entry -> entry.getKey().substring(0, entry.getKey().lastIndexOf("_")),
LinkedHashMap::new,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList()));
This would alter the iteration order of the output Map
:
{Group_Colour=[Red, Blue], Group_Shape=[Rectangle, Triangle, Circle]}