Что такое коллекция?

Я читал термин view несколько раз при использовании Guava коллекций и чтения его документации.

Я искал объяснение того, что представляет собой взгляд в этом контексте и используется ли этот термин за пределами Guava. Здесь довольно часто используется здесь. Этот тип из Guava имеет вид в его названии.

Я предполагаю, что представление коллекции - это еще одна коллекция с теми же данными, но структурированная по-разному; например, когда я добавляю записи от java.util.HashSet до java.util.LinkedHashSet, последний будет иметь вид первого. Это правильно?

Может ли кто-нибудь связать меня со ссылкой на принятое определение вида, если оно есть?

Спасибо.

Ответ 1

Вид другого объекта вообще не содержит собственных данных. Все его операции реализованы с точки зрения операций над другим объектом.

Например, представление keySet() для Map может иметь реализацию, которая выглядит примерно так:

class KeySet implements Set<K> {
  private final Map<K, V> map;

  public boolean contains(Object o) {
    return map.containsKey(o);
  }

  ...
}

В частности, всякий раз, когда вы изменяете базовый объект своего представления, здесь Map поддерживает keySet() - представление отражает те же изменения. Например, если вы вызываете map.remove(key), то keySet.contains(key) вернет false, не делая ничего другого.

В качестве альтернативы Arrays.asList(array) предоставляет представление List этого массива.

String[] strings = {"a", "b", "c"};
List<String> list = Arrays.asList(strings);
System.out.println(list.get(0)); // "a"
strings[0] = "d";
System.out.println(list.get(0)); // "d"
list.set(0, "e");
System.out.println(strings[0]); // "e"

Вид - это еще один способ взглянуть на данные в исходном объекте - Arrays.asList позволяет использовать API List для доступа к нормальному массиву; Map.keySet() позволяет вам получить доступ к клавишам Map, как если бы это был совершенно обычный Set - все без копирования данных или создания другой структуры данных.

Как правило, преимуществом использования представления вместо создания копии является эффективность. Например, если у вас есть массив, и вам нужно получить его для метода, который принимает List, вы не создаете новый ArrayList и целую копию данных - представление Arrays.asList принимает только постоянной дополнительной памяти и просто реализует все методы List, обращаясь к исходному массиву.

Ответ 2

В этом контексте рассматривается сбор, поддерживаемый другой коллекцией (или массивом), которая сама использует память с постоянным объемом (т.е. память не зависит от размера коллекции поддержки). Операции, применяемые к представлению, делегируются в коллекцию (или массив) поддержки. Конечно, можно расширить это определение только за коллекциями, но ваш вопрос, по-видимому, относится именно к ним.

Например, Arrays.asList() возвращает "представление списка указанного массива". Он не копирует элементы в новый список, а создает список, который содержит ссылку на массив и работает на основе этого.

Другим примером является Collections.unmodifiableList(), который возвращает "немодифицируемое представление указанного списка". Другими словами, он возвращает список, содержащий ссылку на указанный список, которому делегируются все операции. В этом случае возвращенный список не позволяет вам каким-либо образом его модифицировать, и поэтому вместо делегирования методов, ответственных за изменение списка, он выдает исключение, когда вместо этого вызывается такие методы.