Java中形成与谓词集合匹配的对象集合的最快方法是什么?
考虑一个对象集合和一个谓词集合,形成谓词集合对象对的最快方式是什么,其中每对都是一个对象和一个返回true的谓词 此外,对象在对之间必须是唯一的,但这不适用于谓词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
即考虑对象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());