5

I want to make a stream with random numbers. As soon as the numbers fullfill a certain condition I want to now how many iterations was needed. So either I want to have the size of the stream or an Collection from which I can read then the size.

Here are my approaches:

random.ints(0, Integer.MAX_VALUE).anyMatch(a -> {return a < 20000;});

This gives me only the a boolean as soon as my condition is fullfilled.

random.ints(0, Integer.MAX_VALUE).filter(a -> a < 20000).limit(1).count();

And this returns obviously 1. But I want to have the size before I filtered my result. I further tried several things with a counting variable but since lambdas are capturing them effectifely final from outside I have an initialising problem.

Any help or hint is appreciated

9
  • 1
    you can use AtomicInteger for initialisation, peek in stream to increment counter, but it won't work the same in parallel stream Commented Dec 18, 2017 at 12:54
  • 1
    @Lino we quit when anyMatch returns true, peek would be done before anyMatch to have the count Commented Dec 18, 2017 at 12:58
  • 1
    @Saravana that sounds like an answer to me ;) Commented Dec 18, 2017 at 12:59
  • 2
    No, streams in Java 8 aren't designed for this use case. Using AtomicInteger and peek as a counter is a hack and should be avoided. Streams were designed to avoid side-effects and this approach goes against this core principle. Unless streams are an absolute necessity, you're better off switching to Java 9 or using a traditional for-each-index loop. Commented Dec 18, 2017 at 13:19
  • 1
    @Synch of course it does, but if you really need it? I can't say that the OP does or not - but in case he/she has a use case, there is no other way Commented Dec 18, 2017 at 13:20

3 Answers 3

3

Java 9 has a feature to support that - takeWhile:

random.ints(0, Integer.MAX_VALUE).takeWhile(a -> a < 20000).count();
Sign up to request clarification or add additional context in comments.

12 Comments

that's not really what the OP wants, he wants to know how many iterations where made to fulfill a certain requirement
@Eugene that's what above does, doesn't it? The count determines the iteration
@Eugene that's what count would give (when combined with takeWhile).
@Eran count here would be the same value as how many elements where produced by the stream, my understanding was that OP wants something like: take elements that are higher than 10 and limit these to 100 - how many elements from the stream (generate where produced) in order to fulfill this
Looks good on the first glance and likely does the expected thing in a sequential execution, but the problem is that the stream of random ints is unordered, so the following applies: If this stream is unordered, and some (but not all) elements of this stream match the given predicate, then the behavior of this operation is nondeterministic; it is free to take any subset of matching elements (which includes the empty set).
|
0

You can try takeWhile from this project

Example :

IntStream intStream = new Random().ints();
        Stream<Integer> result = StreamUtils.takeWhile(intStream.boxed().peek(i->System.out.println("in stream : " + i)), i -> i > 2000);
        long count = result.peek(i->System.out.println("in result : " + i))
                .count();
        System.out.println(count);

Prints:

in stream : 1466689339
in result : 1466689339
in stream : 1588320574
in result : 1588320574
in stream : 1621482181
in result : 1621482181
in stream : -2140739741
3

2 Comments

Can you give the implementation of takeWhile instead of just linking to it? I must admit you do give an example how to use it so it is not strickly a link-only answer.
What is the point to copy-paste the implementation ? It's easy to see it here github.com/poetix/protonpack/blob/master/src/main/java/com/…
0

There is no Stream.takeWhile() in Java 8, but you can easily workaround this with iterator():

public static int countWhile(IntStream stream, IntPredicate predicate) {
    PrimitiveIterator.OfInt iterator = stream.iterator();
    int i = 0;
    while (predicate.test(iterator.nextInt())) {
        i++;
    }
    return i;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.