0

I have a method in which I am trying to return a Map<String, Long> with a stream of strings as its parameter.

The string is a line from a csv file with comma separated lines and values.

What I want to return is a map of ONLY the Num 1-4 columns and the counts of their occurrences of the number 1.

The example str that I defined below is expected to return a Map<String, Long> of {Num1 = 1, Num2 = 0, Num3 = 2, Num4 = 1}.

My main issue is that I do not understand how to collect the ones from each of these columns as I assume that they are multiple objects and a terminal collect operation can seemingly only cover one column.

public static Map<String, Long> returnNumCountsOf1(Stream<String> str) {

// returns a map with the name of the Num columns (key) and their counts (value) of the number 1

// ex.) str = "WORD1  WORD2  WORD3  WORD4  Num1 Num2 Num3 Num4  WN1  WN2  WN3",
                "a,    b,      c,     d,   1,   2,   3,   4,   one, two, three",
                "e,    f,      g,     h,   4,   3,   1,   2,   one, two, seven",
                "i,    j,      k,     l,   2,   4,   3,   1,   one, nine, eleven",
                "m,    n,      o,     p,   3,   4,   1,   2,   one, five, three";


        Map<String, Long> pow = new HashMap<>();
        pow = str
                .map(x -> x.split(","))
                .skip(1) //ignores the header
                .filter(x -> x.length == 11) // splits into indexes
                
                .collect(Collectors.groupingBy(x -> x[5]?, Collectors.counting()));
       return pow;
//Expected return value should be {Num1=1, Num2=0, Num3=2, Num4=1}.
2
  • 1
    Could you make the example CSV as simple as possible and add the exact expected return? As it is "bla","bla"... should give syntax errors. And the variable 'string' comes out of nowhere.... Both the variable name string and the function name countAllInstancesOfOne don't seem like good names. The current state of your question is very confusing. Commented Feb 16, 2022 at 0:25
  • Ah, I see. Sorry about that, I am new to using Stack Overflow and missed a few things when I was typing it all out. Commented Feb 16, 2022 at 2:06

1 Answer 1

2

First of all, do not perform obsolete initialization like Map<String, Long> pow = new HashMap<>(); The HashMap you’re creating here has no relationship to the result of the stream operation you’re assigning to pow right in the next statement. So you’re only creating garbage here.

To collect more than one element for a source stream element, you can use flatMap to map each input element to an arbitrary number of elements. Sometimes, you need to use dedicated objects as stream elements to hold multiple associated data, like the column name and its value, but here, we can get away without, when chaining the operations in a carefully chosen order:

Map<String, Long> pow = str
    .skip(1)
    .map(s -> s.split(","))
    .filter(a -> a.length == 11)
    .flatMap(a -> IntStream.rangeClosed(1, 4)
        .filter(i -> a[i + 3].trim().equals("1"))
        .mapToObj(i -> "Num" + i))
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

The actual value is only needed for the filter, which is applied first, before mapping to the key needed for the final collect operation. The key is constructed by mapping the numbers 1…4 to Num1…Num4. If you have column names not constructible this way, you could map using an array of the known column names. Keep in mind that array indices start with zero.

Since the resulting Stream is a Stream of column names occurring as ofter as they had a corresponding "1" value, you only need to group them to their count of occurrences. With your example input, it produces {Num1 = 1, Num3 = 2, Num4 = 1}, with nondeterministic order, without entries for columns with zero matches.

Sign up to request clarification or add additional context in comments.

Comments

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.