Collections.unmodifiableCollection и Collections.unmodifiableSet - PullRequest
0 голосов
/ 29 августа 2018

Предположим, у меня есть следующее Set

Set<String> fruits = new HashSet<String>();
fruits.add("Apple")
fruits.add("Grapes")
fruits.add("Orange")

Если я хотел создать защитную копию, чтобы при изменении исходного списка копия не отражала его, я могу сделать это:

Set<String> unmodifiableFruits = Collections.unmodifiableSet(new HashSet(fruits))

так что если я сделаю это:

fruits.add("Pineapple")     
println(unmodifiableFruits)

unmodifiableFruits не будет ананаса.

или я так могу:

Set<String> unmodifiableFruits = Collections.unmodifiableCollection(fruits)

и результат тот же, у unmodifiableFruits не будет ананаса.

Вопросы:

  1. Предположим, если я передал fruits в качестве аргумента классу, является ли предпочтительный метод Collections.unmodifiableCollection()?

Причина в том, что я прочитал , что объявление new в конструкторе - плохая практика, если бы я использовал Collections.unmodifiableSet(), мне нужно было бы объявить new HashSet<String>(fruits).

  1. Почему я не могу этого сделать?

    Collections.unmodifiableSet(fruits)

и вернуть его неизменяемую коллекцию.

Вместо этого я должен сделать это:

Collections.unmodifiableSet(new HashSet<String>(fruits))

Это потому, что Set - это интерфейс, и он не знает, какую реализацию возвращать?

1 Ответ

0 голосов
/ 29 августа 2018

Groovy имеет расширенные методы сбора, то есть добавил методы к стандартным классам сбора.

Один из этих методов - toSet():

Конвертировать коллекцию в набор. Всегда возвращает новый набор , даже если коллекция уже является набором.

Пример использования:

def result = [1, 2, 2, 2, 3].toSet()
assert result instanceof Set
assert result == [1, 2, 3] as Set

Когда вы пишете это:

Set<String> unmodifiableFruits = Collections.unmodifiableCollection(fruits)

это подразумевает .toSet() вызов, чтобы принудительно Collection, возвращаемый unmodifiableCollection, Set, неявно копировать данные .

Когда вы пишете это:

Set<String> unmodifiableFruits = Collections.unmodifiableSet(fruits)

возвращаемое значение уже Set, поэтому toSet() не вызывается, что означает, что unmodifiableFruits и fruits совместно используют данные.

Вот почему вы должны явно копировать данные при использовании unmodifiableSet, добавив new HashSet(...).

Правильно ли используется Collections.unmodifiableCollection() при передаче набора в конструктор?

Абсолютно нет. Использование unmodifiableCollection() и присвоение Set, неявно вызывающий toSet, который копирует данные, скрывает факт выполнения копии.

Чтобы обеспечить читабельность кода, т. Е. Чтобы каждый, кто читает код (включая вас самих за 3 года), понял, что он делает, напишите код для явного копирования данных, используя конструктор копирования.

Ну, конечно, если только это не упражнение по запутыванию кода, в этом случае это обманчивый трюк.

...