Java中形成与谓词集合匹配的对象集合的最快方法是什么?

Java中形成与谓词集合匹配的对象集合的最快方法是什么?,java,multithreading,parallel-processing,java-8,predicate,Java,Multithreading,Parallel Processing,Java 8,Predicate,考虑一个对象集合和一个谓词集合,形成谓词集合对象对的最快方式是什么,其中每对都是一个对象和一个返回true的谓词 此外,对象在对之间必须是唯一的,但这不适用于谓词 即考虑对象A、B和C,谓词P1、P2、P3 然而,(A,P1),(B,P1),(C,P2)是一组有效的对 (A,P1)、(A,P1)、(C,P2)是无效的,因为对之间存在重复的对象 因此,一旦谓词与对象匹配,它就有效地拥有它 也就是说,在上述限制条件下,实施以下方法的最快方式是什么: Collection<Pair<Obj

考虑一个对象集合和一个谓词集合,形成谓词集合对象对的最快方式是什么,其中每对都是一个对象和一个返回true的谓词

此外,对象在对之间必须是唯一的,但这不适用于谓词

即考虑对象A、B和C,谓词P1、P2、P3

然而,(A,P1),(B,P1),(C,P2)是一组有效的对 (A,P1)、(A,P1)、(C,P2)是无效的,因为对之间存在重复的对象

因此,一旦谓词与对象匹配,它就有效地拥有它

也就是说,在上述限制条件下,实施以下方法的最快方式是什么:

Collection<Pair<Object,Predicate<Object>> getAllMatches(Collection<Object> objects, Collection<Predicate<Object>>);

Collection您的基准绝对应该是:

final Collection<Pair<Object, Predicate>> getMatches(
        final Collection<Object> objects, 
        final Collection<Predicate> predicates) {
    final Set<Pair<Object, Predicate>> matches = new HashSet<>();
    for (Object o : objects) {
        for (Predicate p : predicates) {
            if (p.test(o)) {
                matches.add(Pair.with(o, p));
                break;
            }
        }
    }
    return matches;
}
final Collection getMatches(
最终收集对象,
最终集合谓词){
final Set matches=新HashSet();
用于(对象o:对象){
for(谓词p:谓词){
如果(p.test(o)){
匹配。添加(与(o,p)配对);
打破
}
}
}
返回比赛;
}
顺序执行通常是最快的。这似乎有悖常理——在多核上运行测试应该是最快的——但对于许多操作来说,您的瓶颈实际上是内存访问。每个处理器都将暂停,什么也不做,同时它将验证它的处理器级缓存是否与所有其他处理器的缓存一致

如果您确信多线程将为您节省一些时间,我建议您进行如下测试:

final Collection<Pair<Object, Predicate>> getMatches(
        final Collection<Object> objects, 
        final Collection<Predicate> predicates) {
    final List<Future<Pair<Object,Predicate>>> futures = new ArrayList<>();
    for (final Object o : objects) {
        futures.add(executorService.invoke(() -> {
            for (Predicate p : predicates) {
                if (p.test(o)) {
                    return Pair.with(o, p);
                }
            }
            return null;
        });
    }
    final Collection<Pair<Object,Predicate>> matches = new ArrayList<>(futures.size());
    for (final Future<Pair<Object,Predicate>> future : futures) {
        final Pair<Object,Predicate> pair = future.get();
        if (pair != null) {
            matches.add(pair);
        }
    }
    return matches;
}
final Collection getMatches(
最终收集对象,
最终集合谓词){
最终列表期货=新的ArrayList();
用于(最终对象o:对象){
futures.add(executorService.invoke)(()->{
for(谓词p:谓词){
如果(p.test(o)){
带(o,p)的返回对;
}
}
返回null;
});
}
最终集合匹配=新的ArrayList(futures.size());
for(最终未来:期货){
最后一对=future.get();
如果(对!=null){
匹配。添加(对);
}
}
返回比赛;
}

没有线程写入共享内存,因此不需要担心锁争用。

您的基准测试绝对应该是:

final Collection<Pair<Object, Predicate>> getMatches(
        final Collection<Object> objects, 
        final Collection<Predicate> predicates) {
    final Set<Pair<Object, Predicate>> matches = new HashSet<>();
    for (Object o : objects) {
        for (Predicate p : predicates) {
            if (p.test(o)) {
                matches.add(Pair.with(o, p));
                break;
            }
        }
    }
    return matches;
}
final Collection getMatches(
最终收集对象,
最终集合谓词){
final Set matches=新HashSet();
用于(对象o:对象){
for(谓词p:谓词){
如果(p.test(o)){
匹配。添加(与(o,p)配对);
打破
}
}
}
返回比赛;
}
顺序执行通常是最快的。这似乎与直觉相反-在多个核上运行测试应该是最快的-但对于许多操作,您的瓶颈实际上是内存访问。每个处理器都会暂停,什么也不做,同时它会验证它的处理器级缓存是否与所有其他处理器一致藏匿处

如果您确信多线程将为您节省一些时间,我建议您进行如下测试:

final Collection<Pair<Object, Predicate>> getMatches(
        final Collection<Object> objects, 
        final Collection<Predicate> predicates) {
    final List<Future<Pair<Object,Predicate>>> futures = new ArrayList<>();
    for (final Object o : objects) {
        futures.add(executorService.invoke(() -> {
            for (Predicate p : predicates) {
                if (p.test(o)) {
                    return Pair.with(o, p);
                }
            }
            return null;
        });
    }
    final Collection<Pair<Object,Predicate>> matches = new ArrayList<>(futures.size());
    for (final Future<Pair<Object,Predicate>> future : futures) {
        final Pair<Object,Predicate> pair = future.get();
        if (pair != null) {
            matches.add(pair);
        }
    }
    return matches;
}
final Collection getMatches(
最终收集对象,
最终集合谓词){
最终列表期货=新的ArrayList();
用于(最终对象o:对象){
futures.add(executorService.invoke)(()->{
for(谓词p:谓词){
如果(p.test(o)){
带(o,p)的返回对;
}
}
返回null;
});
}
最终集合匹配=新的ArrayList(futures.size());
for(最终未来:期货){
最后一对=future.get();
如果(对!=null){
匹配。添加(对);
}
}
返回比赛;
}

没有线程写入共享内存,因此不需要担心锁争用。

使用声明式并行的Java8流的简短解决方案:

Collection<Pair<Object, Predicate<Object>>> getAllMatches(Set<Object> objects, Set<Predicate<Object>> predicates) {
    List<Pair<Object, Predicate<Object>>> pairs = predicates.parallelStream()
        .map(predicate -> new Pair<>(objects.stream().filter(predicate), predicate))
        .flatMap(pair -> pair.a.map(a -> new Pair<>(a, pair.b)))
        .collect(toList());
    return pairs;
}

如果
对象
谓词
不存在重复项,请将
.distinct()
放在
流()或
并行流()后面

使用声明式并行的Java8流的简短解决方案:

Collection<Pair<Object, Predicate<Object>>> getAllMatches(Set<Object> objects, Set<Predicate<Object>> predicates) {
    List<Pair<Object, Predicate<Object>>> pairs = predicates.parallelStream()
        .map(predicate -> new Pair<>(objects.stream().filter(predicate), predicate))
        .flatMap(pair -> pair.a.map(a -> new Pair<>(a, pair.b)))
        .collect(toList());
    return pairs;
}

如果
对象
谓词
不存在重复项,请将
.distinct()
放在
stream()
parallelStream()
后面。我认为您可能过度复杂了一点。对对象进行流处理,并为每个对象找到一个与之匹配的谓词:

objects.stream()    // or parallelStream() for multithreaded
    .distinct()     // can omit this if uniqueness of objects is enforced elsewhere
    .flatMap(obj -> predicates.stream()
        .filter(p -> p.test(obj))
        .map(p -> new Pair<>(obj, p))
        .limit(1)   // one predicate per object
    ).collect(toList());
objects.stream()//或用于多线程的parallelStream()
.distinct()//如果在其他地方强制对象的唯一性,则可以忽略此选项
.flatMap(obj->predicates.stream()
.过滤器(p->p.test(obj))
.map(p->新对(obj,p))
.limit(1)//每个对象一个谓词
).collect(toList());

我认为这可能有点过于复杂了。对对象进行流式处理,并为每个对象找到与之匹配的谓词:

objects.stream()    // or parallelStream() for multithreaded
    .distinct()     // can omit this if uniqueness of objects is enforced elsewhere
    .flatMap(obj -> predicates.stream()
        .filter(p -> p.test(obj))
        .map(p -> new Pair<>(obj, p))
        .limit(1)   // one predicate per object
    ).collect(toList());
objects.stream()//或用于多线程的parallelStream()
.distinct()//如果在其他地方强制对象的唯一性,则可以忽略此选项
.flatMap(obj->predicates.stream()
.过滤器(p->p.test(obj))
.map(p->新对(obj,p))
.limit(1)//每个对象一个谓词
).collect(toList());

为此,您需要编写一些代码。编写一些代码后,如果您有问题,请编辑问题以添加详细信息。一般来说,简单的解决方案(迭代交叉乘积)是唯一的解决方案。在此之前,只需释放集合的副本。您可以通过谓词或对象上的多线程加快速度。@Bohemian当然,我提供了一个
        .collect(toList());
objects.stream()    // or parallelStream() for multithreaded
    .distinct()     // can omit this if uniqueness of objects is enforced elsewhere
    .flatMap(obj -> predicates.stream()
        .filter(p -> p.test(obj))
        .map(p -> new Pair<>(obj, p))
        .limit(1)   // one predicate per object
    ).collect(toList());