2010-02-01 69 views
6

返回Java集合的最佳方式是什麼?java:返回集合

我應該允許調用者提供一個集合添加到?或者只是返回一個List<>Set<>的項目?或兩者?

public class Item { ... } 

public class SomeOtherClass 
{ 
    private List<Item> myItems; 

    public List<Item> getItems() 
    { 
    return Collections.unmodifiableList(this.myItems); 
    } 
    public void collectItems(Collection<? super Item> target) 
    { 
    target.addAll(myItems); 
    } 
} 

注:上面的例子假設可以立即返回一個列表的前生。當這樣的列表先前不存在,並且當調用者調用getItems()或collectItems()時,我也會對這個列表產生興趣。 (我已經根據Mykola提出的觀點重新命名了collectItems。)

+0

+1表示Collections.unmodifiableList。正是我在找的東西。 – Adam 2010-07-01 15:34:01

回答

6

我只是更喜歡List<Item> getItems()方法。 void getItems(Collection<? super Item> target)對於調用者只是在執行myCollection.addAll(foo.getItems())表現或其他方面沒有真正的優勢。 Collections.unmodifiableXYZ只創建一個包裝器,而不是集合的完整副本,所以如果包裝器被立即使用並被丟棄,它將永遠不會從第一代產生出來,並且會很快收集,而且開銷很小。

如果物品的集合並不總是可實現的,那麼當您不知道有多少物品時,可能會考慮讓getItems返回Iterable<Item>。如果你知道項目的數量並且可以爲它們編寫一個迭代器,那麼編寫一個AbstractCollection的自定義子類很容易並返回它。

+1

用於提及迭代器的+1 – 2010-02-01 16:54:36

12

通過return返回結果中的函數會更好(除非有一些性能問題)。這樣就更清楚發生了什麼事情。

如果您選擇第二個選項(填充客戶端集合),那麼最好將getItems的函數重命名爲fillWithItems以避免模糊代碼。

另外不要忘記JavaBeans及其約定。

+0

+1用於提示重命名。 – 2010-02-01 16:44:16

0

您應該返回一個集合。在Java中這是比使用輸入/輸出參數更常用的方法。我沒有看到任何理由會有返回一個大集合的性能損失,它會更簡潔的代碼。

+2

處罰是爲了使你迴歸的東西不可變。 – 2010-02-01 16:46:54

+0

因此,返回集合的副本或克隆。不會比將收藏複製到用戶創建的收藏更少。 – Casey 2010-02-01 17:23:03

0

鑑於Java的工作方式,您通常會期望返回版本。

但是,如果您需要控制創建何種類型的集合,那麼您將執行將其作爲參數傳遞給它的版本。

通常,任何事情都不應該關心創建什麼類型的集合,所以你通常應該使用返回版本。順便利用不可修改列表。

0

注意:返回一個Set並返回一個List有不同的含義。

一組沒有重複,也沒有明確的順序。將元素添加到集合可能會導致元素的順序不同。

列表可能包含重複項,並且添加元素不會(通常)更改列表的整體順序。

至於如何返回列表,我將使用第一種形式:

public List<Item> getItems() 
{ 
    return Collections.unmodifiableList(this.myItems); 
} 

我想不出的情況下,後者的形式是任何好處。 List不像一個數組,其中可以預先分配空間。因此,通過列表並沒有節省性能。

+0

如果我將幾個集合集合在一起,並且每個集合都可以有10,000個項目,我寧願將目標集合傳遞到它的位置。或者,如果集合的類型很重要(集合與列表)並且有大量項目。 – 2010-02-01 17:40:52

0

我可以想到填充現有集合而不是創建新集合的唯一原因是當您在集合中的對象類型有問題時。就像Java庫toArray(Object [] a)函數一樣,程序在編譯時並不知道數組元素的適當類型是什麼,所以它不能僅僅返回。一個String []。所以相反,它們將調用者傳遞給一個數組,其中包含相應類型的元素,並且它們會填充該元素。

90%的時間你知道你想要返回什麼類型的對象,所以你可以做到這一點。

0

您可以更改簽名以返回Collection或Iterable。爲了返回Iterable,可以直接返回一個新的Iterable(myItems.iterator())而不是myItems,以避免客戶端試圖轉換爲List(並修改它)。如果你不想讓他們修改List,還可以考慮返回一個Iterator,但是請注意,Iterable更好,因爲你可以直接在for-each循環中使用它們。

返回Iterable既清楚你的意圖,在上面的例子中,防止修改。唯一的含義是你已經失去了隨機存取,這可能會或可能不會成爲你需要的問題。

+0

鑑於Iterable是一個接口,'new Iterable(myItems.iterator())'是不合法的;你的意思是別的嗎? – 2010-02-02 00:27:49

+0

是的哎呀,你將不得不返回一個實現它的新的匿名類(或默認的Iterable)。 – GreenieMeanie 2010-02-02 16:07:01