![](/img/trans.png)
[英]Convert ArrayList<ArrayList<Integer>> to List<List<Integer>>
[英]Difference between ArrayList<Integer> list = new ArrayList<Integer>(); and Collection<Integer> list1 = new ArrayList<Integer>();
我不明白以下之間的區別:
ArrayList<Integer> list = new ArrayList<Integer>();
Collection<Integer> list1 = new ArrayList<Integer>();
類ArrayList
擴展類,它實現的接口Collection
,因此類ArrayList
實現Collection
接口。 也許list1
允許我們使用Collection
接口中的靜態方法?
接口沒有靜態方法 [在 Java 7 中]。 list1
只允許訪問Collection
的方法,而list
允許訪問ArrayList
所有方法。
最好使用其最不特定的可能類型聲明變量。 因此,例如,如果出於任何原因將ArrayList
更改為LinkedList
或HashSet
,則不必重構大部分代碼(例如,客戶端類)。
想象一下你有這樣的東西(僅用於說明目的,不可編譯):
class CustomerProvider {
public LinkedList<Customer> getAllCustomersInCity(City city) {
// retrieve and return all customers for that city
}
}
然后你決定實現它返回一個HashSet
。 也許有一些客戶端類依賴於您返回LinkedList
的事實,並調用HashSet
沒有的方法(例如LinkedList.getFirst()
)。
這就是為什么你最好這樣做:
class CustomerProvider {
public Collection<Customer> getAllCustomersInCity(City city) {
// retrieve and return all customers for that city
}
}
我們在這里處理的是interface和implementation之間的區別。
接口是一組方法,不考慮這些方法是如何實現的。 當我們將一個對象實例化為具有實際上是interface
的類型時,我們所說的是它是一個實現該interface
所有方法的對象……但不提供對任何interface
訪問class
中實際提供這些實現的方法。
當你實例與實施的類型的對象class
,那么你就可以訪問所有這一切的相關方法class
。 由於class
正在實現interface
,您可以訪問接口中指定的方法,以及實現類提供的任何額外功能。
你為什么想做這個? 好吧,通過將對象的類型限制為interface
,您可以切換新的實現而無需擔心更改其余代碼。 這使它變得更加靈活。
正如其他人所說,不同之處在於,當您將Collection
接口指定為變量類型時,您只能使用Collection
接口定義的方法。 但這並不能回答您為什么要這樣做的問題。
原因是數據類型的選擇為使用代碼的人提供了信息。 特別是用作函數的參數或返回類型時(外部程序員可能無法訪問內部結構)。
按照具體順序,以下是不同類型選擇可能會告訴您的信息:
Collection
- 一組對象,沒有進一步的保證。 這個對象的使用者可以迭代集合(不保證迭代順序),並且可以了解它的大小,但不能做任何其他事情。List
- 一組具有特定順序的對象。 當您迭代這些對象時,您將始終以相同的順序獲得它們。 您還可以通過索引從集合中檢索特定項目,但您不能對此類檢索的性能做出任何假設。ArrayList
- 一組具有特定順序的對象,可以在恆定時間內通過索引訪問。盡管您沒有詢問它們,但這里有一些其他集合類:
Set
一組保證每個equals()
方法不包含重復項的對象。 無法保證這些對象的迭代順序。SortedSet
一組不包含重復項的對象,並且將始終以特定順序迭代(盡管集合不保證該特定順序)。TreeSet
一組沒有重復的有序對象,表現出O(logN)
插入和檢索時間。HashSet
一組沒有重復的對象,沒有固有的順序,但提供(攤銷)恆定時間訪問。唯一的區別是您通過 Collection 接口提供對 list1 的訪問,而您通過 ArrayList 接口提供對 list2 的訪問。 有時,通過受限制的接口提供訪問是有用的,因為它促進了封裝並減少了對實現細節的依賴。
當您對“list1”執行操作時,您將只能從 Collection 接口訪問方法(get、size 等)。 通過將“list”聲明為 ArrayList,您可以訪問僅在 ArrayList 類中定義的其他方法(例如,ensureCapacity 和 trimToSize。
將變量聲明為您需要的最不具體的類通常是最佳實踐。 因此,如果您只需要 Collection 中的方法,請使用它。 通常在這種情況下,這意味着使用 List,它讓您知道它是有序的並且可以處理重復項。
使用最不具體的類/接口允許您以后自由更改實現。 例如,如果您后來了解到 LinkedList 將是一個更好的實現,那么如果您將變量定義為 List,則可以在不破壞所有代碼的情況下更改它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.