[英]Java: How to filter a big collection of objects with a big collection of predicates?
在Java中,我有Set<Person> cityInhabitants
對象(~10,000個對象) ,比如Set<Person> cityInhabitants
。 我還有一個大的謂詞集合(~1,000個謂詞) ,它們將用於過濾掉任何與這些謂詞匹配的Person
。 例如,謂詞可能是
person.getName().equals("ugly name1")
person.getName().equals("ugly name2")
person.getAge() < 18
。 此要求需要以下挑戰:
這些挑戰有哪些解決方案? 有沒有可以幫助的圖書館?
我建議你按照執行速度的順序對謂詞進行排序。 然后,您可以按速度順序執行謂詞,首先使用最快的謂詞,通常意味着較慢的謂詞必須在較小的集合上運行。
但是,這種假設並不完全正確,您需要計算出被刪除的謂詞百分比以便執行速度。 然后我們可以看到哪個是移除最高百分比對象的最快謂詞。 然后我們可以按此順序執行謂詞給我最優化。
您可以輕松實現自己的謂詞interface
public interface Predicate<T> {
boolean filter(T object);
}
然后,您需要為每個規則創建謂詞對象。 您可以為年齡和名稱檢查創建一些更動態的類,這將減少您還需要的代碼量。
public class AgeCheck<T> implements Predicate<T> {
private final int min;
private final int max;
public AgeCheck(int min, int max) {
this.min = min;
this.max = max;
}
@Override
public boolean filter(T object) {
// if( t.age() < max && t.age > min) ...
}
}
在這種情況下,與操作本身的復雜性相比,您無能為力。 如果條目很多,謂詞很多,謂詞很貴,那么你可以盡可能快地進行優化,但是你肯定不會超過某個閾值,因為這里的單個操作可能很昂貴。
您應該測試不同的方法,看看在特定情況下表現更好的方法:
這是另一種選擇:識別類實例可能具有的所有可能屬性。 在您的示例中,您有一個具有兩個屬性的person
類; 姓名和年齡。 因為你有這些屬性的getter,所以最多一個person
可能有兩個屬性(除非你沒有提到其他的getter)。 您可以實現person
,使屬性保存在集合中,這樣您就可以對屬性數量進行限制。 無論如何實現,都要確定所有屬性。
現在,每一個屬性,關聯獨特的素數,然后為每個實例person
保持與分配給這些屬性的素數的乘積person
。 例如,假設一個人可以是年輕人或老年人,男性或女性,外表美觀或不好看。 這是6個屬性,讓我們按如下方式分配素數:
02: young
03: old
05: male
07: female
11: good looking
13: bad looking
繼續這個例子,假設一個人是一個好看的年輕女性。 素數的乘積為2 X 7 X 11或154。
現在你想要找到所有漂亮的年輕人,不分性別。 與該謂詞相關的素數的乘積是2 X 11或22。
所以,你現在可以通過所有的迭代people
,如果與各相關素數的乘積people
可以通過22沒有任何剩余部分(它可以在其中的情況下被划分person
與質數的積為154),那么你有一個匹配。
您可能希望使用BigNumber類來執行乘法,除法和素數乘積的存儲。
如果給一個person
並且詢問它是否與所有謂詞匹配,那么這個解決方案非常快(同樣,謂詞已經被簡化為唯一素數,而謂詞集合現在由這些素數的乘積表示)。
如果你必須遍歷尋找匹配的整個people
這個解決方案可能不會那么快。
( 我沒有意識到這個問題已經過了2年。我在這個派對上已經很晚了!知道作者最終使用了什么解決方案會很好。 )
有沒有可以幫助的圖書館? 好吧,確定有!
您的數據收集不是很大,但是您的謂詞數量不成比例。 此外,您希望這些謂詞由您的用戶管理,並集中存儲等。這聽起來非常適合Drools ,這是一個規則引擎,並附帶了額外的工具來創作,驗證和存儲這些規則。
但是Drools可能很大而且參與其中。 也許你需要更簡單的東西? 您的代碼示例和您對速度的第一個要求讓我想到了CQEngine ,它是一個用於索引對象的庫。 它索引字段(例如您的'名稱字段),它可以以各種方式搜索這些字段(等號,開頭,包含等)。 它很快而且很簡單,但它只能索引。 您自己必須提出規則定義等。另一方面,CQEngine支持邏輯謂詞,因此您可以將謂詞鏈接到和/或。
還有其他用於規則引擎或對象索引的庫。 我相信其他人會在答案中列出他們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.