Convert logic to Streams (Java) (nested for loops with counter)

Viewed 40

Dears,

I'm new to Streams and want to convert some logic to using them:

this is the logic:

    for (String headerKey : map.keySet()) {
        int counter = 1;
        for (String value : map.get(headerKey)) {
            if (map.get(headerKey).size() != 1) {
                System.out.println("Response header: " + headerKey + "[" + counter++ + "]: " + value);
            } else {
                System.out.println("Response header: " + headerKey + ": " + value);
            }
        }
    }

the problem is the "counter"...

I got as far as:

private static long after(Map<String, List<String>> map) {

    return map.keySet().stream().map(key -> output(key, map)).count(); // use print() here instead of output()
}

private static String output(String key, Map<String, List<String>> map) {

    counter = 1;

    long longString = map.get(key).stream().map(value -> print(value, key, map.get(key))).count();

    return "" + longString;
}

private static String print(String value, String key, List<String> strings) {

    if (strings.size() != 1) {
        System.out.println("Response header: " + key + "[" + counter++ + "]: " + value);
    } else {
        System.out.println("Response header: " + key + ": " + value);
    }

    return "";
}

And I suppose I can put the print() method at the indicated spot,

but I don't know how to get the counter to behave as in the original code...

All comment/ideas are welcome :)

Thanks beforehand!

1 Answers

Create a helper method like

static Stream<String> values(List<?> list) {
    return list.size() == 1? Stream.of(": " + list.get(0)):
        IntStream.range(0, list.size()).mapToObj(ix -> "[" + ix + "]: " + list.get(ix));
}

Instead of re-evaluating the list.size() == 1 condition in each iteration, it selects the right shape of the operation upfront. When the size is not one, rather than trying to maintain a counter, stream over the index range in the first place.

This method now can be used when streaming over the map, like

map.entrySet().stream()
    .flatMap(e -> values(e.getValue()).map(("Response header: " + e.getKey())::concat))
    .forEach(System.out::println);
Related