1

I have a set of strings like this

A_2007-04, A_2007-09, A_Agent, A_Daily, A_Execute, A_Exec, B_Action, B_HealthCheck

I want output as:

Key = A, Value = [2007-04,2007-09,Agent,Execute,Exec]
Key = B, Value = [Action,HealthCheck]

I'm using HashMap to do this

pckg:{A,B}
count:total no of strings
reports:set of strings

Logic I used is nested loop:

for (String l : reports[i]) {
    for (String r : pckg) {
        String[] g = l.split("_");
        if (g[0].equalsIgnoreCase(r)) {
            report.add(g[1]);
            dirFiles.put(g[0], report);
        } else {
            break;
        }
    }
}

I'm getting output as

Key = A, Value = [2007-04,2007-09,Agent,Execute,Exec]

How to get second key? Can someone suggest logic for this?

3
  • What is the value of pckg? Commented Sep 9, 2016 at 13:13
  • 1
    First, your variable names are confusing. You should give them meaningful names. Second, what is the type of pckg? Seems weird that you are looping through the pckg variable while in the for loop of reports[i] Commented Sep 9, 2016 at 13:15
  • with P_Action and P_HealthCheck, you cannot get Key = B, Value = [Action,HealthCheck], you can only get it with Key = P so pckg should be:{A,P} not {A,B} Commented Sep 9, 2016 at 13:19

4 Answers 4

1

Assuming that you use Java 8, it can be done using computeIfAbsent to initialize the List of values when it is a new key as next:

List<String> tokens = Arrays.asList(
    "A_2007-04", "A_2007-09", "A_Agent", "A_Daily", "A_Execute", 
    "A_Exec", "P_Action", "P_HealthCheck"
);
Map<String, List<String>> map = new HashMap<>();
for (String token : tokens) {
    String[] g = token.split("_");
    map.computeIfAbsent(g[0], key -> new ArrayList<>()).add(g[1]);
}
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for bringing computeIfAbsent to my attention. I'd been wondering for some time why Java core hadn't made it easier to handle a map whose values were themselves a collection, and this fills the gap nicely.
0

In terms of raw code this should do what I think you are trying to achieve:

// Create a collection of String any way you like, but for testing
// I've simply split a flat string into an array.
String flatString = "A_2007-04,A_2007-09,A_Agent,A_Daily,A_Execute,A_Exec,"
        + "P_Action,P_HealthCheck";
String[] reports = flatString.split(",");

Map<String, List<String>> mapFromReportKeyToValues = new HashMap<>();

for (String report : reports) {
    int underscoreIndex = report.indexOf("_");
    String key = report.substring(0, underscoreIndex);
    String newValue = report.substring(underscoreIndex + 1);
    List<String> existingValues = mapFromReportKeyToValues.get(key);
    if (existingValues == null) {
        // This key hasn't been seen before, so create a new list
        // to contain values which belong under this key.
        existingValues = new ArrayList<>();
        mapFromReportKeyToValues.put(key, existingValues);
    }
    existingValues.add(newValue);
}

System.out.println("Generated map:\n" + mapFromReportKeyToValues);

Though I recommend tidying it up and organising it into a method or methods as fits your project code.

Comments

0

Doing this with Map<String, ArrayList<String>> will be another good approach I think:

    String reports[] = {"A_2007-04", "A_2007-09", "A_Agent", "A_Daily", 
                        "A_Execute", "A_Exec", "P_Action", "P_HealthCheck"};
    Map<String, ArrayList<String>> map = new HashMap<>();

    for (String rep : reports) {

        String s[] = rep.split("_");
        String prefix = s[0], suffix = s[1];
        ArrayList<String> list = new ArrayList<>();

        if (map.containsKey(prefix)) {
            list = map.get(prefix);
        }

        list.add(suffix);
        map.put(prefix, list);
    }

    // Print
    for (Map.Entry<String, ArrayList<String>> entry : map.entrySet()) {
        String key = entry.getKey();
        ArrayList<String> valueList = entry.getValue();
        System.out.println(key + " " + valueList);
    }

Comments

0
for (String l : reports[i]) {
        String[] g = l.split("_");
        for (String r : pckg) {
            if (g[0].equalsIgnoreCase(r)) {
                report = dirFiles.get(g[0]);
                if(report == null){ report = new ArrayList<String>(); } //create new report
                report.add(g[1]);
                dirFiles.put(g[0], report);
            }
        }
}
  • Removed the else part of the if condition. You are using break there which exits the inner loop and you never get to evaluate the keys beyond first key.
  • Added checking for existing values. As suggested by Orin2005.
  • Also I have moved the statement String[] g = l.split("_"); outside inner loop so that it doesn't get executed multiple times.

2 Comments

In the line dirFiles.put(g[0], report);, I think you need to account for everything that is already in the HashMap for that key aswell. so it should be dirFiles.put(g[0], dirFiles.get(g[0]).addAll(report)); or something, depending on what the value of report is.
I assume report is List of Strings and dirFiles is HashMap with key-type String and value-type List of Strings. In that case it'd work as expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.