Как лучше всего возвращать внутреннюю коллекцию в Java? - PullRequest
10 голосов
/ 13 мая 2011

Мне любопытно, что считается лучшим методом при возвращении коллекции объектов из изменяемого класса:

public class Someclass {

  public List<String> strings;  

  public add(String in){ strings.add(in); }
  public remove(String in) { strings.remove(in); }   

  //THIS
  public List<String> getStrings(){
    return Collections.unmodifiableList(strings);
  }

  //OR THIS
  public List<String> getStrings(){
    return new ArrayList(strings);
  }
}

Я всегда предполагал, что наилучшим подходом было обернуть внутреннюю коллекцию в Unmodifiable, так как я не видел причин нести накладные расходы на создание копии. Однако мне пришло в голову, что любые изменения, внесенные в список внутренне, будут выставлены клиенту, что мне кажется плохим.

Ответы [ 4 ]

6 голосов
/ 13 мая 2011

Я не думаю, что есть простой ответ "наилучшей практики" на это.Это действительно зависит от того, сколько ресурсов машины вы готовы потратить на предотвращение нарушения границ абстракции данных классов.И это зависит от того, какие риски вы на самом деле пытаетесь смягчить;например, это простые (не параллельные) ошибки, ошибки параллелизма или утечки информации.

Возможны следующие варианты:

  • Ничего не делать;т.е. возвращать коллекцию как есть.
  • Возвращать коллекцию, завернутую в неизменяемый класс-оболочку.
  • Возвращать поверхностную копию коллекции.
  • Возвращать глубокую копиюcollection.

Помимо прямых затрат на копирование, другими факторами, связанными с производительностью, являются использование памяти и генерация мусора, а также влияние на параллелизм.Например, если несколько потоков обновляют коллекцию и / или «получают» ее, то создание копии коллекции обычно включает ее блокировку ... что потенциально может сделать операцию узким местом параллелизма.

В заключениеВам необходимо сбалансировать влияние затрат / производительности на потенциальные или фактические риски и затраты, связанные с несоблюдением мер предосторожности.

1 голос
/ 13 мая 2011

Мне нравится делать последнее, но используя метод .clone().

0 голосов
/ 13 мая 2011

'new ArrayList (strings)' безопаснее, чем 'Collections.unmodifiableList (strings)'.

Поскольку Collections.unmodifiableList просто перенаправляет список источников.

Пример:

List<String> list1 = someclass.getStrings(); //Use Collections.unmodifiableList(strings) implementation
List<String> list2 = someclass.getStrings(); //Use new ArrayList(strings) implementation

someclass.add("foo");

Теперь вы увидите, что list1 добавлен! list2 нет.

0 голосов
/ 13 мая 2011

Если вы обеспокоены выявлением изменений; и ваш объект реализует Cloneable, тогда вы можете вернуть клонированную глубокую копию вашего списка объектов обратно вызывающему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...