有人打破了我对列表的排序 - 现在选择哪种方法:返回不可修改的List或一个新的List?

时间:2012-10-29 13:55:28

标签: java list sorting unmodifiable

我在jsf网络服务器上使用列表,例如从网页访问数据模型。访问这些列表也可以从其他各个地方完成(Web服务,工具)。

有一段代码被某人诉诸我返回的列表所打破。有人在我的开发团队中谈论某人 - 我们是唯一使用此代码的人。我有大约300个关于这个函数的引用,它可能与性能相关很好地修复:

列表可以是1到10,000个条目,通常我可能有10到100个这样的列表。实际上,我可能经常会有大约20个列表,每个列表有8个条目 - 所以不是很重要。但有时我可以有更多

我正在谈论类似这样的函数:

public List<MyObject> getMyObjectList() {
    if (this.myObjects== null) {
        myObjects = new ArrayList<MyObject>(myObjectsMap.values());
    }
    return myObjects;
}

现在我当然可以像这样做回报:

    public List<MyObject> getMyObjectList() {
        if (this.myObjects== null) {
            myObjects = new ArrayList<MyObject>(myObjectsMap.values());
        }
        return Collections.unmodifiableList(myObjects );
}

但这会破坏,最终会在不同的项目/应用程序的几个地方。 这将是最不可能恢复不可修改的,添加javadoc - 并修复所有破坏的东西。但是:-这是工作。我可能要测试大约10个应用程序。

另一方面,我可以返回一个新列表,例如

public List<MyObject> getMyObjectList() {
    return new ArrayList<MyObject>(myObjectsMap.values());
}

这对于小工作来说是不对的 - 但是这与性能问题有关呢?除此之外 - 如果有人从我返回的列表中删除了东西,它将默默地破坏该应用程序。

所以: 性能问题是什么?这是一个问题吗?

你会做什么?

2 个答案:

答案 0 :(得分:2)

  

你会做什么?

如果我理解正确,这是一个在多个应用程序中使用的生产库。而且,无论喜欢与否,getMyObjectList()的事实上的合同是用户可以对列表进行排序而不会出现错误或异常。

我会立即更改此方法并返回防御副本:

// good idea
public List<MyObject> getMyObjectList() {
    return new ArrayList<MyObject>(myObjectsMap.values());
}

您现在已经解决了有人正在对您的内部集合进行排序并且您没有违反合同的问题。实际上,您甚至可以更新Javadoc并告诉用户他们可以随副本执行任何操作。

这可能会也可能不会导致性能问题。请记住,集合中的对象没有被复制 - 它们仍然被共享。您只是创建一个新的数组列表以及跟踪对象所需的任何内部对象。

如果事实证明这些副本导致性能问题,那么您可以考虑增强您的类以包含内部集合的只读缓存。要访问此方法,您必须为方法指定一个新名称 - ex getMySharedObjectList,然后您可以逐步更新客户端代码,以便根据性能需求使用此新方法。

但不要这样做。我认为这种方法特别糟糕:

// bad idea
public List<MyObject> getMyObjectList() {
    if (this.myObjects== null) {
        myObjects = new ArrayList<MyObject>(myObjectsMap.values());
    }
    return Collections.unmodifiableList(myObjects );
}

您创建了一种情况,即myObjects很容易与myObjectsMap不同步。 (在有人调用getMyObjectList之后将项目添加到myObjectsMap 时会发生什么?)同时,每次有人调用该方法时,您都会复制该列表。所以你只是放弃了你最初获得的理论性能提升。

无论如何,祝你好运。希望这会有所帮助。

答案 1 :(得分:0)

如果你有能力测试应用程序,我会使用unmodifiableList。它将在未来帮助您避免其他相关问题。