Is it a bad practice to append operations to a Stream in different methods?












3















Suppose I have a method used by multiple classes in my application. This method takes a Stream as a parameter and applies a terminal operation forEach in order to write the data to a file, something like the following:



public File writeStreamToTempFile(Stream stream) {
stream.forEach(item -> {
//some code to write item to a file
}
}


There are multiple callers of this method, and in some of those methods I need to transform the data, let's say using map function, like the following:



public void exportAnimalsData() {
Stream<Animal> animalStream = //fetch data from a DB
animals.filter(a -> a.type.equals("dog"))
.map(a -> //Do something useful to transform the Dogs);

writeStreamToTempFile(animalStream);
}


Not all the callers of the writeStreamToTempFile method need to perform additional operations on the stream.



So my question is:



Is it a bad practice to apply operations to a stream in different methods?



I read somewhere that Stream should never be the return type of a method (the caller does not know if that method already consumes the stream or not), does it also apply for parameters of a method?



Should I just apply all the operations needed in the same method or is it ok to append intermediate operations to the same stream in a different method?










share|improve this question




















  • 3





    Stream should never be the return type of a method sounds like a bad policy, one frequently violated by the JDK. It should be obvious that a method returning a stream wouldn't have consumed it.

    – shmosel
    Nov 21 '18 at 21:05








  • 1





    Look for “Methods … that return Stream” in docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/…

    – Holger
    Nov 22 '18 at 9:38
















3















Suppose I have a method used by multiple classes in my application. This method takes a Stream as a parameter and applies a terminal operation forEach in order to write the data to a file, something like the following:



public File writeStreamToTempFile(Stream stream) {
stream.forEach(item -> {
//some code to write item to a file
}
}


There are multiple callers of this method, and in some of those methods I need to transform the data, let's say using map function, like the following:



public void exportAnimalsData() {
Stream<Animal> animalStream = //fetch data from a DB
animals.filter(a -> a.type.equals("dog"))
.map(a -> //Do something useful to transform the Dogs);

writeStreamToTempFile(animalStream);
}


Not all the callers of the writeStreamToTempFile method need to perform additional operations on the stream.



So my question is:



Is it a bad practice to apply operations to a stream in different methods?



I read somewhere that Stream should never be the return type of a method (the caller does not know if that method already consumes the stream or not), does it also apply for parameters of a method?



Should I just apply all the operations needed in the same method or is it ok to append intermediate operations to the same stream in a different method?










share|improve this question




















  • 3





    Stream should never be the return type of a method sounds like a bad policy, one frequently violated by the JDK. It should be obvious that a method returning a stream wouldn't have consumed it.

    – shmosel
    Nov 21 '18 at 21:05








  • 1





    Look for “Methods … that return Stream” in docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/…

    – Holger
    Nov 22 '18 at 9:38














3












3








3


1






Suppose I have a method used by multiple classes in my application. This method takes a Stream as a parameter and applies a terminal operation forEach in order to write the data to a file, something like the following:



public File writeStreamToTempFile(Stream stream) {
stream.forEach(item -> {
//some code to write item to a file
}
}


There are multiple callers of this method, and in some of those methods I need to transform the data, let's say using map function, like the following:



public void exportAnimalsData() {
Stream<Animal> animalStream = //fetch data from a DB
animals.filter(a -> a.type.equals("dog"))
.map(a -> //Do something useful to transform the Dogs);

writeStreamToTempFile(animalStream);
}


Not all the callers of the writeStreamToTempFile method need to perform additional operations on the stream.



So my question is:



Is it a bad practice to apply operations to a stream in different methods?



I read somewhere that Stream should never be the return type of a method (the caller does not know if that method already consumes the stream or not), does it also apply for parameters of a method?



Should I just apply all the operations needed in the same method or is it ok to append intermediate operations to the same stream in a different method?










share|improve this question
















Suppose I have a method used by multiple classes in my application. This method takes a Stream as a parameter and applies a terminal operation forEach in order to write the data to a file, something like the following:



public File writeStreamToTempFile(Stream stream) {
stream.forEach(item -> {
//some code to write item to a file
}
}


There are multiple callers of this method, and in some of those methods I need to transform the data, let's say using map function, like the following:



public void exportAnimalsData() {
Stream<Animal> animalStream = //fetch data from a DB
animals.filter(a -> a.type.equals("dog"))
.map(a -> //Do something useful to transform the Dogs);

writeStreamToTempFile(animalStream);
}


Not all the callers of the writeStreamToTempFile method need to perform additional operations on the stream.



So my question is:



Is it a bad practice to apply operations to a stream in different methods?



I read somewhere that Stream should never be the return type of a method (the caller does not know if that method already consumes the stream or not), does it also apply for parameters of a method?



Should I just apply all the operations needed in the same method or is it ok to append intermediate operations to the same stream in a different method?







java java-8 java-stream






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 22:32









john

1,50451927




1,50451927










asked Nov 21 '18 at 20:18









Luis MiguelLuis Miguel

91110




91110








  • 3





    Stream should never be the return type of a method sounds like a bad policy, one frequently violated by the JDK. It should be obvious that a method returning a stream wouldn't have consumed it.

    – shmosel
    Nov 21 '18 at 21:05








  • 1





    Look for “Methods … that return Stream” in docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/…

    – Holger
    Nov 22 '18 at 9:38














  • 3





    Stream should never be the return type of a method sounds like a bad policy, one frequently violated by the JDK. It should be obvious that a method returning a stream wouldn't have consumed it.

    – shmosel
    Nov 21 '18 at 21:05








  • 1





    Look for “Methods … that return Stream” in docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/…

    – Holger
    Nov 22 '18 at 9:38








3




3





Stream should never be the return type of a method sounds like a bad policy, one frequently violated by the JDK. It should be obvious that a method returning a stream wouldn't have consumed it.

– shmosel
Nov 21 '18 at 21:05







Stream should never be the return type of a method sounds like a bad policy, one frequently violated by the JDK. It should be obvious that a method returning a stream wouldn't have consumed it.

– shmosel
Nov 21 '18 at 21:05






1




1





Look for “Methods … that return Stream” in docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/…

– Holger
Nov 22 '18 at 9:38





Look for “Methods … that return Stream” in docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/…

– Holger
Nov 22 '18 at 9:38












2 Answers
2






active

oldest

votes


















8















i read somewhere that Stream should never be the return type of a method




Not sure where you read that a Stream should never be the return type of a method. (Can you update your question with a link?).



On the contrary, Brian Goetz, one of the designers of the Stream API, clearly thinks otherwise:



https://stackoverflow.com/a/24679745/340088




(the caller does not know if that method already consume the stream or not)




If the caller is getting a Stream it is implicitly understood that the stream is usable. If you return a consumed Stream it is like returning a closed Socket or a closed InputStream. While possible syntactically, it is just bad coding. Doesn't mean you shouldn't return a Socket or an InputStream from a method just because some bad coder occasionally returns one in a bad state.



On the contrary, monadic style objects are intended to be returned. Stream, Optional, CompletableFuture, and all the functional interfaces (Function, Consumer, Operator, etc.) are intended to be returned so that more functional-style operations can be attached to them, without actually performing the function on the spot.



The example you posted, to me, is perfectly reasonable. You are sort of decorating your Stream with additional operations to the pipeline. You can have logic which decides which operations are added to the pipeline, and there is no reason why not to encapsulate them properly in small methods.



Furthermore, if the stream is very large carrying hundreds of thousands of elements, if you returned a collection, you would just be creating a huge collection in memory, incurring the cost to add them all, only to then stream them again to write them to the file. Doesn't make much sense does it?






share|improve this answer


























  • Trying to find the video where i heard that it is not recommended to return a Stream from a method, will update the question once i find it. BTW great answer, thanks.

    – Luis Miguel
    Nov 21 '18 at 21:12








  • 3





    Would be interested to see it. But its probably wrong (or contextually different). Rest assured its perfectly fine to return Stream (or any other functional type for that matter). Just do your code readable and sensibly organised.

    – jbx
    Nov 21 '18 at 21:18



















0















should i just apply all the operations needed in the same method or is
it ok to append intermediate operations to the same stream in
different method?




Technically it is not necessarily the same stream/object. For example invoking an operation such as map() on the stream will create another stream.



In fact I think that while you didn't consume the stream with a terminal operation I don't see why it would be an issue to work on it to create or get the expected stream and then to pass to the method that expects a Stream.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53419885%2fis-it-a-bad-practice-to-append-operations-to-a-stream-in-different-methods%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    8















    i read somewhere that Stream should never be the return type of a method




    Not sure where you read that a Stream should never be the return type of a method. (Can you update your question with a link?).



    On the contrary, Brian Goetz, one of the designers of the Stream API, clearly thinks otherwise:



    https://stackoverflow.com/a/24679745/340088




    (the caller does not know if that method already consume the stream or not)




    If the caller is getting a Stream it is implicitly understood that the stream is usable. If you return a consumed Stream it is like returning a closed Socket or a closed InputStream. While possible syntactically, it is just bad coding. Doesn't mean you shouldn't return a Socket or an InputStream from a method just because some bad coder occasionally returns one in a bad state.



    On the contrary, monadic style objects are intended to be returned. Stream, Optional, CompletableFuture, and all the functional interfaces (Function, Consumer, Operator, etc.) are intended to be returned so that more functional-style operations can be attached to them, without actually performing the function on the spot.



    The example you posted, to me, is perfectly reasonable. You are sort of decorating your Stream with additional operations to the pipeline. You can have logic which decides which operations are added to the pipeline, and there is no reason why not to encapsulate them properly in small methods.



    Furthermore, if the stream is very large carrying hundreds of thousands of elements, if you returned a collection, you would just be creating a huge collection in memory, incurring the cost to add them all, only to then stream them again to write them to the file. Doesn't make much sense does it?






    share|improve this answer


























    • Trying to find the video where i heard that it is not recommended to return a Stream from a method, will update the question once i find it. BTW great answer, thanks.

      – Luis Miguel
      Nov 21 '18 at 21:12








    • 3





      Would be interested to see it. But its probably wrong (or contextually different). Rest assured its perfectly fine to return Stream (or any other functional type for that matter). Just do your code readable and sensibly organised.

      – jbx
      Nov 21 '18 at 21:18
















    8















    i read somewhere that Stream should never be the return type of a method




    Not sure where you read that a Stream should never be the return type of a method. (Can you update your question with a link?).



    On the contrary, Brian Goetz, one of the designers of the Stream API, clearly thinks otherwise:



    https://stackoverflow.com/a/24679745/340088




    (the caller does not know if that method already consume the stream or not)




    If the caller is getting a Stream it is implicitly understood that the stream is usable. If you return a consumed Stream it is like returning a closed Socket or a closed InputStream. While possible syntactically, it is just bad coding. Doesn't mean you shouldn't return a Socket or an InputStream from a method just because some bad coder occasionally returns one in a bad state.



    On the contrary, monadic style objects are intended to be returned. Stream, Optional, CompletableFuture, and all the functional interfaces (Function, Consumer, Operator, etc.) are intended to be returned so that more functional-style operations can be attached to them, without actually performing the function on the spot.



    The example you posted, to me, is perfectly reasonable. You are sort of decorating your Stream with additional operations to the pipeline. You can have logic which decides which operations are added to the pipeline, and there is no reason why not to encapsulate them properly in small methods.



    Furthermore, if the stream is very large carrying hundreds of thousands of elements, if you returned a collection, you would just be creating a huge collection in memory, incurring the cost to add them all, only to then stream them again to write them to the file. Doesn't make much sense does it?






    share|improve this answer


























    • Trying to find the video where i heard that it is not recommended to return a Stream from a method, will update the question once i find it. BTW great answer, thanks.

      – Luis Miguel
      Nov 21 '18 at 21:12








    • 3





      Would be interested to see it. But its probably wrong (or contextually different). Rest assured its perfectly fine to return Stream (or any other functional type for that matter). Just do your code readable and sensibly organised.

      – jbx
      Nov 21 '18 at 21:18














    8












    8








    8








    i read somewhere that Stream should never be the return type of a method




    Not sure where you read that a Stream should never be the return type of a method. (Can you update your question with a link?).



    On the contrary, Brian Goetz, one of the designers of the Stream API, clearly thinks otherwise:



    https://stackoverflow.com/a/24679745/340088




    (the caller does not know if that method already consume the stream or not)




    If the caller is getting a Stream it is implicitly understood that the stream is usable. If you return a consumed Stream it is like returning a closed Socket or a closed InputStream. While possible syntactically, it is just bad coding. Doesn't mean you shouldn't return a Socket or an InputStream from a method just because some bad coder occasionally returns one in a bad state.



    On the contrary, monadic style objects are intended to be returned. Stream, Optional, CompletableFuture, and all the functional interfaces (Function, Consumer, Operator, etc.) are intended to be returned so that more functional-style operations can be attached to them, without actually performing the function on the spot.



    The example you posted, to me, is perfectly reasonable. You are sort of decorating your Stream with additional operations to the pipeline. You can have logic which decides which operations are added to the pipeline, and there is no reason why not to encapsulate them properly in small methods.



    Furthermore, if the stream is very large carrying hundreds of thousands of elements, if you returned a collection, you would just be creating a huge collection in memory, incurring the cost to add them all, only to then stream them again to write them to the file. Doesn't make much sense does it?






    share|improve this answer
















    i read somewhere that Stream should never be the return type of a method




    Not sure where you read that a Stream should never be the return type of a method. (Can you update your question with a link?).



    On the contrary, Brian Goetz, one of the designers of the Stream API, clearly thinks otherwise:



    https://stackoverflow.com/a/24679745/340088




    (the caller does not know if that method already consume the stream or not)




    If the caller is getting a Stream it is implicitly understood that the stream is usable. If you return a consumed Stream it is like returning a closed Socket or a closed InputStream. While possible syntactically, it is just bad coding. Doesn't mean you shouldn't return a Socket or an InputStream from a method just because some bad coder occasionally returns one in a bad state.



    On the contrary, monadic style objects are intended to be returned. Stream, Optional, CompletableFuture, and all the functional interfaces (Function, Consumer, Operator, etc.) are intended to be returned so that more functional-style operations can be attached to them, without actually performing the function on the spot.



    The example you posted, to me, is perfectly reasonable. You are sort of decorating your Stream with additional operations to the pipeline. You can have logic which decides which operations are added to the pipeline, and there is no reason why not to encapsulate them properly in small methods.



    Furthermore, if the stream is very large carrying hundreds of thousands of elements, if you returned a collection, you would just be creating a huge collection in memory, incurring the cost to add them all, only to then stream them again to write them to the file. Doesn't make much sense does it?







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 21 '18 at 21:08

























    answered Nov 21 '18 at 20:30









    jbxjbx

    11.4k1060111




    11.4k1060111













    • Trying to find the video where i heard that it is not recommended to return a Stream from a method, will update the question once i find it. BTW great answer, thanks.

      – Luis Miguel
      Nov 21 '18 at 21:12








    • 3





      Would be interested to see it. But its probably wrong (or contextually different). Rest assured its perfectly fine to return Stream (or any other functional type for that matter). Just do your code readable and sensibly organised.

      – jbx
      Nov 21 '18 at 21:18



















    • Trying to find the video where i heard that it is not recommended to return a Stream from a method, will update the question once i find it. BTW great answer, thanks.

      – Luis Miguel
      Nov 21 '18 at 21:12








    • 3





      Would be interested to see it. But its probably wrong (or contextually different). Rest assured its perfectly fine to return Stream (or any other functional type for that matter). Just do your code readable and sensibly organised.

      – jbx
      Nov 21 '18 at 21:18

















    Trying to find the video where i heard that it is not recommended to return a Stream from a method, will update the question once i find it. BTW great answer, thanks.

    – Luis Miguel
    Nov 21 '18 at 21:12







    Trying to find the video where i heard that it is not recommended to return a Stream from a method, will update the question once i find it. BTW great answer, thanks.

    – Luis Miguel
    Nov 21 '18 at 21:12






    3




    3





    Would be interested to see it. But its probably wrong (or contextually different). Rest assured its perfectly fine to return Stream (or any other functional type for that matter). Just do your code readable and sensibly organised.

    – jbx
    Nov 21 '18 at 21:18





    Would be interested to see it. But its probably wrong (or contextually different). Rest assured its perfectly fine to return Stream (or any other functional type for that matter). Just do your code readable and sensibly organised.

    – jbx
    Nov 21 '18 at 21:18













    0















    should i just apply all the operations needed in the same method or is
    it ok to append intermediate operations to the same stream in
    different method?




    Technically it is not necessarily the same stream/object. For example invoking an operation such as map() on the stream will create another stream.



    In fact I think that while you didn't consume the stream with a terminal operation I don't see why it would be an issue to work on it to create or get the expected stream and then to pass to the method that expects a Stream.






    share|improve this answer




























      0















      should i just apply all the operations needed in the same method or is
      it ok to append intermediate operations to the same stream in
      different method?




      Technically it is not necessarily the same stream/object. For example invoking an operation such as map() on the stream will create another stream.



      In fact I think that while you didn't consume the stream with a terminal operation I don't see why it would be an issue to work on it to create or get the expected stream and then to pass to the method that expects a Stream.






      share|improve this answer


























        0












        0








        0








        should i just apply all the operations needed in the same method or is
        it ok to append intermediate operations to the same stream in
        different method?




        Technically it is not necessarily the same stream/object. For example invoking an operation such as map() on the stream will create another stream.



        In fact I think that while you didn't consume the stream with a terminal operation I don't see why it would be an issue to work on it to create or get the expected stream and then to pass to the method that expects a Stream.






        share|improve this answer














        should i just apply all the operations needed in the same method or is
        it ok to append intermediate operations to the same stream in
        different method?




        Technically it is not necessarily the same stream/object. For example invoking an operation such as map() on the stream will create another stream.



        In fact I think that while you didn't consume the stream with a terminal operation I don't see why it would be an issue to work on it to create or get the expected stream and then to pass to the method that expects a Stream.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 21 '18 at 20:28









        davidxxxdavidxxx

        66.5k66995




        66.5k66995






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53419885%2fis-it-a-bad-practice-to-append-operations-to-a-stream-in-different-methods%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            How to fix TextFormField cause rebuild widget in Flutter

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith