Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以检查所有Java8流元素是否满足给定谓词之一?_Java_Java 8_Java Stream - Fatal编程技术网

是否可以检查所有Java8流元素是否满足给定谓词之一?

是否可以检查所有Java8流元素是否满足给定谓词之一?,java,java-8,java-stream,Java,Java 8,Java Stream,使用流API,我可以使用allMatch(e->predicate(e))方法轻松检查所有元素是否满足给定条件。我还可以检查多个条件中的任何一个是否满足allMatch(e->predictea(e)| | predicteb(e)| | predictec(e))。但是否可以检查所有元素是否满足其中一个谓词(任意一个)?在前一种情况下,可能有些元素满足A,有些元素不满足,但它们满足B或C(反之亦然) 我可以多次执行allMatch,但是流将被终止,我需要重复最初的操作 我还可以设计一个复杂的r

使用流API,我可以使用
allMatch(e->predicate(e))
方法轻松检查所有元素是否满足给定条件。我还可以检查多个条件中的任何一个是否满足
allMatch(e->predictea(e)| | predicteb(e)| | predictec(e))
。但是否可以检查所有元素是否满足其中一个谓词(任意一个)?在前一种情况下,可能有些元素满足A,有些元素不满足,但它们满足B或C(反之亦然)

我可以多次执行
allMatch
,但是流将被终止,我需要重复最初的操作

我还可以设计一个复杂的reduce操作,但是当结果明显为假时(就像
allMatch
方法那样),它将无法提前停止

我可以执行此操作两次,但是流将被终止,我需要重复最初的操作

如果您打算仅在检查条件后处理元素,则无论如何都必须缓冲流,因为只有在遍历所有元素后才能检查条件


因此,您可以选择两次生成流或将其放入一个集合中。

这里有一种可能的方法,可以返回到对流元素使用简单的
迭代器(因此它没有并行支持,但适用于任何类型和任何数量的谓词)

它创建一个初始的
位集
,其大小与给定谓词的长度相同,所有位都设置为
true
,每次检索下一个元素时,我们都会清除(设置为
false
)不匹配的谓词索引。因此,在每个索引处,位集将包含该谓词到目前为止是否都与流的元素匹配。它是短路,因为它循环直到有元素剩余,并且位集不是空的(这意味着到目前为止仍然存在所有匹配元素的谓词)


如果我们想保持并行支持,我们可以从库中获得帮助,该库具有
筛选
首先
配对
收集器。我们重用
anyMatching
收集器


您可以采用的迭代解决方案创建一个功能性解决方案,该解决方案不是短路,而是并行工作:

@SafeVarargs
private static <T> boolean allMatchOneOf(Stream<T> stream, Predicate<T>... predicates) {
    int length = predicates.length;
    return stream.collect( () -> new BitSet(length),
    (bitSet,t) ->
      IntStream.range(0, length).filter(i -> !predicates[i].test(t)).forEach(bitSet::set),
    BitSet::or).nextClearBit(0)<length;
}
@SafeVarargs
私有静态布尔allMatchOneOf(流、谓词…谓词){
int length=谓词.length;
返回stream.collect(()->新位集(长度),
(位集,t)->
IntStream.range(0,length).filter(i->!谓词[i].test(t)).forEach(位集::集),
位集::或.nextClearBit(0)新位集(长度),
(位集,t)->{

对于(int bit=bitSet.nextClearBit(0);bit不完全正确。
Stream.of(“一”、“二”、“三”).peek(e->System.out.println(e)).allMatch(e->e.equals(“一”);
将导致打印“一”和“二”,因为第二个元素的条件将失败。元素“三”未处理。您所观察到的只是当前行为,API不能保证这一点,因此这不是我建议的解决方案。它不能保证这一点,因为它取决于确切的谓词以及源流是否无限。但这是一个短路终端操作,如果没有必要()。有时还允许在有限的时间内处理无限的流。我想我们可能在讨论不同的事情。在检查流的所有元素是否满足一个条件后,您是否真的要使用流的内容?是的,但为了检查条件,我需要预处理每个元素。因此,如果在处理前几个元素后,每个谓词至少有一个失败,因此无需进一步处理-立即返回false将是有效的。在这个问题中,Tagir Valeev的解决方案可能是短路:@RadosławŁazarz该问题涉及两个相反的谓词,例如yes,但有些答案更为笼统。塔吉尔·瓦列夫的答案的第二部分更为笼统,适用于任何两个谓词。在那篇文章中,它也更为笼统、简单,但缺乏并行支持。我不太明白你到底想实现什么。你能写出你如何解决这个问题吗?运行
allMatch
multiple times,看看有没有办法简化它?@StuartMarks:据我所知,目标是做
foos.stream().allMatch(谓词1)| foos.stream().allMatch(谓词2)
不创建两个流并保持短路行为。请注意,如果将
StreamEx
流用作输入,则由
AllMatchingOnof
创建的采集器实际上应该短路。将与非StreamEx流的正常采集器一样工作。
// false because not all elements are either even or divisible by 3
System.out.println(allMatchOneOf(Stream.of(2, 3, 12), i -> i % 2 == 0, i -> i % 3 == 0));

// true because all elements are divisible by 3
System.out.println(allMatchOneOf(Stream.of(3, 12, 18), i -> i % 2 == 0, i -> i % 3 == 0));
import static one.util.streamex.MoreCollectors.*;

@SafeVarargs
static <T> Collector<T, ?, Boolean> allMatchingOneOf(Predicate<T> first, Predicate<T>... predicates) {
    Collector<T, ?, Boolean> collector = allMatching(first);
    for (Predicate<T> predicate : predicates) {
        collector = pairing(collector, allMatching(predicate), Boolean::logicalOr);
    }
    return collector;
}

static <T> Collector<T, ?, Boolean> allMatching(Predicate<T> pred) {
    return collectingAndThen(anyMatching(pred.negate()), b -> !b);
}

static <T> Collector<T, ?, Boolean> anyMatching(Predicate<T> pred) {
    return collectingAndThen(filtering(pred, first()), Optional::isPresent);
}
// false because not all elements are either even or divisible by 3
System.out.println(Stream.of(2, 3, 12).collect(allMatchingOneOf(i -> i % 2 == 0, i -> i % 3 == 0)));

// true because all elements are divisible by 3
System.out.println(Stream.of(3, 12, 18).collect(allMatchingOneOf(i -> i % 2 == 0, i -> i % 3 == 0)));
@SafeVarargs
private static <T> boolean allMatchOneOf(Stream<T> stream, Predicate<T>... predicates) {
    int length = predicates.length;
    return stream.collect( () -> new BitSet(length),
    (bitSet,t) ->
      IntStream.range(0, length).filter(i -> !predicates[i].test(t)).forEach(bitSet::set),
    BitSet::or).nextClearBit(0)<length;
}
@SafeVarargs
private static <T> boolean allMatchOneOf(Stream<T> stream, Predicate<T>... predicates) {
    int length = predicates.length;
    return stream.collect( () -> new BitSet(length),
        (bitSet,t) -> {
            for(int bit=bitSet.nextClearBit(0); bit<length; bit=bitSet.nextClearBit(bit+1))
                if(!predicates[bit].test(t)) bitSet.set(bit);
        },
        BitSet::or).nextClearBit(0)<length;
}
@SafeVarargs
private static <T> boolean allMatchOneOf(Stream<T> stream, Predicate<T>... predicates) {
    int length = predicates.length;
    BitSet bitSet = new BitSet(length);
    bitSet.set(0, length);
    for(Iterator<T> it = stream.iterator(); it.hasNext() && !bitSet.isEmpty(); ) {
        T t = it.next();
        for(int bit=bitSet.nextSetBit(0); bit>=0; bit=bitSet.nextSetBit(bit+1))
            if(!predicates[bit].test(t)) bitSet.clear(bit);
    }
    return !bitSet.isEmpty();
}