0
public class Histogram {
    public static void main(String[] args) throws IOException {
        Stream<String> stream = Files.lines(Paths.get("words.txt"));
        ArrayList<String> list = (ArrayList<String>) stream
                .map(w -> w.split("\\.|\\s+|,")).flatMap(Arrays::stream)
                .filter(x-> x.length() != 0)
                .collect(Collectors.toList());
        list.forEach(s -> System.out.print(s + "(" + s.length() + ") "));
    }  
}

Now I have all results in one line. How I can make logic in this Java stream 8, to put every 5 words from forEach loop to newline (System.out.println). Every sixth word is printed in a new line.

João Dias
  • 16,277
  • 6
  • 33
  • 45
  • Use a regular for loop (`list.forEach` or `for-each` in general) hides the iterator; so you can't tell when you're at the sixth word. – Elliott Frisch Nov 17 '21 at 21:21
  • Does this answer your question? [Take every nth element from a Java 8 stream](https://stackoverflow.com/questions/31602425/take-every-nth-element-from-a-java-8-stream) – Sam Nov 17 '21 at 21:28
  • 1
    Don’t cast the result of `collect(Collectors.toList())` to `ArrayList`. The documentation doesn’t specify what list you can expect and there is no reason not to use just `List list = …`. By the way, instead of `x.length() != 0` you can write `! x.isEmpty()` – Holger Nov 18 '21 at 09:50

2 Answers2

1

Split the list into chunks of 5 and join the items inside each chunk.

IntStream.iterate(0, i -> i < list.size(), i -> i + 5)
    .forEach(i -> System.out.println(
        IntStream.range(i, Math.min(i + 5, list.size()))
            .mapToObj(list::get)
            .map(s -> s + "(" + s.length() + ")")
            .collect(Collectors.joining("; "))
    ));

Note: Stream.iterate with condition is available in Java 9. Pure Java 8 solution could use Stream.limit with a calculated number of chunks:

IntStream.iterate(0, i -> i + 5)
    .limit(list.size() / 5 + (list.size() % 5 > 0 ? 1 : 0))
    .forEach(i -> System.out.println(
        IntStream.range(i, Math.min(i + 5, list.size()))
            .mapToObj(list::get)
            .map(s -> s + "(" + s.length() + ")")
            .collect(Collectors.joining("; "))
    ));
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
0

You can use stream:

private static final String NEW_LINE = System.lineSeparator();

public static String addNewLines(String str, int n) {
    
    String[] words = str.split(" ");
    
    int size = words.length;
    
    int lines = (int) Math.round((double) size / n);
    
    int lastLine = size - lines * n;
    
    return IntStream.range(0, lines)
            .mapToObj(i -> toString(words, i * n, i * n + n))
            .collect(Collectors.joining(NEW_LINE, "", lastLine > 0 
                            ? NEW_LINE + toString(words, size - lastLine, size)
                            : ""));
}

private static String toString(String[] words, int start, int end) {
    return Arrays.stream(words, start, end).collect(Collectors.joining(" "));
}

Then:

String str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam egestas maximus augue, in vehicula erat dictum quis. Sed rhoncus tempor maximus. Etiam tempus tristique ex et imperdiet.";

System.out.println(addNewLines(str, 5));

Output:

Lorem ipsum dolor sit amet,
consectetur adipiscing elit. Nam egestas
maximus augue, in vehicula erat
dictum quis. Sed rhoncus tempor
maximus. Etiam tempus tristique ex
et imperdiet.
Oboe
  • 2,643
  • 2
  • 9
  • 17