0

I want add Bufferedreader to List with stream API. I have a problem that all Bufferedreader save to list[0]. Why .map(n->n.split(" +")) doesn't work?

BufferedReader  bufferedReader= new BufferedReader(new InputStreamReader(System.in,"UTF-8"));

    List<String> list = bufferedReader.lines().collect(Collectors.toList());
    list.stream()
            .map(n-> n.toLowerCase())
            .map(n->n.replaceAll("[^a-z0-9]"," "))
            .map(n->n.split(" +"));
    String [] a = list.stream().toArray(String[]::new);
    System.out.println(list.size());

}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 1
    stream() operations do not modify the underlying collection. You need to `collect` again to a new variable. Note: your last `map()` returns `Stream` not `Stream` (so it could never be reassigned to `list`). – charles-allen Aug 03 '19 at 23:45
  • 1
    Please update your question to give an example of what you want (example input & output). It makes it easier to help you :) – charles-allen Aug 03 '19 at 23:48

1 Answers1

3

Stream operations do not mutate your underlying List. You need to collect the result after map.

Since a Stream can only be processed once, you might as well do the entire transformation chain at once (without intermediate variables). I'm guessing that you want a single array (or list) containing all the "words" (so I used flatMap to merge to a single List<String>):

    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
    Pattern pattern = Pattern.compile(" +");

    List<String> allWords = bufferedReader.lines()
            .map(String::toLowerCase)
            .map(line -> line.replaceAll("[^a-z0-9]", " "))
            .flatMap(pattern::splitAsStream)
            .collect(Collectors.toList());

If you want "word" count, replace collect(...) with count().

You can also merge replaceAll() and split() into 1 action, skipping toLowerCase():

    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
    Pattern pattern = Pattern.compile("[^A-Za-z0-9]+");

    List<String> allWords = bufferedReader.lines()
            .flatMap(pattern::splitAsStream)
            .map(String::toLowerCase) // if still needed
            .collect(Collectors.toList());

Edits:
190805: Simplified flatMap as suggested by @greg-449
190806: Merged replace & split as suggested by @Holger

charles-allen
  • 3,891
  • 2
  • 23
  • 35
  • 1
    Using `Pattern.splitAsStream` instead of `String.split` and `Arrays.stream` would be better – greg-449 Aug 04 '19 at 08:53
  • 1
    Of course, since the only purpose of replacing `[^a-z0-9]` with `" "`, is to split at the spaces afterwards, the replacement is obsolete, as you can use `[^a-z0-9]+` as splitting pattern directly. And I'd use `[^A-Za-z0-9]+` as splitting pattern first and do `toLowerCase` afterwards (if actually needed), to avoid obsolete operations. `List allWords = bufferedReader.lines() .flatMap(Pattern.compile("[^A-Za-z0-9]+")::splitAsStream) .map(String::toLowerCase) .collect(Collectors.toList());` – Holger Aug 05 '19 at 14:20
  • @Holger - Understood! I'll add it below (to introduce the concepts step-by-step). Does your code create the Pattern once? Or once per line? (that was my motivation to separate the constructor call). – charles-allen Aug 05 '19 at 18:08
  • 1
    @AjahnCharles it will create it once for the entire Stream operation; that’s the way, `expression::name` works, evaluate `expression` immediately, check for `null`, then capture the result for the function instance. See [What is the equivalent lambda expression for System.out::println](https://stackoverflow.com/q/28023364/2711488). Or related problems, [NullPointerException is thrown using a method-reference but not a lambda expression](https://stackoverflow.com/q/37413106/2711488) and [Why does invokeLater execute in the main thread?](https://stackoverflow.com/q/44543465/2711488). – Holger Aug 06 '19 at 07:17
  • @Holger - Thanks for the explanation. I will definitely make use of that! – charles-allen Aug 06 '19 at 07:53