Java 用谓词限制流

Java 用谓词限制流,java,java-8,java-stream,Java,Java 8,Java Stream,是否有Java 8流操作限制(可能无限)流,直到第一个元素无法匹配谓词 在Java9中,我们可以使用takeWhile打印所有小于10的数字,如下例所示 IntStream .iterate(1, n -> n + 1) .takeWhile(n -> n < 10) .forEach(System.out::println); IntStream .迭代(1,n->n+1) .takeWhile(n->nn+1); TakeWhile.stream(

是否有Java 8流操作限制(可能无限)
,直到第一个元素无法匹配谓词

在Java9中,我们可以使用
takeWhile
打印所有小于10的数字,如下例所示

IntStream
    .iterate(1, n -> n + 1)
    .takeWhile(n -> n < 10)
    .forEach(System.out::println);
IntStream
.迭代(1,n->n+1)
.takeWhile(n->n<10)
.forEach(System.out::println);

由于Java8中没有这样的操作,一般来说,实现它的最佳方法是什么

对于Java 8
流,这样的操作应该是可能的,但它不一定能有效地完成——例如,您不一定能并行化这样的操作,因为您必须按顺序查看元素

API并没有提供一种简单的实现方法,但最简单的方法可能是使用
Stream.iterator()
,将
迭代器
包装成“take while”实现,然后返回到
拆分器
,然后是
。或者——也许——包装
拆分器
,尽管在这个实现中它不能再被拆分了

下面是一个未经测试的
takeWhile
拆分器上的实现:

static <T> Spliterator<T> takeWhile(
    Spliterator<T> splitr, Predicate<? super T> predicate) {
  return new Spliterators.AbstractSpliterator<T>(splitr.estimateSize(), 0) {
    boolean stillGoing = true;
    @Override public boolean tryAdvance(Consumer<? super T> consumer) {
      if (stillGoing) {
        boolean hadNext = splitr.tryAdvance(elem -> {
          if (predicate.test(elem)) {
            consumer.accept(elem);
          } else {
            stillGoing = false;
          }
        });
        return hadNext && stillGoing;
      }
      return false;
    }
  };
}

static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
   return StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false);
}
静态拆分器(

Spliterator splitr,Predicate更新:Java9
流现在提供了一个方法。

不需要黑客或其他解决方案。只要使用它


我相信这可以大大改进: (也许有人可以让它线程安全)

Stream=Stream.iterate(0,n->n+1);
TakeWhile.stream(流,n->n<10000)
.forEach(n->System.out.print((n==0?“+n:”,“+n));
一个黑客肯定…不优雅-但它的作品~:D 类TakeWhile实现迭代器{ 私有最终迭代器; 私有最终谓词; 下一步; private volatile boolean keepGoing=true; 公共TakeWhile(流s,谓词p){ this.iterator=s.iterator(); this.predicate=p; } @凌驾 公共布尔hasNext(){ 如果(!继续){ 返回false; } 如果(下一步!=null){ 返回true; } if(iterator.hasNext()){ next=迭代器.next(); keepGoing=predicate.test(下一步); 如果(!继续){ next=null; } } 返回下一步!=null; } @凌驾 公共交通工具{ if(next==null){ 如果(!hasNext()){ 抛出新的NoSuchElementException(“对不起,没什么适合你的。”); } } T温度=下一个; next=null; 返回温度; } 公共静态流(流s,谓词p){ TakeWhile tw=新TakeWhile(s,p); Spliterator split=Spliterators.Spliterator(tw,Integer.MAX_值,Spliterator.ORDERED); 返回StreamSupport.stream(拆分,false); } }
这是一个在ints上完成的版本-如问题中所述

用法:

StreamUtil.takeWhile(IntStream.iterate(1, n -> n + 1), n -> n < 10);

takeWhile
是由提供的功能之一

Stream infinitements=Stream.iterate(0,i->i+1);
streamfiniteints=StreamUtils.takeWhile(无限元素,i->i<10);
断言(finiteInts.collect(Collectors.toList()),
hasSize(10));

通过实现这一点,我有了另一个快速的解决方案(事实上这是不干净的,但你明白了):

publicstaticvoidmain(字符串[]args){
System.out.println(StreamUtil.iterate(1,o->o+1).terminateOn(15)
.map(o->o.toString()).collect(collector.joining(“,”));
}
静态接口终止流{
流终止(te);
}
静态类StreamUtil{
静态终止流迭代(T种子,一元运算符op){
返回新的TerminatedStream(){
公共流终止(TE){
Builder=Stream.Builder().add(种子);
T电流=种子;
而(!current.equals(e)){
电流=操作应用(电流);
builder.add(当前);
}
返回builder.build();
}
};
}
}
allMatch()
是一个短路函数,因此您可以使用它来停止处理。主要缺点是您必须执行两次测试:一次是查看是否应该处理它,另一次是查看是否继续

IntStream
    .iterate(1, n -> n + 1)
    .peek(n->{if (n<10) System.out.println(n);})
    .allMatch(n->n < 10);
IntStream
.迭代(1,n->n+1)
.peek(n->{if(nn<10);
您可以使用java8+

import java.util.stream.IntStream;
进口接收。可观察;
//例1)
IntStream IntStream=IntStream.iterate(1,n->n+1);
可观察的.from(()->intStream.iterator())
.takeWhile(n->
{
系统输出println(n);
返回n<10;
}
).subscribe();
//例2
IntStream IntStream=IntStream.iterate(1,n->n+1);
可观察的.from(()->intStream.iterator())
.takeWhile(n->n<10)
.forEach(n->System.out.println(n));

以下是我仅使用Java流库的尝试

        IntStream.iterate(0, i -> i + 1)
        .filter(n -> {
                if (n < 10) {
                    System.out.println(n);
                    return false;
                } else {
                    return true;
                }
            })
        .findAny();
IntStream.iterate(0,i->i+1)
.过滤器(n->{
如果(n<10){
系统输出println(n);
返回false;
}否则{
返回true;
}
})
.findAny();

操作
takeWhile
dropWhile
已添加到JDK 9中。您的示例代码

IntStream
    .iterate(1, n -> n + 1)
    .takeWhile(n -> n < 10)
    .forEach(System.out::println);
IntStream
.迭代(1,n->n+1)
.takeWhile(n->n<10)
.forEach(System.out::println);
在JDK 9下编译和运行时,它的行为将完全符合您的预期

JDK 9已发布。可在此处下载:。

作为后续。我的库具有与当前JDK-9实现兼容的操作。在JDK-9下运行时,它
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));
public static void main(String[] args) {
    System.out.println(StreamUtil.iterate(1, o -> o + 1).terminateOn(15)
            .map(o -> o.toString()).collect(Collectors.joining(", ")));
}

static interface TerminatedStream<T> {
    Stream<T> terminateOn(T e);
}

static class StreamUtil {
    static <T> TerminatedStream<T> iterate(T seed, UnaryOperator<T> op) {
        return new TerminatedStream<T>() {
            public Stream<T> terminateOn(T e) {
                Builder<T> builder = Stream.<T> builder().add(seed);
                T current = seed;
                while (!current.equals(e)) {
                    current = op.apply(current);
                    builder.add(current);
                }
                return builder.build();
            }
        };
    }
}
IntStream
    .iterate(1, n -> n + 1)
    .peek(n->{if (n<10) System.out.println(n);})
    .allMatch(n->n < 10);
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));
        IntStream.iterate(0, i -> i + 1)
        .filter(n -> {
                if (n < 10) {
                    System.out.println(n);
                    return false;
                } else {
                    return true;
                }
            })
        .findAny();
IntStream
    .iterate(1, n -> n + 1)
    .takeWhile(n -> n < 10)
    .forEach(System.out::println);
IntStreamEx.iterate(1, n -> n + 1)
           .takeWhile(n -> n < 10)
           .forEach(System.out::println);
IntStream.iterate(1, n -> n + 1).takeWhile(n -> n < 10).forEach(System.out::println);
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
IntStream.iterate(2, (i) -> i + 2).peek(System.out::println).allMatch(i -> i < 20);
IntStream.iterate(2, (i) -> i + 2).peek(System.out::println).anyMatch(i -> i >= 20);
2
4
6
8
10
12
14
16
18
20
IntStream
    .iterate(1, n -> n + 1)
    .limit(10)
    .forEach(System.out::println);
static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> p) {
    class Taking extends Spliterators.AbstractSpliterator<T> implements Consumer<T> {
        private static final int CANCEL_CHECK_COUNT = 63;
        private final Spliterator<T> s;
        private int count;
        private T t;
        private final AtomicBoolean cancel = new AtomicBoolean();
        private boolean takeOrDrop = true;

        Taking(Spliterator<T> s) {
            super(s.estimateSize(), s.characteristics() & ~(Spliterator.SIZED | Spliterator.SUBSIZED));
            this.s = s;
        }

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            boolean test = true;
            if (takeOrDrop &&               // If can take
                    (count != 0 || !cancel.get()) && // and if not cancelled
                    s.tryAdvance(this) &&   // and if advanced one element
                    (test = p.test(t))) {   // and test on element passes
                action.accept(t);           // then accept element
                return true;
            } else {
                // Taking is finished
                takeOrDrop = false;
                // Cancel all further traversal and splitting operations
                // only if test of element failed (short-circuited)
                if (!test)
                    cancel.set(true);
                return false;
            }
        }

        @Override
        public Comparator<? super T> getComparator() {
            return s.getComparator();
        }

        @Override
        public void accept(T t) {
            count = (count + 1) & CANCEL_CHECK_COUNT;
            this.t = t;
        }

        @Override
        public Spliterator<T> trySplit() {
            return null;
        }
    }
    return StreamSupport.stream(new Taking(stream.spliterator()), stream.isParallel()).onClose(stream::close);
}
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;
}
static <T> List<T> take(List<T> l, int n) {
    if (n <= 0) {
        return newArrayList();
    } else {
        int takeTo = Math.min(Math.max(n, 0), l.size());
        return l.subList(0, takeTo);
    }
}
    assertEquals(newArrayList(1, 2, 3), take(newArrayList(1, 2, 3, 4, 5), 3));
    assertEquals(newArrayList(1, 2, 3), take(newArrayList(1, 2, 3), 5));

    assertEquals(newArrayList(), take(newArrayList(1, 2, 3), -1));
    assertEquals(newArrayList(), take(newArrayList(1, 2, 3), 0));
static <T> List<T> takeWhile(List<T> l, Predicate<T> p) {
    return l.stream().
            filter(p.negate()).findFirst(). // find first element when p is false
            map(l::indexOf).        // find the index of that element
            map(i -> take(l, i)).   // take up to the index
            orElse(l);  // return full list if p is true for all elements
}
    assertEquals(newArrayList(1, 2, 3), takeWhile(newArrayList(1, 2, 3, 4, 3, 2, 1), i -> i < 4));
IntStream
          .iterate(1, n -> n + 1)
          .limit(10)
          .forEach(System.out::println);
    IntStream.iterate(1, n -> n + 1)
    .peek(System.out::println) //it will be executed 9 times
    .filter(n->n>=9)
    .findAny();
    IntStream.iterate(1, n -> n + 1)
    .mapToObj(n->{   //it will be executed 9 times
            if(n<9)
                return "";
            return "Loop repeats " + n + " times";});
    .filter(message->!message.isEmpty())
    .findAny()
    .ifPresent(System.out::println);