Top answer
1 of 6
192

For this specific example, you could do:

IntStream.rangeClosed(1, 8)
         .forEach(System.out::println);

If you need a step different from 1, you can use a mapping function, for example, for a step of 2:

IntStream.rangeClosed(1, 8)
         .map(i -> 2 * i - 1)
         .forEach(System.out::println);

Or build a custom iteration and limit the size of the iteration:

IntStream.iterate(1, i -> i + 2)
         .limit(8)
         .forEach(System.out::println);
2 of 6
80

Here's another technique I ran across the other day:

Collections.nCopies(8, 1)
           .stream()
           .forEach(i -> System.out.println(i));

The Collections.nCopies call creates a List containing n copies of whatever value you provide. In this case it's the boxed Integer value 1. Of course it doesn't actually create a list with n elements; it creates a "virtualized" list that contains only the value and the length, and any call to get within range just returns the value. The nCopies method has been around since the Collections Framework was introduced way back in JDK 1.2. Of course, the ability to create a stream from its result was added in Java SE 8.

Big deal, another way to do the same thing in about the same number of lines.

However, this technique is faster than the IntStream.generate and IntStream.iterate approaches, and surprisingly, it's also faster than the IntStream.range approach.

For iterate and generate the result is perhaps not too surprising. The streams framework (really, the Spliterators for these streams) is built on the assumption that the lambdas will potentially generate different values each time, and that they will generate an unbounded number of results. This makes parallel splitting particularly difficult. The iterate method is also problematic for this case because each call requires the result of the previous one. So the streams using generate and iterate don't do very well for generating repeated constants.

The relatively poor performance of range is surprising. This too is virtualized, so the elements don't actually all exist in memory, and the size is known up front. This should make for a fast and easily parallelizable spliterator. But it surprisingly didn't do very well. Perhaps the reason is that range has to compute a value for each element of the range and then call a function on it. But this function just ignores its input and returns a constant, so I'm surprised this isn't inlined and killed.

The Collections.nCopies technique has to do boxing/unboxing in order to handle the values, since there are no primitive specializations of List. Since the value is the same every time, it's basically boxed once and that box is shared by all n copies. I suspect boxing/unboxing is highly optimized, even intrinsified, and it can be inlined well.

Here's the code:

    public static final int LIMIT = 500_000_000;
    public static final long VALUE = 3L;

    public long range() {
        return
            LongStream.range(0, LIMIT)
                .parallel()
                .map(i -> VALUE)
                .map(i -> i % 73 % 13)
                .sum();
}

    public long ncopies() {
        return
            Collections.nCopies(LIMIT, VALUE)
                .parallelStream()
                .mapToLong(i -> i)
                .map(i -> i % 73 % 13)
                .sum();
}

And here are the JMH results: (2.8GHz Core2Duo)

Benchmark                    Mode   Samples         Mean   Mean error    Units
c.s.q.SO18532488.ncopies    thrpt         5        7.547        2.904    ops/s
c.s.q.SO18532488.range      thrpt         5        0.317        0.064    ops/s

There is a fair amount of variance in the ncopies version, but overall it seems comfortably 20x faster than the range version. (I'd be quite willing to believe that I've done something wrong, though.)

I'm surprised at how well the nCopies technique works. Internally it doesn't do very much special, with the stream of the virtualized list simply being implemented using IntStream.range! I had expected that it would be necessary to create a specialized spliterator to get this to go fast, but it already seems to be pretty good.

Top answer
1 of 2
26
IntStream.range(0, 1000)
         /* .parallel() */
         .filter(i -> i+1 % 100 == 0)
         .peek(i -> System.out.println("Test number " + i + " started."))
         /* other operations on the stream including a terminal one */;

If the test is running on each iteration regardless of the condition (take the filter out):

IntStream.range(0, 1000)
         .peek(i -> {
             if (i + 1 % 100 == 0) {
                 System.out.println("Test number " + i + " started.");
             }
         }).forEach(i -> {/* the test */});

Another approach (if you want to iterate over an index with a predefined step, as @Tunaki mentioned) is:

IntStream.iterate(0, i -> i + 100)
         .limit(1000 / 100)
         .forEach(i -> { /* the test */ });

There is an awesome overloaded method Stream.iterate(seed, condition, unaryOperator) in JDK 9 which perfectly fits your situation and is designed to make a stream finite and might replace a plain for:

Stream<Integer> stream = Stream.iterate(0, i -> i < 1000, i -> i + 100);
2 of 2
2

You can use IntStream as shown below and explained in the comments:

(1) Iterate IntStream range from 1 to 1000

(2) Convert to parallel stream

(3) Apply Predicate condition to allow integers with (i+1)%100 == 0

(4) Now convert the integer to a string "Test number "+i+" started."

(5) Output to console

IntStream.range(1, 1000). //iterates 1 to 1000
   parallel().//converts to parallel stream
   filter( i -> ((i+1)%100 == 0)). //filters numbers & allows like 99, 199, etc..)
   mapToObj((int i) -> "Test number "+i+" started.").//maps integer to String
   forEach(System.out::println);//prints to the console
🌐
Baeldung
baeldung.com › home › java › java streams › java and infinite streams
Java and Infinite Streams | Baeldung
January 8, 2024 - We are printing i counter ten times. We can expect that such construct can be easily written using Stream API and ideally, we would have a doWhile() method on a stream. Unfortunately, there is no such method on a stream and when we want to achieve functionality similar to standard do-while loop we need to use a limit() method:
🌐
Mkyong
mkyong.com › home › java8 › java 8 stream.iterate examples
Java 8 Stream.iterate examples - Mkyong.com
November 29, 2018 - In Java 8, we can use Stream.iterate to create stream values on demand, so called infinite stream. ... //Stream.iterate(initial value, next value) Stream.iterate(0, n -> n + 1) .limit(10) .forEach(x -> System.out.println(x));
Top answer
1 of 2
1

There are multiple ways you could change your snippet here to use Java-8 Streams. Here an overview of a few straight out of my head.

List<IDWrapper> list = IntStream.range( 0, 20 ).mapToObj( IDWrapper::new ).collect( Collectors.toList() );
    List<String> details = list.stream().map( IDWrapper::getId ).map( this::getDetails ).collect( Collectors.toList() );
    List<String> details2 = list.stream().map( item -> item.getId() ).map( id -> getDetails( id ) ).collect( Collectors.toList() );
    List<String> details3 = list.stream().map( item -> getDetails( item.getId() ) ).collect( Collectors.toList() );

Let's break them down and explain their differences a bite more.

1.

List<String> details = list.stream().map( IDWrapper::getId ).map( this::getDetails ).collect( Collectors.toList() );

This one uses MethodReferences to pass the desired functions down the Stream#map(Function) method. It can be read as 'map the items, which are IDWrapper-Objects and do it by calling IDWrapper#getId() on every object and put the resulting items (integer values in this case) back into the stream'. Afterwards another call to Stream#map(Function) is done but this time the object to operate on is 'this' (my dummy class i created for the example) and call the #getDetails(int) method on this class.

2.

List<String> details2 = list.stream().map( item -> item.getId() ).map( id -> getDetails( id ) ).collect( Collectors.toList() );

This one is quite simply equal to 1. but using usual lambda expression to achieve the same.

3.

List<String> details3 = list.stream().map( item -> getDetails( item.getId() ) ).collect( Collectors.toList() );

In this case we're defining the function as a lamda and simply chaining the method class.

As mentioned before there are lots of other possibilities, but here are an education few. Hope I could help you understanding streams a little bit better.

2 of 2
0

Something like:

Map<String,Integer> m =
    list.stream()
        .collect(Collectors.toMap(e -> e.getUser, // key extractor
                                  e -> getDetail(e.getId()).getBody().getData() // value extractor
                                 )
                );    

----EDIT----

Ho ho... This is exactly Holger's comment. Give credit where credit is due.

🌐
Adam-bien
adam-bien.com › roller › abien › entry › java_8_from_ordinary_for
Java 8: From Ordinary For-Loop To An IntStream
January 28, 2014 - IntStream.range(0, 10).parallel().forEach( nbr -> { try { Thread.sleep(1000); } catch (InterruptedException ex) {} System.out.println(nbr); } );
🌐
Medium
medium.com › @AlexanderObregon › javas-stream-iterate-method-explained-2922dfd01117
Java’s Stream.iterate() Method Explained | Medium
December 1, 2024 - ... The Stream.iterate() method can create sequences following any arithmetic rule. For instance, generating a sequence that starts at 5 and increments by 3 each time: import java.util.stream.Stream; public class ArithmeticSequenceExample { public static void main(String[] args) { Stream.iterate(5, n -> n + 3) ...
Find elsewhere
🌐
Quora
quora.com › How-can-I-make-a-loop-run-X-number-of-times-in-Java
How to make a loop run X number of times in Java - Quora
A for loop uses a counter. A while loop uses a counter. Java 8 uses IntStream with forEach. These examples demonstrate ways to run a loop a specific number of times. A counter or range of values is utilized. The numberOfTimes variable changes the loop's iteration count.
🌐
Baeldung
baeldung.com › home › java › java streams › streams vs. loops in java
Streams vs. Loops in Java | Baeldung
January 8, 2024 - We’ll compare the execution times of complex operations involving filtering, mapping, and summing using both for-loops and streams. For this purpose, we’ll use the Java Microbenchmarking Harness (JMH), a tool designed specifically for benchmarking Java code.
🌐
javathinking
javathinking.com › blog › using-a-stream-to-iterate-n-times-instead-of-using-a-for-loop-to-create-n-items
Java 8 Streams: How to Iterate N Times and Create Items (Instead of For Loops) — javathinking.com
In this blog, we’ll explore how to use Java 8 streams to iterate `N` times and create items—replacing clunky `for` loops with concise, readable code. We’ll cover multiple stream-based techniques, their use cases, and best practices to avoid common pitfalls.
🌐
Medium
medium.com › @ezzeddinebilel › java-stream-and-for-loop-a-balanced-view-on-performance-a38e45f271e5
Java Stream and For Loop: A Balanced View on Performance | by Bilel Ezzeddine | Medium
February 18, 2024 - When it comes to iterating through lists and arrays using traditional for loops, the algorithmic complexity is straightforward. The time complexity of looping through a collection of size n using a for loop is O(n), where n represents the number ...
Top answer
1 of 5
2

I would suggest you make a list of all the user ids outside the loop. Just make sure the class Id overrides equals() function.

List<Id> allUsersIds = allUserNodes.stream().map(n -> n.getNodeId()).collect(Collectors.toList());

for (ItemSetNode itemSetNode : itemSetNodeList)
{
    Id nodeId = itemSetNode.getNodeId();

    if (!allUsersIds.contains(nodeId))
    {
        isUserMissingNode = true;
        break;
    }
}
2 of 5
1

The following code should be equivalent, except that the value of the boolean is reversed so it's false if there are missing nodes.

First all the user node Ids are collected to a TreeSet (if Id implements hashCode() and equals() you should use a HashSet). Then we stream itemSetNodeList to see if all those nodeIds are contained in the set.

TreeSet<Id> all = allUserNodes
                        .stream()
                        .map(n -> n.getNodeId())
                        .collect(Collectors.toCollection(TreeSet::new));

boolean isAllNodes = itemSetNodeList
                        .stream()
                        .allMatch(n -> all.contains(n.getNodeId()));

There are many ways to write equivalent (at least to outside eyes) code, this uses a Set to improve the lookup so we don't need to keep iterating the allUserNodes collection constantly.

You want to avoid using a stream in a loop, because that will turn your algorithm into O(n²) when you're doing a linear loop and a linear stream operation inside it. This approach is O(n log n), for the linear stream operation and O(log n) TreeSet lookup. With a HashSet this goes down to just O(n), not that it matters much unless you're dealing with large amount of elements.

🌐
HowToDoInJava
howtodoinjava.com › home › java 8 › java stream reuse – consume stream multiple times?
Java Stream Reuse - Consume Stream Multiple Times?
May 27, 2024 - A stream implementation may throw IllegalStateException if it detects that the stream is being reused.“ · So the simple answer is: NO, we cannot reuse the streams or traverse the streams multiple times.
🌐
Medium
neesri.medium.com › about-stream-iterate-e2984e87caea
✍️Stream.iterate in Java 8
July 20, 2025 - f: The unary operator (a function that takes one argument and returns a result of the same type) to apply to the previous element to produce the next element. Here’s an example of using Stream.iterate in Java 8: ... Add 2 each time: 0, 2, 4, 6, ...
🌐
Coderanch
coderanch.com › t › 698985 › java › Java-streams-multiple-loops
Java8 - Use of streams in multiple loops (Features new in Java 8 forum at Coderanch)
September 14, 2018 - I am iterating the same list twice. Is it possible to do it using streams? Thanks, Atul ... Atul More wrote:. . . I am iterating the same list twice. Is it possible to do it using streams? . . . Yes, but you cannot use the same Stream twice; you may need to create two Streams.
🌐
OneCompiler
onecompiler.com › java › 3uavpjre6
Print 1 to 10 numbers using IntStream (Java8) - Java - OneCompiler
import java.util.Scanner; class Input { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("Enter your name: "); String inp = input.next(); System.out.println("Hello, " + inp); } } OneCompiler supports Gradle for dependency management. Users can add dependencies in the build.gradle file and use them in their programs. When you add the dependencies for the first time, the first run might be a little slow as we download the dependencies, but the subsequent runs will be faster.