86
Семейства Arrays и Collections в java.util содержат вспомогательные методы для включения групп элементов в коллекции. Метод Arrays.asList() получает либо массив, либо список элементов, разделенных запятыми, и преобразует его в объект List. Метод Collections.addAUQ получает объект Collection и либо массив, либо список, разделенный запятыми, и добавляет элементы в Collection. Пример:
//• hoiding/AddingGroups java
// Добавление групп элементов в объекты Collection
import java.util *;
public class AddingGroups {
public static void main(String[] args) { Collection<Integer> collection =
new ArrayList<Integer>(Arrays.asList(l, 2, 3, 4, 5)); Integer[] morelnts = { 6. 7. 8. 9. 10 }; collection.addAll(Arrays.asList(morelnts)); // Работает намного быстрее, но таким способом // невозможно сконструировать Collection: Collections.addAll(collection, 11, 12, 13, 14, 15); Col lections.addAll(collection, morelnts); // Создает список на основе массива: List<Integer> list = Arrays.asList(16. 17, 18, 19, 20); list set(l, 99); // Можно - изменение элемента // list.add(21); // Ошибка времени выполнения - нижележащий // массив не должен изменяться в размерах
}
} ///:-
Конструктор Collection может получать другой объект Collection, используемый для его инициализации, поэтому для передачи исходных данных можно воспользоваться методом Arrays.asList(). Однако метод Collections.addAll() работает намного быстрее, и вы с таким же успехом можете сконструировать Collection без элементов, а затем вызвать Collections.addAll — этот способ считается предпочтительным.
Методу Collection.addAll() в аргументе может передаваться только другой объект Collection, поэтому он уступает в гибкости методам Arrays.asList() и Collections.addAll(), использующим переменные списки аргументов.
Также можно использовать вывод Arrays.asList() напрямую, в виде List, но в этом случае нижележащим представлением будет массив, не допускающий изменения размеров. Вызов add() или delete() для такого списка приведет к попытке изменения размера массива, а это приведет к ошибке во время выполнения.
Недостаток Arrays.asList() заключается в том, что он пытается «вычислить» итоговый тип List, не обращая внимания на то, что ему присваивается. Иногда это создает проблемы:
//: hoiding/AsListInference.java // Arrays.asListO makes its best guess about type, import java.util.*;
class Snow {}
class Powder extends Snow {} class Light extends Powder {} class Heavy extends Powder {} class Crusty extends Snow {} class Slush extends Snow {}
public class AsListInference {
public static void main(String[] args) { List<Snow> snowl = Arrays.asList(
new CrustyO. new SlushO. new PowderO);
// He компилируется- // List<Snow> snow2 = Arrays.asList( // new LightO. new HeavyO); // Сообщение компилятора: //found java.util.List<Powder> // required, java util List<Snow>
II Collections.addAllО работает нормально:
List<Snow> snow3 = new ArrayList<Snow>():
Col 1 ecti ons. addAl 1 (snow3, new LightO. new HeavyO);
II Передача информации посредством уточнения // типа аргумента
List<Snow> snow4 = Arrays <Snow>asList( new LightO, new HeavyO),
}
} ///:-
При попытке создания snow2, Arrays.asList() создает List<Powder> вместо List <Snow>, тогда как Collections.addAll() работает нормально, потому что целевой тип определяется первым аргументом. Как видно из создания snow4, в вызов Arrays.asList() можно вставить «подсказку», которая сообщает компилятору фактический тип объекта List, производимого Arrays.asList().
С контейнерами Map дело обстоит сложнее, и стандартная библиотека Java не предоставляет средств их автоматической инициализации, кроме как по содержимому другого объекта Map.
Вывод содержимого контейнеров
Для получения печатного представления массива необходимо использовать метод Arrays.toString, но контейнеры отлично выводятся и без посторонней помощи. Следующий пример демонстрирует использование основных типов контейнеров:
II: ell:Printi ngContai ners.java II Вывод контейнеров по умолчанию import java.util.*;
import static net.mindview.util.Print.*;
public class PrintingContainers {
static Collection fill(Collection<String> collection) { collection. addC'rat"): collection.addC'cat"); collection.adde'dog"): col lection.add("dog"); return collection;
}
static Map fill(Map<String,String> map) {
map. put ("rat", "Fuzzy");продолжение &
map.put("cat". "Rags"), тар.put("dog". "Bosco"); map.put("dog", "Spot"); return map;
}
public static void main(String[] args) {
pri nt(fi11(new ArrayLi st<Stri ng>())); print(fill(new LinkedList<String>())); pri nt(fi11(new HashSet<Stri ng>())); pri nt(fi11(new TreeSet<Stri ng>())); pri nt(fi11(new Li nkedHashSet<Stri ng>())); pri nt(fi11(new HashMap<Stri ng.Stri ng>())); print(fill(new TreeMap<String,String>())); print(fi11(new LinkedHashMap<String,String>()));
}
} /* Output: [rat, cat, dog, dog] [rat, cat. dog, dog] [dog, cat, rat] [cat, dog, rat] [rat. cat. dog]
{dog=Spot. cat=Rags, rat=Fuzzy} {cat=Rags, dog=Spot, rat=Fuzzy} {rat=Fuzzy, cat=Rags, dog=Spot} *///:-
Как уже было упомянуто, в библиотеке контейнеров Java существует две основные категории, различающиеся прежде всего тем, сколько в одной ячейке контейнера «помещается» элементов. Коллекции (Collection) содержат только один элемент в каждой ячейке. К этой категории относятся список (List), где в определенной последовательности хранится группа элементов, множество (Set), в которое можно добавлять только по одному элементу определенного типа, и очередь (Queue). В контейнерах Map (карта) хранятся два объекта: ключ и связанное с ним значение.
Из выходных данных программы видно, что вывод по умолчанию (обеспечиваемый методом toStringO каждого контейнера) дает вполне приличные результаты. Содержимое Collection выводится в квадратных скобках, с разделением элементов запятыми. Содержимое Map заключается в фигурные скобки, ключи и значения разделяются знаком равенства (ключи слева, значения справа).
Контейнеры ArrayList и LinkedList принадлежат к семейству List, и из выходных данных видно, что элементы в них хранятся в порядке вставки. Они различаются не только скоростью выполнения тех или иных операций, но и тем, что LinkedList содержит больше операций, чем ArrayList.
HashSet, TreeSet и LinkedHashSet относятся к семейству Set. Из выходных данных видно, что в множествах Set каждый элемент хранится только в одном экземпляре, а разные реализации Set используют разный порядок хранения элементов. В HashSet порядок элементов определяется по довольно сложному алгоритму — пока достаточно знать, что этот алгоритм обеспечивает минимальное время выборки элементов, но порядок следования элементов на первый взгляд выглядит хаотично. Если порядок хранения для вас важен, используйте контейнер TreeSet, в котором объекты хранятся отсортированными по возрастанию в порядке сравнения, или LinkedHashSet с хранением элементов в порядке добавления.