使用List或Collection更好吗?

时间:2010-05-26 23:46:57

标签: java list collections abstraction

我有一个对象,它将一些数据存储在列表中。实现可能会在以后更改,我不希望将内部实现公开给最终用户。但是,用户必须能够修改和访问此数据集。目前我有这样的事情:

public List<SomeDataType> getData() {
   return this.data;
}

public void setData(List<SomeDataType> data) {
   this.data = data;
}

这是否意味着我已允许内部实施细节泄漏?我应该这样做吗?

public Collection<SomeDataType> getData() {
   return this.data;
}

public void setData(Collection<SomeDataType> data) {
   this.data = new ArrayList<SomeDataType>(data);
}

8 个答案:

答案 0 :(得分:25)

这取决于,您是否希望您的用户能够索引数据?如果是,请使用List。两者都是接口,因此您不会泄漏实现细节,实际上,您只需要确定所需的最低功能。

答案 1 :(得分:16)

返回列表符合最高适合接口的编程。

返回集合会导致用户不明确,因为返回的集合可能是:Set,List或Queue。

答案 2 :(得分:9)

独立于通过List.get(int)索引到列表的能力,用户(或您)是否期望集合的元素处于可靠且可预测的顺序?该集合可以具有相同项目的倍数吗?这些都是对更常见集合不常见的列表的期望。这些是我在确定向最终用户公开哪个抽象时使用的测试。

答案 3 :(得分:8)

当返回高层次结构中的接口或类的实现时,经验法则是声明的返回类型应该是最高级别,它提供了您准备向调用者保证的最小功能,以及呼叫者合理需要。例如,假设您真正返回的是ArrayList。 ArrayList实现了List和Collection(以及其他功能)。如果您希望调用者需要使用get(int x)函数,那么它将无法返回Collection,您需要返回List或ArrayList。只要你没有看到任何理由为什么你会改变你的实现以使用除列表之外的东西 - 比如说Set - 那么正确的答案就是返回一个List。我不确定ArrayList中是否有任何函数不在List中,但如果存在,则会应用相同的推理。另一方面,一旦返回List而不是Collection,您现在已经在某种程度上锁定了您的实现。您放入API的次数越少,对未来改进的限制就越少。

(在实践中,我几乎总是在这种情况下返回一个List,它从来没有烧过我。但我可能真的应该返回一个Collection。)

答案 4 :(得分:5)

使用最常用的类型(即Collection)是最有意义的,除非有明确的理由使用更具体的类型 - List。但无论你做什么,如果这是一个供公众消费的API,请在文档中明确说明它的作用;如果它返回集合的浅表副本,请说明。

答案 5 :(得分:1)

是的,如果不是接口合同的一部分,那么您的第一个替代方案会泄漏实现细节,该方法将始终返回List。此外,允许用户代码替换您的集合实例有点危险,因为它们传入的实现可能不会像您期望的那样。

当然,这完全取决于您对用户的信任程度。如果你采用Python哲学“我们都同意成年人”,那么第一种方法就好了。如果您认为您的图书馆将由没有经验的开发人员使用,您需要尽一切可能“照看”他们并确保他们没有做错事,那么最好不要让他们设置集合而不是甚至不返回实际的集合。而是返回它的(浅)副本。

答案 6 :(得分:0)

如果我担心将数据的内部表示模糊到外部用户,我会使用XML或JSON。无论哪种方式,它们都相当普遍。

答案 7 :(得分:0)

这取决于您希望为用户提供什么保证。如果数据是连续的,使得元素的顺序很重要并且您允许重复,那么使用列表。如果元素的顺序无关紧要并且可能允许或不允许重复,则使用集合。由于您实际上正在返回底层集合,因此您不应该同时具有get和set函数,只能使用get函数,因为返回的集合可能会发生变异。此外,提供set函数允许用户更改集合类型,而您可能希望由您控制特定类型。