2009-11-07 47 views
1

我正在連接到非常不靈活的套接字API。它會返回如下行:數組中項目的Java計數(類似於SQL聚合函數)

NAME, CITY, STATE, JOB, MONTH 

但會有重複,因爲它不會做任何聚合。我需要計算重複的行(這在SQL中非常簡單,但據我所知,在Java中不是那麼容易)。

示例源數據:

NAME,  CITY, STATE, JOB,   MONTH 
John Doe, Denver, CO, INSTALLATION, 090301 
John Doe, Denver, CO, INSTALLATION, 090301 
John Doe, Denver, CO, INSTALLATION, 090301 
Jane Doe, Phoenix, AZ, SUPPORT, 090301 

預期:

NAME, CITY, STATE,   JOB, MONTH, COUNT 
John Doe, Denver, CO, INSTALLATION, 090301, 3 
Jane Doe, Phoenix, AZ,  SUPPORT, 090301, 1 

我可以很容易地做到這一點的約10萬回行,但我處理在一個月約60萬美元。有任何想法嗎?

編輯:不幸的是,行不返回的有序......也沒有通過API的選項排序。我得到了這些需要彙總的東西。現在我使用一個ArrayList並執行indexOf(新行)來查找該項是否已經存在,但是它的行越多,它越慢。

編輯:爲了澄清,這將只需要每個月運行一次,在月底。感謝您對所有的答覆

回答

3

您可以使用HashSet來存儲具有相同內容的前一行。 (假設你的行對象有適當.hashValue()和.equals()方法來實現

這樣的事情也許:

Set<Row> previousRows = new HashSet<Row>(); 
List<Row> rowsInOrder = new LinkedList<Row>(); 

然後使用(進一步假設你有一個incrementCount()方法該行類):

Row newRow = getNextRow(); 
if(!previousRows.contains(newRow)){ 
    previousRows.put(newRow); 
    rowsInOrder.add(newRow); 
} 
previousRows.get(newRow).incrementCount(); 

如果你不關心這些行進來的順序,你可以擺脫名單,只是使用Set

+0

幾乎正是我想要建議的。 – 2009-11-07 04:27:35

+0

考慮到OP需要處理的數據集的大小,將所有行存儲在「HashSet」中可能會導致出現OutOfMemoryException。 – Asaph 2009-11-07 04:30:56

+0

我會在星期一嘗試這個......看起來就像我在找什麼。我最大的問題是它的速度變慢了...... HashSet應該快得多...... – jle 2009-11-07 04:53:39

1

的你有靈活性,或者這是一個足夠重要的東西投資像Hadoop任務?有了這樣大小的數據,你就想要從「地圖縮減」的思維角度開始思考它。

0

行是否總是返回排序?即。被分組的行是否總是一個接一個地返回?如果答案是肯定的:

1)初始化一個計數器。

2)跟蹤的上一行,你剛纔讀,並將其與當前行的。如果相同,請增加計數器。如果不同,請使用當前計數器值記錄您的行並重置計數器。

3)當你到達最後一條記錄,確保將當前計數記錄行。

這一戰略將讓你在大型數據集讀取流,並保持你的程序的內存佔用低,同時產生你以後更緊湊的彙總數據。

1

你是AB型。一次將所有數據放入內存中?如果你把它放在一個ArrayList中,它聽起來像你可以。

如果是這樣的話,你可以只使用多集的一種實現,如一個在Google collections

然後,你可能只是做你的行插入多集如下

Multiset<Row> rowMultiset = HashMultiset.create(); 
for (Row row: rows) { 
    rowMultiset.add(row); 
} 

你可以遍歷,具有計數,使用類似:

for (Multiset.Entry entry : rowMultiset.entrySet()) { 
    System.out.println("row: "+entry.getElement()+", count: "+entry.getCount()); 
} 

如果你不想使用外部庫,你可以做一些事š同樣使用HashMap將行映射到整數。

如果不是所有的行都適合內存,我認爲最簡單的方法就是將數據插入數據庫並執行查詢。數據庫針對不適合內存的大型數據集進行設計和優化。

0

我能想到的四種方式來做到這一點:

  • 如果你有足夠的內存來保存在內存中6000萬行表示(少重複),使用HashMap<Row, Integer>代表計數。

  • 將行存儲在RDB中,然後使用SQL進行聚合和計數。

  • 將行寫入一個大文件並使用傳統合並對它進行排序,然後再單次統計 行。

  • 使用類似Hadoop的東西在多臺機器上傳播行。

你期望在一個月或更長週期進行累積計數的事實表明,你需要考慮你的應用程序將需要重新啓動的可能性。這表明需要RDB或基於文件的解決方案。