1

I have a LinkedHashMap and would like to do the following:

  1. loop through the HashMap and check if the string in the Key contains 'Group' word in it
  2. create String[] of all the Values matching that Key string

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.

Community
  • 1
  • 1
SDN
  • 47
  • 1
  • 6
  • if you want to search in hashmap and return values which their keys are contain "Group" word, you will have single string array as output. in your example; you will return String[] returnList = {"Red", "Blue", "Rectangle", "Triangle", "Circle"}; how do you distinguish between {"Red", "Blue"} and {"Rectangle", "Triangle", "Circle"} ????while both match your key pattern (contain "Group") !! – M2E67 Apr 30 '17 at 06:04

3 Answers3

0

Please remove the for loops to avoid multiple duplicate results. You need to have two calls with "Group_"Colour" and "Group_Shade" as prefix to the filter method to get the desired results.

OTM
  • 656
  • 5
  • 8
0

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]}
Eran
  • 387,369
  • 54
  • 702
  • 768
  • that is precisely what I was after. You've made my day :-) Java 8 keeps on surprising me! – SDN Apr 30 '17 at 06:32
  • Unfortunately I can't select your answer as the preferred solution because I don't have the right access to do it. If I did I'd have selected your answer. Thanks again and much appreciated. – SDN Apr 30 '17 at 06:39
  • @SDN You're welcome. You should have the right access to accept the answer (that's a privilege any user has). You just have to click the check mark next to it. – Eran Apr 30 '17 at 06:44
0

Instead of Arrays for storing Group values, you can use HashMap as shown below :

HashMap<String,ArrayList<String>> groupList = new HashMap<String, ArrayList<String>>();

Then inside loop you can implement below logic to store repespective Group Key and their values :

if(prefix.contains("Group")){
    String keyGrp = prefix.split("_")[1];
    if(groupList.containsKey(keyGrp)){
        groupList.get(keyGrp).add(entry.getValue());
    }else{
        ArrayList<String> grpVal = new ArrayList<String>();
        grpVal.add(entry.getValue());
        groupList.put(keyGrp, grpVal);
    }
}
Nishesh Pratap Singh
  • 2,131
  • 2
  • 13
  • 20
  • Thanks a lot for your response. Your answer does exactly what I was looking for, please see @Eran's answer above, it has less lines of code. Much appreciate for your time in providing an answer. – SDN Apr 30 '17 at 06:36
  • Yup, I had seen @Eran's answers but that was in Java 8, and mine is for rest. :) – Nishesh Pratap Singh Apr 30 '17 at 06:44