Limit a stream by a predicate

前端 未结 19 3108
别跟我提以往
别跟我提以往 2020-11-21 22:54

Is there a Java 8 stream operation that limits a (potentially infinite) Stream until the first element fails to match a predicate?

In Java 9 we can use

相关标签:
19条回答
  • 2020-11-21 23:34

    Even I was having a similar requirement -- invoke the web-service, if it fails, retry it 3 times. If it fails even after these many trials, send an email notification. After googling a lot, anyMatch() came as a saviour. My sample code as follows. In the following example, if webServiceCall method returns true in the first iteration itself, stream does not iterate further as we have called anyMatch(). I believe, this is what you are looking for.

    import java.util.stream.IntStream;
    
    import io.netty.util.internal.ThreadLocalRandom;
    
    class TrialStreamMatch {
    
    public static void main(String[] args) {        
        if(!IntStream.range(1,3).anyMatch(integ -> webServiceCall(integ))){
             //Code for sending email notifications
        }
    }
    
    public static boolean webServiceCall(int i){
        //For time being, I have written a code for generating boolean randomly
        //This whole piece needs to be replaced by actual web-service client code
        boolean bool = ThreadLocalRandom.current().nextBoolean();
        System.out.println("Iteration index :: "+i+" bool :: "+bool);
    
        //Return success status -- true or false
        return bool;
    }
    
    0 讨论(0)
  • 2020-11-21 23:35

    If you have different problem, different solution may be needed but for your current problem, I would simply go with:

    IntStream
        .iterate(1, n -> n + 1)
        .limit(10)
        .forEach(System.out::println);
    
    0 讨论(0)
  • 2020-11-21 23:39

    If you know the exact amount of repititions that will be performed, you can do

    IntStream
              .iterate(1, n -> n + 1)
              .limit(10)
              .forEach(System.out::println);
    
    0 讨论(0)
  • 2020-11-21 23:41

    You can't abort a stream except by a short-circuiting terminal operation, which would leave some stream values unprocessed regardless of their value. But if you just want to avoid operations on a stream you can add a transform and filter to the stream:

    import java.util.Objects;
    
    class ThingProcessor
    {
        static Thing returnNullOnCondition(Thing thing)
        {    return( (*** is condition met ***)? null : thing);    }
    
        void processThings(Collection<Thing> thingsCollection)
        {
            thingsCollection.stream()
            *** regular stream processing ***
            .map(ThingProcessor::returnNullOnCondition)
            .filter(Objects::nonNull)
            *** continue stream processing ***
        }
    } // class ThingProcessor
    

    That transforms the stream of things to nulls when the things meet some condition, then filters out nulls. If you're willing to indulge in side effects, you could set the condition value to true once some thing is encountered, so all subsequent things are filtered out regardless of their value. But even if not you can save a lot of (if not quite all) processing by filtering values out of the stream that you don't want to process.

    0 讨论(0)
  • 2020-11-21 23:43

    takeWhile is one of the functions provided by the protonpack library.

    Stream<Integer> infiniteInts = Stream.iterate(0, i -> i + 1);
    Stream<Integer> finiteInts = StreamUtils.takeWhile(infiniteInts, i -> i < 10);
    
    assertThat(finiteInts.collect(Collectors.toList()),
               hasSize(10));
    
    0 讨论(0)
  • 2020-11-21 23:44

    You can use java8 + rxjava.

    import java.util.stream.IntStream;
    import rx.Observable;
    
    
    // Example 1)
    IntStream intStream  = IntStream.iterate(1, n -> n + 1);
    Observable.from(() -> intStream.iterator())
        .takeWhile(n ->
              {
                    System.out.println(n);
                    return n < 10;
              }
        ).subscribe() ;
    
    
    // Example 2
    IntStream intStream  = IntStream.iterate(1, n -> n + 1);
    Observable.from(() -> intStream.iterator())
        .takeWhile(n -> n < 10)
        .forEach( n -> System.out.println(n));
    
    0 讨论(0)
提交回复
热议问题