<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
.MsoChpDefault
{mso-style-type:export-only;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:70.85pt 70.85pt 70.85pt 70.85pt;}
div.WordSection1
{page:WordSection1;}
--></style></head><body lang=NO-BOK style='word-wrap:break-word'><div class=WordSection1><p class=MsoNormal>Hi,</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I did some testing where one gatherer (doNothingReturnTrue) does not handle the downStream.push(element) returning false correctly. </p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>The stream processing is terminated in one case and not in the two other.</p><p class=MsoNormal>Especially see the difference between output from handling «efgh» and «EFGH» below.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Is this an error, or is it as expected (Since the doNothingReturnTrue is incorrectly implemented) ?</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Hilsen<o:p></o:p></p><p class=MsoNormal>Svein Otto Solem<o:p></o:p></p><p class=MsoNormal>Retired programmer<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Trace:<o:p></o:p></p><p class=MsoNormal>splitText('1234')<o:p></o:p></p><p class=MsoNormal>GatherDoNothingReturnTrue('1')<o:p></o:p></p><p class=MsoNormal>GatherDoNothingReturnTrue('2')<o:p></o:p></p><p class=MsoNormal>GatherDoNothingReturnTrue('3')<o:p></o:p></p><p class=MsoNormal>GatherDoNothingReturnTrue('4')<o:p></o:p></p><p class=MsoNormal>Optional[1]<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>splitText('efgh')<o:p></o:p></p><p class=MsoNormal>GatherDoNothingReturnTrue('e')<o:p></o:p></p><p class=MsoNormal>PeekDoNothing('e')<o:p></o:p></p><p class=MsoNormal>GatherDoNothingReturnTrue('f')<o:p></o:p></p><p class=MsoNormal>GatherDoNothingReturnTrue('g')<o:p></o:p></p><p class=MsoNormal>GatherDoNothingReturnTrue('h')<o:p></o:p></p><p class=MsoNormal>Optional[e]<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>splitText('EFGH')<o:p></o:p></p><p class=MsoNormal>GatherDoNothingReturnTrue('E')<o:p></o:p></p><p class=MsoNormal>GatherDoNothing('E')<o:p></o:p></p><p class=MsoNormal>Optional[E]<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Code:<o:p></o:p></p><p class=MsoNormal>package org.example;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>import java.util.Iterator;<o:p></o:p></p><p class=MsoNormal>import java.util.Optional;<o:p></o:p></p><p class=MsoNormal>import java.util.function.Consumer;<o:p></o:p></p><p class=MsoNormal>import java.util.function.Function;<o:p></o:p></p><p class=MsoNormal>import java.util.function.Predicate;<o:p></o:p></p><p class=MsoNormal>import java.util.stream.Gatherer;<o:p></o:p></p><p class=MsoNormal>import java.util.stream.Stream;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>import static java.lang.StringTemplate.STR;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>public class GatherTestWhereDownStreamPushResultIsNotRespected {<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal> public static void main(String[] args) {<o:p></o:p></p><p class=MsoNormal> Optional<String> f1 = Stream.of("1234")<o:p></o:p></p><p class=MsoNormal> .gather(logElement("splitText", splitText()))<o:p></o:p></p><p class=MsoNormal> .gather(logElement("GatherDoNothingReturnTrue", doNothingReturnTrue()))<o:p></o:p></p><p class=MsoNormal> .findFirst();<o:p></o:p></p><p class=MsoNormal> System.out.println(f1 +"\n");<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal> Optional<String> f2 = Stream.of("efgh")<o:p></o:p></p><p class=MsoNormal> .gather(logElement("splitText", splitText()))<o:p></o:p></p><p class=MsoNormal> .gather(logElement("GatherDoNothingReturnTrue", doNothingReturnTrue()))<o:p></o:p></p><p class=MsoNormal> .peek(logElement("PeekDoNothing", s -> {}))<o:p></o:p></p><p class=MsoNormal> .findFirst();<o:p></o:p></p><p class=MsoNormal> System.out.println(f2+"\n");<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal> Optional<String> f3 = Stream.of("EFGH")<o:p></o:p></p><p class=MsoNormal> .gather(logElement("splitText", splitText()))<o:p></o:p></p><p class=MsoNormal> .gather(logElement("GatherDoNothingReturnTrue", doNothingReturnTrue()))<o:p></o:p></p><p class=MsoNormal> .gather(logElement("GatherDoNothing", doNothing()))<o:p></o:p></p><p class=MsoNormal> .findFirst();<o:p></o:p></p><p class=MsoNormal> System.out.println(f3+"\n");<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal> public static <T> Gatherer<T, ?, T> doNothing() {<o:p></o:p></p><p class=MsoNormal> // This is correct impl of doNothing<o:p></o:p></p><p class=MsoNormal> return Gatherer.of((_, element, downstream) -> downstream.push(element));<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal> public static <T> Gatherer<T, ?, T> doNothingReturnTrue() {<o:p></o:p></p><p class=MsoNormal> // This is erronous since it does not respect the downstream.push's return value<o:p></o:p></p><p class=MsoNormal> return Gatherer.of((_, element, downstream) -> { downstream.push(element); return true; });<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal> public static Gatherer<String, ?, String> splitText() {<o:p></o:p></p><p class=MsoNormal> Gatherer.Integrator<Void, String, String> integrator = (_, s, downstream) -> {<o:p></o:p></p><p class=MsoNormal> Iterator<String> iterator = s.chars().mapToObj(Character::toString).iterator();<o:p></o:p></p><p class=MsoNormal> while (iterator.hasNext()) {<o:p></o:p></p><p class=MsoNormal> String next = iterator.next();<o:p></o:p></p><p class=MsoNormal> if (!downstream.push(next)) {<o:p></o:p></p><p class=MsoNormal> return false;<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal> return true;<o:p></o:p></p><p class=MsoNormal> };<o:p></o:p></p><p class=MsoNormal> return Gatherer.of(integrator);<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal> private static void println(String name, Object s) {<o:p></o:p></p><p class=MsoNormal> System.out.println(STR. "\{ name }('\{ s }')" );<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal> private static <T> Consumer<T> logElement(String name, Consumer<? super T> c) {<o:p></o:p></p><p class=MsoNormal> return x -> {<o:p></o:p></p><p class=MsoNormal> println(name, x);<o:p></o:p></p><p class=MsoNormal> c.accept(x);<o:p></o:p></p><p class=MsoNormal> };<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal> private static <T, A, R> Gatherer<T, A, R> logElement(String name, Gatherer<T, A, R> gatherer) {<o:p></o:p></p><p class=MsoNormal> return new Gatherer<T, A, R>() {<o:p></o:p></p><p class=MsoNormal> // Still only logs in integrator<o:p></o:p></p><p class=MsoNormal> @Override<o:p></o:p></p><p class=MsoNormal> public Integrator<A, T, R> integrator() {<o:p></o:p></p><p class=MsoNormal> return (state, elem, downstream) -> {<o:p></o:p></p><p class=MsoNormal> println(name, elem);<o:p></o:p></p><p class=MsoNormal> return gatherer.integrator().integrate(state, elem, downstream);<o:p></o:p></p><p class=MsoNormal> };<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal> };<o:p></o:p></p><p class=MsoNormal> }<o:p></o:p></p><p class=MsoNormal>}<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p></div></body></html>