簡體   English   中英

Java:如何使用大量謂詞過濾大量對象?

[英]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) ...
    }

}

在這種情況下,與操作本身的復雜性相比,您無能為力。 如果條目很多,謂詞很多,謂詞很貴,那么你可以盡可能快地進行優化,但是你肯定不會超過某個閾值,因為這里的單個操作可能很昂貴。

您應該測試不同的方法,看看在特定情況下表現更好的方法:

  • 排序謂詞首先檢查應該更寬的謂詞(這樣第一個謂詞將過濾掉盡可能多的條目)
  • 根據它們的復雜性對謂詞進行排序(因此首先執行速度更快,而在較少的條目中執行速度較慢)
  • 不要更新原始數據結構,而是保留包含已過濾元素vs的並行集
  • 始終更新數據結構,以便您每次都可以遍歷少量人員

這是另一種選擇:識別類實例可能具有的所有可能屬性。 在您的示例中,您有一個具有兩個屬性的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM