Кто-то нарушает мою сортировку списка - теперь какой подход выбрать: вернуть немодифицируемый список или новый список вообще?

Я использую списки на веб-сервере jsf, например, для доступа к модели данных с веб-страниц. Доступ к этим спискам также осуществляется из других мест (веб-сервисы, инструменты).

Есть фрагмент кода, который нарушается кем-то, прибегающим к списку, который я возвращаю. С кем-то я говорю о ком-то из моей команды разработчиков - мы единственные, кто использует этот код. У меня есть около 300 ссылок на эту функцию, и это может быть связано с производительностью, чтобы сделать исправление красиво:

Список может быть где-то от 1 до 10000 записей, и обычно у меня может быть 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 - и исправить все, что сломалось. Но:-D это работа. Вероятно, мне придется протестировать примерно 10 приложений.

С другой стороны, я мог бы просто вернуть новый список, например

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

Что не мало для работы - но как насчет проблем с производительностью с этим? Кроме этого - если кто-то удаляет материал из списка, который я вернул, он молча сломает приложение.

Итак: в чем проблема производительности? Это проблема?

Чтобы ты делал?

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. (Что происходит, когда элемент добавляется в myObjectsMap после того, как кто-то вызвал getMyObjectList?) В то же время вы создаете копию списка каждый раз, когда кто-то вызывает метод. Таким образом, вы просто отказались от теоретического прироста производительности, который у вас был.

В любом случае, удачи. Надеюсь это поможет.

Если вы можете позволить себе тестировать приложения, я бы пошел с unmodifiableList. Это избавит вас от других связанных с этим вопросов в будущем.

Другие вопросы по тегам