Panagiss
Panagiss

Reputation: 3750

Compare String with each element of a String Array using Streams

Hi i want to count how many time a String is found in a Array of Strings using Streams

What i have thought so far is this:

Stream<String> stream=Arrays.stream(array);

int counter= (int) stream.filter(c-> c.contains("something")).count();

return counter;

The problem that i get is that most of the time i get an error of NullPointerException and i think is because of .count() if it doesn't get any much inside filter(c-> c.contains("something")). And i came to this conclusion cause if i run it with out .count() like that stream.filter(c-> c.contains("something")); without returning nothing, it won't throw an Exception. I'm not sure about it but that's what i think.

Any ideas on how i can count the times a String appears in and Array of Strings using Streams?

Upvotes: 0

Views: 1521

Answers (3)

Ousmane D.
Ousmane D.

Reputation: 56499

The problem that i get is that most of the time i get an error of NullPointerException and i think is because of .count() And i came to this conclusion cause if i run it with out .count() it won't throw an Exception.

The reason being you cannot replicate the NullPointerException without calling count is because streams are lazy evaluated i.e. the entire pipeline is not executed until an eager operation (an operation which triggers the processing of the pipeline) is invoked.

We can come to the conclusion that Arrays.stream(array) is not the culprit for the NullPointerException because it would have blown up regardless of wether you called an eager operation on the stream or not as the parameter to Arrays.stream should be nonNull or else it would bomb out with the aforementioned error.

Thus we can come to the conclusion that the elements inside the array are the culprits for this error in the code you've illustrated but then you should ask your self are null elements allowed in the first place and if so then filter them out before performing c.contains("something") and if not then you should debug at which point in your application were nulls added to the array when they should not be. find the bug rather than suppress it.

if null's are allowed in the first place then the solution is simple i.e. filter the nulls out before calling .contains:

int counter = (int)stream.filter(Objects::nonNull)
                         .filter(c -> c.contains("something")) // or single filter with c -> c != null && c.contains("something") as pred
                         .count();

Upvotes: 2

deHaar
deHaar

Reputation: 18588

You have to filter for null values first. Do it either the way @pafauk. answered or by filtering sepraretly. That requires the null filter to be applied before the one you already use:

public static void main(String[] args) {
    List<String> chainedChars = new ArrayList<>();
    chainedChars.add("something new");  // match
    chainedChars.add("something else"); // match
    chainedChars.add("anything new");
    chainedChars.add("anything else");
    chainedChars.add("some things will never change");
    chainedChars.add("sometimes");
    chainedChars.add(null);
    chainedChars.add("some kind of thing");
    chainedChars.add("sumthin");
    chainedChars.add("I have something in mind");   // match
    chainedChars.add("handsome thing");

    long somethings = chainedChars.stream()
                                    .filter(java.util.Objects::nonNull)
                                    .filter(cc -> cc.contains("something"))
                                    .count();

    System.out.printf("Found %d somethings", somethings);
}

outputs

Found 3 somethings

while switching the filter lines will result in a NullPointerException.

Upvotes: 1

pafau k.
pafau k.

Reputation: 1687

null is a valid element of an array, so you have to be prepared to handle these. For example:

int counter = stream.filter(c -> c != null && c.contains("something")).count();

Upvotes: 2

Related Questions