2012-02-07 28 views

回答

0

要使用最少量的做到這一點更改代碼,只需添加一個if語句來檢查,看看是否要追加的東西已經在toReturn

if (!first) 
    toReturn.append(", ") ; 
first = false; 
toReturn.append(values.next().toString()); 

被改爲

String v = values.next().toString() 
if (toReturn.indexOf(v) == -1) { // indexOf returns -1 if it is not there 
    if (!first) { 
     toReturn.append(", ") ; 
    } 
    toReturn.append(v); 
    first = false 
} 

上述溶液是有點慢,因爲它具有每一次,看是否該字符串是有遍歷整個字符串。可能最好的方法是使用HashSet來收集項目,然後將HashSet中的值合併爲最終輸出字符串。

+0

非常感謝你的魅力! – James 2012-02-07 19:57:50

1

那麼你想刪除已映射的副本,即你想減少中間值列表到輸出列表沒有重複。我最好的選擇是簡單地在reduce()方法轉換Iterator<Text>到Java Set和遍歷它改變:

while (values.hasNext()) { 
    if (!first) 
    toReturn.append(", ") ; 
    first = false; 
    toReturn.append(values.next().toString()); 
} 

喜歡的東西:

Set<Text> valueSet = new HashSet<Text>(); 
while (values.hasNext()) { 
    valueSet.add(values.next()); 
} 

for(Text value : valueSet) { 
    if(!first) { 
     toReturn.append(", "); 
    } 
    first = false; 
    toReturn.append(value.toString()); 
} 

不幸的是,我不知道有什麼好(更簡潔)將Iterator轉換爲Set的方法。

這應該比橙色的解決方案具有更小的時間複雜度,但是會消耗更多的內存。

@Edit:短一點:

Set<Text> valueSet = new HashSet<Text>(); 
while (values.hasNext()) { 
    Text next = values.next(); 
    if(!valueSet.contains(next)) { 
     if(!first) { 
      toReturn.append(", "); 
     } 
     first = false; 
     toReturn.append(value.toString()); 
     valueSet.add(next); 
    } 
} 

包含應(就像補充)固定的時間,所以應該是O(n)的現在。

+0

您的解決方案就是我在回答結束時提出的建議,並且是最佳解決方案。實際上,我們的空間複雜度是相同的,因爲我必須在將結果寫出之前將結果緩存到StringBuffer中。 – 2012-02-07 20:30:18

+0

是的,但我也有那個StringBuilder(因爲這是我們實際返回),但我也有存儲唯一結果的集合。我想我們也可以通過在「while」外觀中添加所有內容並添加一個簡單的if/else檢查來優化它。問題是什麼會更快:如果在while循環的每一步或第二個for循環中多加一個。 – 2012-02-07 20:37:22

+0

在Hadoop的宏偉計劃中可能無所謂:) – 2012-02-07 20:40:50