2015-02-06 72 views
5

我被聲納拉昇,由於下面的代碼行:什麼接口代表的插入順序LinkedHashSet迭代

public void setFileNames(LinkedHashSet<String> fileNames) { 

隨着錯誤消息:

避免使用實施類型,如'LinkedHashSet';使用接口,而不是

當我想要表示一個不分類的Set保持其插入順序時,這種方式是什麼?我只是使用Set並明確指出迭代順序會保留嗎?

存儲的數據將使用JaxB進行序列化,迭代順序在反序列化後非常重要。

(我知道的和完全理解this

+0

你會從方法中讀取數據,向數據集中添加條目嗎? – WilQu 2015-02-06 15:27:26

回答

3

沒有這樣的interface,因爲對輸入要求這種行爲是沒有意義的。代碼創建 a Set可能有關於訂單的意圖,並在創建Set時選擇適當的實施。

但是,Set是否有插入順序,字母順序或任意的問題基於哈希,訂單對於像setFileNames(Set<String> fileNames)這樣的方法有所不同?

聲明參數類型爲Set給你保證這不會有這對行爲產生影響的重複,但插入順序是關於歷史上的一個無意義的信息(除非呼叫者使得它有意義)的Set

如果你堅持有一個方法簽名setFileNames(LinkedHashSet<String> fileNames),我仍然可以通過Set無意義的順序,例如,呼叫
setFileNames(new LinkedHashSet<String>(hashSet))或者具有字典順序的集合,例如, setFileNames(new LinkedHashSet<String>(treeSet))。您的簽名使其更加複雜。

+0

我不能和你最後的段落爭論。來電者仍然可以做錯事。然而,你不覺得'LinkedHashSet'和文檔一起爲調用者提供的不僅僅是'Set'和文檔。也許不是。也許在任何一種情況下,他們可能會錯誤(第一次),然後去調試並閱讀文檔,然後最終解決問題。 – 2015-02-06 16:51:00

+0

@邁克爾韋爾奇:問題依然存在,爲什麼該方法的工作應該以任何方式依賴於'插入'順序的'集合'。換句話說,如果'Set'是一個'SortedSet',爲什麼該方法會失敗。我並不是說方法的文檔應該告訴'Set'應該維持插入順序,我說這個方法不應該依賴這樣的屬性。在這方面,考慮你的答案,我想強調'List'不保留*插入*順序,它只是*有*順序,但'List'可以任意地重新排序。 – Holger 2015-02-06 17:09:40

+0

我明白你的意思了。我猜如果訂單很重要,它可以/應該更明確地定義。也許是一組元組,其中一部分元組指定元組落在哪裏。然後,他的方法可以排序或做任何需要的操作,以確保元素按正確的順序訪問。(我想我假設他的實現依賴於已知的迭代順序,也許他正在爲某種排隊建模,我同意不清楚爲什麼「插入順序」很重要。) – 2015-02-06 18:17:09

-1

如果您需要您收到被排序的元素,那麼你的方法應該接受一個列表,而不是設置。但爲了擺脫警告,你必須使用Set而不是LinkedHashSet。在您的方法中使用接口而不是實際的類是一種很好的做法。你不應該暴露一個接口的實際實現。另外,如果您只需要遍歷Set的元素,就可以接收一個迭代器,然後迭代它。

編輯:如果你真的想確保你只收到一個LinkedHashSet,你可以做這樣的事情:

public void setFileNames(Set<String> fileNames) { 
    if (!(fileNames instanceof LinkedHashSet)) { 
     throw new IllegalArgumentException("I need a LinkedHashSet!"); 
    } 
} 

編輯2:我不認爲有一個理想的答案在這裏,但如果你確實需要首先接收LinkedHashSet,我會在界面中聲明它,並找到一種方法讓Sonar忽略該警告的特定實例。

+0

LinkedHashSet也被排序.. – 2015-02-06 14:28:12

+0

您希望排序List接口中的元素。通常對於集合來說這是不正確的。 – 2015-02-06 14:30:17

+0

http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashSet.html。它說有序。 – 2015-02-06 14:33:02

1

我很欣賞其他答案,我也非常感謝Sonar警告。但是,有時(也許在你的情況下)可以忽略警告。在我看來,您正在使用LinkedHashSet來精確定義調用者的責任。設置不會傳達您的要求(訂單未保存)。列表(不保證不同的元素)。所以也許可以忽略這個警告。

另一種方法是,你允許一個List,然後你必須仔細檢查(在你的方法中)列表沒有重複項,如果有的話會拋出異常。這對我來說似乎很荒謬。

正如其他人所說,你應該弄清楚如何在Sonar中抑制警告。希望這個機制能夠包含你抑制它的一個原因。然後你可以向未來的維護者解釋你的決定。

1

只要接受一個Set,讓來電者決定如何實現在傳遞。

其保持其插入順序?

這取決於調用者。 LinkedHashSet在插入時保留訂單基礎,TreeSet保留基於自然順序的訂單。爲什麼你的方法關心如何實現順序?