Сравните String с каждым элементом массива String, используя Streams - PullRequest
0 голосов
/ 28 мая 2020

Привет, я хочу подсчитать, сколько раз String обнаруживается в массиве строк с использованием потоков

До сих пор я думал следующее:

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

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

return counter;

Проблема что я получаю, это то, что большую часть времени я получаю ошибку NullPointerException, и я думаю, что это из-за .count(), если он не получает ничего особенного внутри filter(c-> c.contains("something")). И я пришел к такому выводу, потому что, если я запустил его без .count(), как этот stream.filter(c-> c.contains("something"));, ничего не возвращая, он не выдаст Exception. Я не уверен в этом, но я так думаю.

Есть идеи, как я могу подсчитать, сколько раз появляется строка и массив строк с помощью потоков?

Ответы [ 3 ]

2 голосов
/ 28 мая 2020

Проблема, которую я получаю, заключается в том, что большую часть времени я получаю ошибку NullPointerException, и я думаю, что это из-за .count () И я пришел к такому выводу, если я запустил его с out .count () это не вызовет исключения.

Причина, по которой вы не можете реплицировать NullPointerException без вызова count, состоит в том, что потоки лениво оцениваются , т.е. весь конвейер не выполняется до тех пор, пока не будет выполнена активная операция (операция который запускает обработку конвейера).

Мы можем прийти к выводу, что Arrays.stream(array) не является виновником NullPointerException, потому что он взорвался бы независимо от того, вызвали ли вы активную операцию в потоке или нет в качестве параметра для Arrays.stream должно быть nonNull , иначе он вылетит из-за вышеупомянутой ошибки.

Таким образом, мы можем прийти к выводу, что элементы внутри массива являются виновниками для эта ошибка в коде, который вы проиллюстрировали, но затем вы должны спросить себя, разрешены ли в первую очередь нулевые элементы, и если да, то отфильтруйте их перед выполнением c.contains("something"), а если нет, то вам следует отладить, в какой момент в вашем приложении были нули добавляются в массив, когда их не должно быть. Найдите ошибку, а не подавите ее.

если нули разрешены в первую очередь , решение простое, т.е. отфильтровать нули перед вызовом .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();
2 голосов
/ 28 мая 2020

null - допустимый элемент массива, поэтому вы должны быть готовы с ними справиться. Например:

int counter = stream.filter(c -> c != null && c.contains("something")).count();
1 голос
/ 28 мая 2020

Сначала необходимо отфильтровать значения null. Сделайте это любым способом @pafauk. ответил или отфильтровав отдельно. Для этого необходимо применить фильтр null перед тот, который вы уже используете:

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);
}

выводит

Found 3 somethings

при переключении строк фильтра приведет к а NullPointerException.

...