How do I get the first element while continue streaming?












19















I have a stream of generic items. I'd like to print the class name of the first item + the toString() of all the items.



If I had an Iterable, it would look like this:



Iterable<E> itemIter = ...;
boolean first = true;
for (E e : itemIter) {
if (first) {
first = false;
System.out.println(e.getClass().getSimpleName());
}
System.out.println(e);
}


Can I do this on a stream (Stream<T>) with the stream API?



* Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.










share|improve this question

























  • Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.

    – AlikElzin-kilaka
    Mar 6 at 16:38











  • @AndrewTobilko - I don't have an Iterable - just Stream.

    – AlikElzin-kilaka
    Mar 6 at 19:29











  • Note that, if you have a stream, you can get an iterator (and, if you need one, also an iterable).

    – Ilmari Karonen
    Mar 7 at 8:47
















19















I have a stream of generic items. I'd like to print the class name of the first item + the toString() of all the items.



If I had an Iterable, it would look like this:



Iterable<E> itemIter = ...;
boolean first = true;
for (E e : itemIter) {
if (first) {
first = false;
System.out.println(e.getClass().getSimpleName());
}
System.out.println(e);
}


Can I do this on a stream (Stream<T>) with the stream API?



* Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.










share|improve this question

























  • Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.

    – AlikElzin-kilaka
    Mar 6 at 16:38











  • @AndrewTobilko - I don't have an Iterable - just Stream.

    – AlikElzin-kilaka
    Mar 6 at 19:29











  • Note that, if you have a stream, you can get an iterator (and, if you need one, also an iterable).

    – Ilmari Karonen
    Mar 7 at 8:47














19












19








19


5






I have a stream of generic items. I'd like to print the class name of the first item + the toString() of all the items.



If I had an Iterable, it would look like this:



Iterable<E> itemIter = ...;
boolean first = true;
for (E e : itemIter) {
if (first) {
first = false;
System.out.println(e.getClass().getSimpleName());
}
System.out.println(e);
}


Can I do this on a stream (Stream<T>) with the stream API?



* Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.










share|improve this question
















I have a stream of generic items. I'd like to print the class name of the first item + the toString() of all the items.



If I had an Iterable, it would look like this:



Iterable<E> itemIter = ...;
boolean first = true;
for (E e : itemIter) {
if (first) {
first = false;
System.out.println(e.getClass().getSimpleName());
}
System.out.println(e);
}


Can I do this on a stream (Stream<T>) with the stream API?



* Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.







java java-stream






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 7 at 9:49









Peter Mortensen

13.7k1986113




13.7k1986113










asked Mar 6 at 16:13









AlikElzin-kilakaAlikElzin-kilaka

18.8k15127206




18.8k15127206













  • Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.

    – AlikElzin-kilaka
    Mar 6 at 16:38











  • @AndrewTobilko - I don't have an Iterable - just Stream.

    – AlikElzin-kilaka
    Mar 6 at 19:29











  • Note that, if you have a stream, you can get an iterator (and, if you need one, also an iterable).

    – Ilmari Karonen
    Mar 7 at 8:47



















  • Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.

    – AlikElzin-kilaka
    Mar 6 at 16:38











  • @AndrewTobilko - I don't have an Iterable - just Stream.

    – AlikElzin-kilaka
    Mar 6 at 19:29











  • Note that, if you have a stream, you can get an iterator (and, if you need one, also an iterable).

    – Ilmari Karonen
    Mar 7 at 8:47

















Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.

– AlikElzin-kilaka
Mar 6 at 16:38





Please note that it's a question about streams - not about iterators. I have a stream - not an iterator.

– AlikElzin-kilaka
Mar 6 at 16:38













@AndrewTobilko - I don't have an Iterable - just Stream.

– AlikElzin-kilaka
Mar 6 at 19:29





@AndrewTobilko - I don't have an Iterable - just Stream.

– AlikElzin-kilaka
Mar 6 at 19:29













Note that, if you have a stream, you can get an iterator (and, if you need one, also an iterable).

– Ilmari Karonen
Mar 7 at 8:47





Note that, if you have a stream, you can get an iterator (and, if you need one, also an iterable).

– Ilmari Karonen
Mar 7 at 8:47












7 Answers
7






active

oldest

votes


















12














There is StreamEx library that extends standard Java's Stream API. Using StreamEx.of(Iterator) and peekFirst :



StreamEx.of(itemIter.iterator())
.peekFirst(e -> System.out.println(e.getClass().getSimpleName()))
.forEach(System.out::println);





share|improve this answer


























  • I wonder how they've implemented it, probably like one of the solutions already given here

    – Lino
    Mar 6 at 16:50






  • 1





    note that the method has some limitations (mentioned in the docs) and "exists mainly to support debugging".

    – Andrew Tobilko
    Mar 6 at 16:55











  • @Lino combine this answer which performs an action for the first element (but also consumes it) and this answer which will push the first item back after examining it and you have the necessary tools to construct such an operation.

    – Holger
    Mar 6 at 17:36






  • 1





    By the way, it’s preferable to use StreamEx.of(itemIter.spliterator()), which may carry additional meta information to the stream (depending on the actual Iterable), potentially improving the performance.

    – Holger
    Mar 6 at 17:48



















7














Native solution: Stream in Java is not reusable. This means, that consuming stream can be done only once. If you get the first element from a stream, you can iterate over it one more time.



Workaround would be to create another stream same as the first one or getting the first item and then creating a stream, something like that:



Stream<E> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED), false);
E firstElement = itemIter.next();
stream.foreach(...);


Edit



There is not really any way to "copy" a stream, you need to keep an iterator / collection. More about it here. When it comes to memory once stream is exhausted, it can be collected by garbage collector as there is no use from it. Stream itself does not take more space than iterator it originates from. Bear in mind, that streams can be potentially infinite. Elements currently manipulated are stored in memory.






share|improve this answer





















  • 1





    @AlikElzin-kilaka please don't ask about the memory implications :) To me, it's obvious that none of Stream API solutions will outdo the simple loop approach mentioned by you (I'd go with a fori loop, though) in any way (performance, readability, maintenance). I honestly don't understand why you want streams here.

    – Andrew Tobilko
    Mar 6 at 16:44













  • Why do you assume that it's safe to cast: (List<E>) itemIter?

    – ernest_k
    Mar 6 at 16:46











  • @ernest_k it doesn't really matter, I don't know the context (what itemIter really is). Let's just treat it as a pseudocode, that can be compiled, just to show the idea :)

    – Andronicus
    Mar 6 at 16:48






  • 1





    Well, it doesn’t even compile. Since objects are not an Iterable and an Iterator at the same time, you can’t cast it to List and expect it to also have a next() method. Once you fixed this, you don’t need the questionable type cast: E firstElement = itemIter.iterator().next(); Stream<E> stream = StreamSupport.stream(itemIter.spliterator(), false);

    – Holger
    Mar 6 at 17:44



















5














If your starting point is a Stream and you want to retain all of its properties and the laziness, the following solution will do:



public static <E> Stream<E> forFirst(Stream<E> stream, Consumer<? super E> c) {
boolean parallel = stream.isParallel();
Spliterator<E> sp = stream.spliterator();
return StreamSupport.stream(() -> {
if(sp.getExactSizeIfKnown() == 0) return sp;
Stream.Builder<E> b = Stream.builder();
if(!sp.tryAdvance(b.andThen(c))) return sp;
return Stream.concat(b.build(), StreamSupport.stream(sp, parallel)).spliterator();
}, sp.characteristics(), parallel);
}


E.g. when you use it with



List<String> list = new ArrayList<>(List.of("foo", "bar", "baz"));
Stream<String> stream = forFirst(
list.stream().filter(s -> s.startsWith("b")),
s -> System.out.println(s+" ("+s.getClass().getSimpleName()+')')
).map(String::toUpperCase);
list.add(1, "blah");
System.out.println(stream.collect(Collectors.joining(" | ")));


it will print



blah (String)
BLAH | BAR | BAZ


demonstrating that the processing will not start before commencing the terminal operation (collect), hence reflecting the preceding update to the source List.






share|improve this answer
























  • can't tell why this is not a lot higher :|

    – Eugene
    Mar 7 at 8:31











  • @Eugene because posted two hours after the other answers and being placed at the end in the default ordering… nothing to worry about

    – Holger
    Mar 7 at 10:07



















4














You can abuse reduction:



Stream<E> stream = ...;
System.out.println(stream
.reduce("",(out,e) ->
out + (out.isEmpty() ? e.getClass().getSimpleName()+"n" : "")
+ e));





share|improve this answer

































    0














    One workaround is to do it like this -



    import java.util.*; 
    import java.util.stream.Collectors;
    public class MyClass {
    static int i = 0;
    static int getCounter(){
    return i;
    }
    static void incrementCounter(){
    i++;
    }
    public static void main(String args) {
    List<String> list = Arrays.asList("A", "B", "C", "D", "E", "F", "G");
    List<String> answer = list.stream().filter(str -> {if(getCounter()==0) {System.out.println("First Element : " + str);} incrementCounter(); return true;}).
    collect(Collectors.toList());
    System.out.println(answer);
    }
    }


    Output :



    First Element : A
    [A, B, C, D, E, F, G]





    share|improve this answer



















    • 1





      requires you to always reset the value though, and will not work in a multi thread environment

      – Lino
      Mar 6 at 16:52



















    0














    You could use peek for that:



    AtomicBoolean first = new AtomicBoolean(true);
    StreamSupport.stream(itemIter.spliterator(), false)
    .peek(e -> {
    if(first.get()) {
    System.out.println(e.getClass().getSimpleName());
    first.set(false);
    }
    })
    ...





    share|improve this answer





















    • 1





      In that sense, I guess the code in question would be much better even if the iterable is defined. Keeping in mind there is nothing like itemIter.stream() available up front.

      – Naman
      Mar 6 at 16:36













    • @nullpointer you're right, I've edited my answer to use StreamSupport

      – Lino
      Mar 6 at 16:46











    • The action passed to peek will be executed in the processing order which is not guaranteed to be the Stream’s encounter order.

      – Holger
      Mar 6 at 17:45



















    0














    You can also use an boolean atomic reference:



    AtomicReference<Boolean> first = new AtomicReference<Boolean>(Boolean.TRUE);
    stream.forEach(e ->
    System.out.println("First == " + first.getAndUpdate(b -> false)));





    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%2f55027574%2fhow-do-i-get-the-first-element-while-continue-streaming%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      7 Answers
      7






      active

      oldest

      votes








      7 Answers
      7






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      12














      There is StreamEx library that extends standard Java's Stream API. Using StreamEx.of(Iterator) and peekFirst :



      StreamEx.of(itemIter.iterator())
      .peekFirst(e -> System.out.println(e.getClass().getSimpleName()))
      .forEach(System.out::println);





      share|improve this answer


























      • I wonder how they've implemented it, probably like one of the solutions already given here

        – Lino
        Mar 6 at 16:50






      • 1





        note that the method has some limitations (mentioned in the docs) and "exists mainly to support debugging".

        – Andrew Tobilko
        Mar 6 at 16:55











      • @Lino combine this answer which performs an action for the first element (but also consumes it) and this answer which will push the first item back after examining it and you have the necessary tools to construct such an operation.

        – Holger
        Mar 6 at 17:36






      • 1





        By the way, it’s preferable to use StreamEx.of(itemIter.spliterator()), which may carry additional meta information to the stream (depending on the actual Iterable), potentially improving the performance.

        – Holger
        Mar 6 at 17:48
















      12














      There is StreamEx library that extends standard Java's Stream API. Using StreamEx.of(Iterator) and peekFirst :



      StreamEx.of(itemIter.iterator())
      .peekFirst(e -> System.out.println(e.getClass().getSimpleName()))
      .forEach(System.out::println);





      share|improve this answer


























      • I wonder how they've implemented it, probably like one of the solutions already given here

        – Lino
        Mar 6 at 16:50






      • 1





        note that the method has some limitations (mentioned in the docs) and "exists mainly to support debugging".

        – Andrew Tobilko
        Mar 6 at 16:55











      • @Lino combine this answer which performs an action for the first element (but also consumes it) and this answer which will push the first item back after examining it and you have the necessary tools to construct such an operation.

        – Holger
        Mar 6 at 17:36






      • 1





        By the way, it’s preferable to use StreamEx.of(itemIter.spliterator()), which may carry additional meta information to the stream (depending on the actual Iterable), potentially improving the performance.

        – Holger
        Mar 6 at 17:48














      12












      12








      12







      There is StreamEx library that extends standard Java's Stream API. Using StreamEx.of(Iterator) and peekFirst :



      StreamEx.of(itemIter.iterator())
      .peekFirst(e -> System.out.println(e.getClass().getSimpleName()))
      .forEach(System.out::println);





      share|improve this answer















      There is StreamEx library that extends standard Java's Stream API. Using StreamEx.of(Iterator) and peekFirst :



      StreamEx.of(itemIter.iterator())
      .peekFirst(e -> System.out.println(e.getClass().getSimpleName()))
      .forEach(System.out::println);






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Mar 6 at 16:50









      Andrew Tobilko

      28.2k104488




      28.2k104488










      answered Mar 6 at 16:31









      RuslanRuslan

      3,642827




      3,642827













      • I wonder how they've implemented it, probably like one of the solutions already given here

        – Lino
        Mar 6 at 16:50






      • 1





        note that the method has some limitations (mentioned in the docs) and "exists mainly to support debugging".

        – Andrew Tobilko
        Mar 6 at 16:55











      • @Lino combine this answer which performs an action for the first element (but also consumes it) and this answer which will push the first item back after examining it and you have the necessary tools to construct such an operation.

        – Holger
        Mar 6 at 17:36






      • 1





        By the way, it’s preferable to use StreamEx.of(itemIter.spliterator()), which may carry additional meta information to the stream (depending on the actual Iterable), potentially improving the performance.

        – Holger
        Mar 6 at 17:48



















      • I wonder how they've implemented it, probably like one of the solutions already given here

        – Lino
        Mar 6 at 16:50






      • 1





        note that the method has some limitations (mentioned in the docs) and "exists mainly to support debugging".

        – Andrew Tobilko
        Mar 6 at 16:55











      • @Lino combine this answer which performs an action for the first element (but also consumes it) and this answer which will push the first item back after examining it and you have the necessary tools to construct such an operation.

        – Holger
        Mar 6 at 17:36






      • 1





        By the way, it’s preferable to use StreamEx.of(itemIter.spliterator()), which may carry additional meta information to the stream (depending on the actual Iterable), potentially improving the performance.

        – Holger
        Mar 6 at 17:48

















      I wonder how they've implemented it, probably like one of the solutions already given here

      – Lino
      Mar 6 at 16:50





      I wonder how they've implemented it, probably like one of the solutions already given here

      – Lino
      Mar 6 at 16:50




      1




      1





      note that the method has some limitations (mentioned in the docs) and "exists mainly to support debugging".

      – Andrew Tobilko
      Mar 6 at 16:55





      note that the method has some limitations (mentioned in the docs) and "exists mainly to support debugging".

      – Andrew Tobilko
      Mar 6 at 16:55













      @Lino combine this answer which performs an action for the first element (but also consumes it) and this answer which will push the first item back after examining it and you have the necessary tools to construct such an operation.

      – Holger
      Mar 6 at 17:36





      @Lino combine this answer which performs an action for the first element (but also consumes it) and this answer which will push the first item back after examining it and you have the necessary tools to construct such an operation.

      – Holger
      Mar 6 at 17:36




      1




      1





      By the way, it’s preferable to use StreamEx.of(itemIter.spliterator()), which may carry additional meta information to the stream (depending on the actual Iterable), potentially improving the performance.

      – Holger
      Mar 6 at 17:48





      By the way, it’s preferable to use StreamEx.of(itemIter.spliterator()), which may carry additional meta information to the stream (depending on the actual Iterable), potentially improving the performance.

      – Holger
      Mar 6 at 17:48













      7














      Native solution: Stream in Java is not reusable. This means, that consuming stream can be done only once. If you get the first element from a stream, you can iterate over it one more time.



      Workaround would be to create another stream same as the first one or getting the first item and then creating a stream, something like that:



      Stream<E> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED), false);
      E firstElement = itemIter.next();
      stream.foreach(...);


      Edit



      There is not really any way to "copy" a stream, you need to keep an iterator / collection. More about it here. When it comes to memory once stream is exhausted, it can be collected by garbage collector as there is no use from it. Stream itself does not take more space than iterator it originates from. Bear in mind, that streams can be potentially infinite. Elements currently manipulated are stored in memory.






      share|improve this answer





















      • 1





        @AlikElzin-kilaka please don't ask about the memory implications :) To me, it's obvious that none of Stream API solutions will outdo the simple loop approach mentioned by you (I'd go with a fori loop, though) in any way (performance, readability, maintenance). I honestly don't understand why you want streams here.

        – Andrew Tobilko
        Mar 6 at 16:44













      • Why do you assume that it's safe to cast: (List<E>) itemIter?

        – ernest_k
        Mar 6 at 16:46











      • @ernest_k it doesn't really matter, I don't know the context (what itemIter really is). Let's just treat it as a pseudocode, that can be compiled, just to show the idea :)

        – Andronicus
        Mar 6 at 16:48






      • 1





        Well, it doesn’t even compile. Since objects are not an Iterable and an Iterator at the same time, you can’t cast it to List and expect it to also have a next() method. Once you fixed this, you don’t need the questionable type cast: E firstElement = itemIter.iterator().next(); Stream<E> stream = StreamSupport.stream(itemIter.spliterator(), false);

        – Holger
        Mar 6 at 17:44
















      7














      Native solution: Stream in Java is not reusable. This means, that consuming stream can be done only once. If you get the first element from a stream, you can iterate over it one more time.



      Workaround would be to create another stream same as the first one or getting the first item and then creating a stream, something like that:



      Stream<E> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED), false);
      E firstElement = itemIter.next();
      stream.foreach(...);


      Edit



      There is not really any way to "copy" a stream, you need to keep an iterator / collection. More about it here. When it comes to memory once stream is exhausted, it can be collected by garbage collector as there is no use from it. Stream itself does not take more space than iterator it originates from. Bear in mind, that streams can be potentially infinite. Elements currently manipulated are stored in memory.






      share|improve this answer





















      • 1





        @AlikElzin-kilaka please don't ask about the memory implications :) To me, it's obvious that none of Stream API solutions will outdo the simple loop approach mentioned by you (I'd go with a fori loop, though) in any way (performance, readability, maintenance). I honestly don't understand why you want streams here.

        – Andrew Tobilko
        Mar 6 at 16:44













      • Why do you assume that it's safe to cast: (List<E>) itemIter?

        – ernest_k
        Mar 6 at 16:46











      • @ernest_k it doesn't really matter, I don't know the context (what itemIter really is). Let's just treat it as a pseudocode, that can be compiled, just to show the idea :)

        – Andronicus
        Mar 6 at 16:48






      • 1





        Well, it doesn’t even compile. Since objects are not an Iterable and an Iterator at the same time, you can’t cast it to List and expect it to also have a next() method. Once you fixed this, you don’t need the questionable type cast: E firstElement = itemIter.iterator().next(); Stream<E> stream = StreamSupport.stream(itemIter.spliterator(), false);

        – Holger
        Mar 6 at 17:44














      7












      7








      7







      Native solution: Stream in Java is not reusable. This means, that consuming stream can be done only once. If you get the first element from a stream, you can iterate over it one more time.



      Workaround would be to create another stream same as the first one or getting the first item and then creating a stream, something like that:



      Stream<E> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED), false);
      E firstElement = itemIter.next();
      stream.foreach(...);


      Edit



      There is not really any way to "copy" a stream, you need to keep an iterator / collection. More about it here. When it comes to memory once stream is exhausted, it can be collected by garbage collector as there is no use from it. Stream itself does not take more space than iterator it originates from. Bear in mind, that streams can be potentially infinite. Elements currently manipulated are stored in memory.






      share|improve this answer















      Native solution: Stream in Java is not reusable. This means, that consuming stream can be done only once. If you get the first element from a stream, you can iterate over it one more time.



      Workaround would be to create another stream same as the first one or getting the first item and then creating a stream, something like that:



      Stream<E> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED), false);
      E firstElement = itemIter.next();
      stream.foreach(...);


      Edit



      There is not really any way to "copy" a stream, you need to keep an iterator / collection. More about it here. When it comes to memory once stream is exhausted, it can be collected by garbage collector as there is no use from it. Stream itself does not take more space than iterator it originates from. Bear in mind, that streams can be potentially infinite. Elements currently manipulated are stored in memory.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Mar 7 at 5:34

























      answered Mar 6 at 16:17









      AndronicusAndronicus

      4,71921531




      4,71921531








      • 1





        @AlikElzin-kilaka please don't ask about the memory implications :) To me, it's obvious that none of Stream API solutions will outdo the simple loop approach mentioned by you (I'd go with a fori loop, though) in any way (performance, readability, maintenance). I honestly don't understand why you want streams here.

        – Andrew Tobilko
        Mar 6 at 16:44













      • Why do you assume that it's safe to cast: (List<E>) itemIter?

        – ernest_k
        Mar 6 at 16:46











      • @ernest_k it doesn't really matter, I don't know the context (what itemIter really is). Let's just treat it as a pseudocode, that can be compiled, just to show the idea :)

        – Andronicus
        Mar 6 at 16:48






      • 1





        Well, it doesn’t even compile. Since objects are not an Iterable and an Iterator at the same time, you can’t cast it to List and expect it to also have a next() method. Once you fixed this, you don’t need the questionable type cast: E firstElement = itemIter.iterator().next(); Stream<E> stream = StreamSupport.stream(itemIter.spliterator(), false);

        – Holger
        Mar 6 at 17:44














      • 1





        @AlikElzin-kilaka please don't ask about the memory implications :) To me, it's obvious that none of Stream API solutions will outdo the simple loop approach mentioned by you (I'd go with a fori loop, though) in any way (performance, readability, maintenance). I honestly don't understand why you want streams here.

        – Andrew Tobilko
        Mar 6 at 16:44













      • Why do you assume that it's safe to cast: (List<E>) itemIter?

        – ernest_k
        Mar 6 at 16:46











      • @ernest_k it doesn't really matter, I don't know the context (what itemIter really is). Let's just treat it as a pseudocode, that can be compiled, just to show the idea :)

        – Andronicus
        Mar 6 at 16:48






      • 1





        Well, it doesn’t even compile. Since objects are not an Iterable and an Iterator at the same time, you can’t cast it to List and expect it to also have a next() method. Once you fixed this, you don’t need the questionable type cast: E firstElement = itemIter.iterator().next(); Stream<E> stream = StreamSupport.stream(itemIter.spliterator(), false);

        – Holger
        Mar 6 at 17:44








      1




      1





      @AlikElzin-kilaka please don't ask about the memory implications :) To me, it's obvious that none of Stream API solutions will outdo the simple loop approach mentioned by you (I'd go with a fori loop, though) in any way (performance, readability, maintenance). I honestly don't understand why you want streams here.

      – Andrew Tobilko
      Mar 6 at 16:44







      @AlikElzin-kilaka please don't ask about the memory implications :) To me, it's obvious that none of Stream API solutions will outdo the simple loop approach mentioned by you (I'd go with a fori loop, though) in any way (performance, readability, maintenance). I honestly don't understand why you want streams here.

      – Andrew Tobilko
      Mar 6 at 16:44















      Why do you assume that it's safe to cast: (List<E>) itemIter?

      – ernest_k
      Mar 6 at 16:46





      Why do you assume that it's safe to cast: (List<E>) itemIter?

      – ernest_k
      Mar 6 at 16:46













      @ernest_k it doesn't really matter, I don't know the context (what itemIter really is). Let's just treat it as a pseudocode, that can be compiled, just to show the idea :)

      – Andronicus
      Mar 6 at 16:48





      @ernest_k it doesn't really matter, I don't know the context (what itemIter really is). Let's just treat it as a pseudocode, that can be compiled, just to show the idea :)

      – Andronicus
      Mar 6 at 16:48




      1




      1





      Well, it doesn’t even compile. Since objects are not an Iterable and an Iterator at the same time, you can’t cast it to List and expect it to also have a next() method. Once you fixed this, you don’t need the questionable type cast: E firstElement = itemIter.iterator().next(); Stream<E> stream = StreamSupport.stream(itemIter.spliterator(), false);

      – Holger
      Mar 6 at 17:44





      Well, it doesn’t even compile. Since objects are not an Iterable and an Iterator at the same time, you can’t cast it to List and expect it to also have a next() method. Once you fixed this, you don’t need the questionable type cast: E firstElement = itemIter.iterator().next(); Stream<E> stream = StreamSupport.stream(itemIter.spliterator(), false);

      – Holger
      Mar 6 at 17:44











      5














      If your starting point is a Stream and you want to retain all of its properties and the laziness, the following solution will do:



      public static <E> Stream<E> forFirst(Stream<E> stream, Consumer<? super E> c) {
      boolean parallel = stream.isParallel();
      Spliterator<E> sp = stream.spliterator();
      return StreamSupport.stream(() -> {
      if(sp.getExactSizeIfKnown() == 0) return sp;
      Stream.Builder<E> b = Stream.builder();
      if(!sp.tryAdvance(b.andThen(c))) return sp;
      return Stream.concat(b.build(), StreamSupport.stream(sp, parallel)).spliterator();
      }, sp.characteristics(), parallel);
      }


      E.g. when you use it with



      List<String> list = new ArrayList<>(List.of("foo", "bar", "baz"));
      Stream<String> stream = forFirst(
      list.stream().filter(s -> s.startsWith("b")),
      s -> System.out.println(s+" ("+s.getClass().getSimpleName()+')')
      ).map(String::toUpperCase);
      list.add(1, "blah");
      System.out.println(stream.collect(Collectors.joining(" | ")));


      it will print



      blah (String)
      BLAH | BAR | BAZ


      demonstrating that the processing will not start before commencing the terminal operation (collect), hence reflecting the preceding update to the source List.






      share|improve this answer
























      • can't tell why this is not a lot higher :|

        – Eugene
        Mar 7 at 8:31











      • @Eugene because posted two hours after the other answers and being placed at the end in the default ordering… nothing to worry about

        – Holger
        Mar 7 at 10:07
















      5














      If your starting point is a Stream and you want to retain all of its properties and the laziness, the following solution will do:



      public static <E> Stream<E> forFirst(Stream<E> stream, Consumer<? super E> c) {
      boolean parallel = stream.isParallel();
      Spliterator<E> sp = stream.spliterator();
      return StreamSupport.stream(() -> {
      if(sp.getExactSizeIfKnown() == 0) return sp;
      Stream.Builder<E> b = Stream.builder();
      if(!sp.tryAdvance(b.andThen(c))) return sp;
      return Stream.concat(b.build(), StreamSupport.stream(sp, parallel)).spliterator();
      }, sp.characteristics(), parallel);
      }


      E.g. when you use it with



      List<String> list = new ArrayList<>(List.of("foo", "bar", "baz"));
      Stream<String> stream = forFirst(
      list.stream().filter(s -> s.startsWith("b")),
      s -> System.out.println(s+" ("+s.getClass().getSimpleName()+')')
      ).map(String::toUpperCase);
      list.add(1, "blah");
      System.out.println(stream.collect(Collectors.joining(" | ")));


      it will print



      blah (String)
      BLAH | BAR | BAZ


      demonstrating that the processing will not start before commencing the terminal operation (collect), hence reflecting the preceding update to the source List.






      share|improve this answer
























      • can't tell why this is not a lot higher :|

        – Eugene
        Mar 7 at 8:31











      • @Eugene because posted two hours after the other answers and being placed at the end in the default ordering… nothing to worry about

        – Holger
        Mar 7 at 10:07














      5












      5








      5







      If your starting point is a Stream and you want to retain all of its properties and the laziness, the following solution will do:



      public static <E> Stream<E> forFirst(Stream<E> stream, Consumer<? super E> c) {
      boolean parallel = stream.isParallel();
      Spliterator<E> sp = stream.spliterator();
      return StreamSupport.stream(() -> {
      if(sp.getExactSizeIfKnown() == 0) return sp;
      Stream.Builder<E> b = Stream.builder();
      if(!sp.tryAdvance(b.andThen(c))) return sp;
      return Stream.concat(b.build(), StreamSupport.stream(sp, parallel)).spliterator();
      }, sp.characteristics(), parallel);
      }


      E.g. when you use it with



      List<String> list = new ArrayList<>(List.of("foo", "bar", "baz"));
      Stream<String> stream = forFirst(
      list.stream().filter(s -> s.startsWith("b")),
      s -> System.out.println(s+" ("+s.getClass().getSimpleName()+')')
      ).map(String::toUpperCase);
      list.add(1, "blah");
      System.out.println(stream.collect(Collectors.joining(" | ")));


      it will print



      blah (String)
      BLAH | BAR | BAZ


      demonstrating that the processing will not start before commencing the terminal operation (collect), hence reflecting the preceding update to the source List.






      share|improve this answer













      If your starting point is a Stream and you want to retain all of its properties and the laziness, the following solution will do:



      public static <E> Stream<E> forFirst(Stream<E> stream, Consumer<? super E> c) {
      boolean parallel = stream.isParallel();
      Spliterator<E> sp = stream.spliterator();
      return StreamSupport.stream(() -> {
      if(sp.getExactSizeIfKnown() == 0) return sp;
      Stream.Builder<E> b = Stream.builder();
      if(!sp.tryAdvance(b.andThen(c))) return sp;
      return Stream.concat(b.build(), StreamSupport.stream(sp, parallel)).spliterator();
      }, sp.characteristics(), parallel);
      }


      E.g. when you use it with



      List<String> list = new ArrayList<>(List.of("foo", "bar", "baz"));
      Stream<String> stream = forFirst(
      list.stream().filter(s -> s.startsWith("b")),
      s -> System.out.println(s+" ("+s.getClass().getSimpleName()+')')
      ).map(String::toUpperCase);
      list.add(1, "blah");
      System.out.println(stream.collect(Collectors.joining(" | ")));


      it will print



      blah (String)
      BLAH | BAR | BAZ


      demonstrating that the processing will not start before commencing the terminal operation (collect), hence reflecting the preceding update to the source List.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Mar 6 at 18:26









      HolgerHolger

      169k23238454




      169k23238454













      • can't tell why this is not a lot higher :|

        – Eugene
        Mar 7 at 8:31











      • @Eugene because posted two hours after the other answers and being placed at the end in the default ordering… nothing to worry about

        – Holger
        Mar 7 at 10:07



















      • can't tell why this is not a lot higher :|

        – Eugene
        Mar 7 at 8:31











      • @Eugene because posted two hours after the other answers and being placed at the end in the default ordering… nothing to worry about

        – Holger
        Mar 7 at 10:07

















      can't tell why this is not a lot higher :|

      – Eugene
      Mar 7 at 8:31





      can't tell why this is not a lot higher :|

      – Eugene
      Mar 7 at 8:31













      @Eugene because posted two hours after the other answers and being placed at the end in the default ordering… nothing to worry about

      – Holger
      Mar 7 at 10:07





      @Eugene because posted two hours after the other answers and being placed at the end in the default ordering… nothing to worry about

      – Holger
      Mar 7 at 10:07











      4














      You can abuse reduction:



      Stream<E> stream = ...;
      System.out.println(stream
      .reduce("",(out,e) ->
      out + (out.isEmpty() ? e.getClass().getSimpleName()+"n" : "")
      + e));





      share|improve this answer






























        4














        You can abuse reduction:



        Stream<E> stream = ...;
        System.out.println(stream
        .reduce("",(out,e) ->
        out + (out.isEmpty() ? e.getClass().getSimpleName()+"n" : "")
        + e));





        share|improve this answer




























          4












          4








          4







          You can abuse reduction:



          Stream<E> stream = ...;
          System.out.println(stream
          .reduce("",(out,e) ->
          out + (out.isEmpty() ? e.getClass().getSimpleName()+"n" : "")
          + e));





          share|improve this answer















          You can abuse reduction:



          Stream<E> stream = ...;
          System.out.println(stream
          .reduce("",(out,e) ->
          out + (out.isEmpty() ? e.getClass().getSimpleName()+"n" : "")
          + e));






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 6 at 16:38

























          answered Mar 6 at 16:20









          Benjamin UrquhartBenjamin Urquhart

          1446




          1446























              0














              One workaround is to do it like this -



              import java.util.*; 
              import java.util.stream.Collectors;
              public class MyClass {
              static int i = 0;
              static int getCounter(){
              return i;
              }
              static void incrementCounter(){
              i++;
              }
              public static void main(String args) {
              List<String> list = Arrays.asList("A", "B", "C", "D", "E", "F", "G");
              List<String> answer = list.stream().filter(str -> {if(getCounter()==0) {System.out.println("First Element : " + str);} incrementCounter(); return true;}).
              collect(Collectors.toList());
              System.out.println(answer);
              }
              }


              Output :



              First Element : A
              [A, B, C, D, E, F, G]





              share|improve this answer



















              • 1





                requires you to always reset the value though, and will not work in a multi thread environment

                – Lino
                Mar 6 at 16:52
















              0














              One workaround is to do it like this -



              import java.util.*; 
              import java.util.stream.Collectors;
              public class MyClass {
              static int i = 0;
              static int getCounter(){
              return i;
              }
              static void incrementCounter(){
              i++;
              }
              public static void main(String args) {
              List<String> list = Arrays.asList("A", "B", "C", "D", "E", "F", "G");
              List<String> answer = list.stream().filter(str -> {if(getCounter()==0) {System.out.println("First Element : " + str);} incrementCounter(); return true;}).
              collect(Collectors.toList());
              System.out.println(answer);
              }
              }


              Output :



              First Element : A
              [A, B, C, D, E, F, G]





              share|improve this answer



















              • 1





                requires you to always reset the value though, and will not work in a multi thread environment

                – Lino
                Mar 6 at 16:52














              0












              0








              0







              One workaround is to do it like this -



              import java.util.*; 
              import java.util.stream.Collectors;
              public class MyClass {
              static int i = 0;
              static int getCounter(){
              return i;
              }
              static void incrementCounter(){
              i++;
              }
              public static void main(String args) {
              List<String> list = Arrays.asList("A", "B", "C", "D", "E", "F", "G");
              List<String> answer = list.stream().filter(str -> {if(getCounter()==0) {System.out.println("First Element : " + str);} incrementCounter(); return true;}).
              collect(Collectors.toList());
              System.out.println(answer);
              }
              }


              Output :



              First Element : A
              [A, B, C, D, E, F, G]





              share|improve this answer













              One workaround is to do it like this -



              import java.util.*; 
              import java.util.stream.Collectors;
              public class MyClass {
              static int i = 0;
              static int getCounter(){
              return i;
              }
              static void incrementCounter(){
              i++;
              }
              public static void main(String args) {
              List<String> list = Arrays.asList("A", "B", "C", "D", "E", "F", "G");
              List<String> answer = list.stream().filter(str -> {if(getCounter()==0) {System.out.println("First Element : " + str);} incrementCounter(); return true;}).
              collect(Collectors.toList());
              System.out.println(answer);
              }
              }


              Output :



              First Element : A
              [A, B, C, D, E, F, G]






              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Mar 6 at 16:33









              Mohammad AdilMohammad Adil

              39.5k1471100




              39.5k1471100








              • 1





                requires you to always reset the value though, and will not work in a multi thread environment

                – Lino
                Mar 6 at 16:52














              • 1





                requires you to always reset the value though, and will not work in a multi thread environment

                – Lino
                Mar 6 at 16:52








              1




              1





              requires you to always reset the value though, and will not work in a multi thread environment

              – Lino
              Mar 6 at 16:52





              requires you to always reset the value though, and will not work in a multi thread environment

              – Lino
              Mar 6 at 16:52











              0














              You could use peek for that:



              AtomicBoolean first = new AtomicBoolean(true);
              StreamSupport.stream(itemIter.spliterator(), false)
              .peek(e -> {
              if(first.get()) {
              System.out.println(e.getClass().getSimpleName());
              first.set(false);
              }
              })
              ...





              share|improve this answer





















              • 1





                In that sense, I guess the code in question would be much better even if the iterable is defined. Keeping in mind there is nothing like itemIter.stream() available up front.

                – Naman
                Mar 6 at 16:36













              • @nullpointer you're right, I've edited my answer to use StreamSupport

                – Lino
                Mar 6 at 16:46











              • The action passed to peek will be executed in the processing order which is not guaranteed to be the Stream’s encounter order.

                – Holger
                Mar 6 at 17:45
















              0














              You could use peek for that:



              AtomicBoolean first = new AtomicBoolean(true);
              StreamSupport.stream(itemIter.spliterator(), false)
              .peek(e -> {
              if(first.get()) {
              System.out.println(e.getClass().getSimpleName());
              first.set(false);
              }
              })
              ...





              share|improve this answer





















              • 1





                In that sense, I guess the code in question would be much better even if the iterable is defined. Keeping in mind there is nothing like itemIter.stream() available up front.

                – Naman
                Mar 6 at 16:36













              • @nullpointer you're right, I've edited my answer to use StreamSupport

                – Lino
                Mar 6 at 16:46











              • The action passed to peek will be executed in the processing order which is not guaranteed to be the Stream’s encounter order.

                – Holger
                Mar 6 at 17:45














              0












              0








              0







              You could use peek for that:



              AtomicBoolean first = new AtomicBoolean(true);
              StreamSupport.stream(itemIter.spliterator(), false)
              .peek(e -> {
              if(first.get()) {
              System.out.println(e.getClass().getSimpleName());
              first.set(false);
              }
              })
              ...





              share|improve this answer















              You could use peek for that:



              AtomicBoolean first = new AtomicBoolean(true);
              StreamSupport.stream(itemIter.spliterator(), false)
              .peek(e -> {
              if(first.get()) {
              System.out.println(e.getClass().getSimpleName());
              first.set(false);
              }
              })
              ...






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Mar 6 at 16:45

























              answered Mar 6 at 16:32









              LinoLino

              10k22043




              10k22043








              • 1





                In that sense, I guess the code in question would be much better even if the iterable is defined. Keeping in mind there is nothing like itemIter.stream() available up front.

                – Naman
                Mar 6 at 16:36













              • @nullpointer you're right, I've edited my answer to use StreamSupport

                – Lino
                Mar 6 at 16:46











              • The action passed to peek will be executed in the processing order which is not guaranteed to be the Stream’s encounter order.

                – Holger
                Mar 6 at 17:45














              • 1





                In that sense, I guess the code in question would be much better even if the iterable is defined. Keeping in mind there is nothing like itemIter.stream() available up front.

                – Naman
                Mar 6 at 16:36













              • @nullpointer you're right, I've edited my answer to use StreamSupport

                – Lino
                Mar 6 at 16:46











              • The action passed to peek will be executed in the processing order which is not guaranteed to be the Stream’s encounter order.

                – Holger
                Mar 6 at 17:45








              1




              1





              In that sense, I guess the code in question would be much better even if the iterable is defined. Keeping in mind there is nothing like itemIter.stream() available up front.

              – Naman
              Mar 6 at 16:36







              In that sense, I guess the code in question would be much better even if the iterable is defined. Keeping in mind there is nothing like itemIter.stream() available up front.

              – Naman
              Mar 6 at 16:36















              @nullpointer you're right, I've edited my answer to use StreamSupport

              – Lino
              Mar 6 at 16:46





              @nullpointer you're right, I've edited my answer to use StreamSupport

              – Lino
              Mar 6 at 16:46













              The action passed to peek will be executed in the processing order which is not guaranteed to be the Stream’s encounter order.

              – Holger
              Mar 6 at 17:45





              The action passed to peek will be executed in the processing order which is not guaranteed to be the Stream’s encounter order.

              – Holger
              Mar 6 at 17:45











              0














              You can also use an boolean atomic reference:



              AtomicReference<Boolean> first = new AtomicReference<Boolean>(Boolean.TRUE);
              stream.forEach(e ->
              System.out.println("First == " + first.getAndUpdate(b -> false)));





              share|improve this answer




























                0














                You can also use an boolean atomic reference:



                AtomicReference<Boolean> first = new AtomicReference<Boolean>(Boolean.TRUE);
                stream.forEach(e ->
                System.out.println("First == " + first.getAndUpdate(b -> false)));





                share|improve this answer


























                  0












                  0








                  0







                  You can also use an boolean atomic reference:



                  AtomicReference<Boolean> first = new AtomicReference<Boolean>(Boolean.TRUE);
                  stream.forEach(e ->
                  System.out.println("First == " + first.getAndUpdate(b -> false)));





                  share|improve this answer













                  You can also use an boolean atomic reference:



                  AtomicReference<Boolean> first = new AtomicReference<Boolean>(Boolean.TRUE);
                  stream.forEach(e ->
                  System.out.println("First == " + first.getAndUpdate(b -> false)));






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Mar 6 at 16:59









                  ernest_kernest_k

                  23.5k42749




                  23.5k42749






























                      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%2f55027574%2fhow-do-i-get-the-first-element-while-continue-streaming%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

                      How to change which sound is reproduced for terminal bell?

                      Can I use Tabulator js library in my java Spring + Thymeleaf project?

                      Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents