Поскольку структура коллекций языка Java (коллекции, такие как список, карта, набор и т. д.) не предоставляет какой-либо удобной синтаксической структуры, это сильно усложняет работу по созданию коллекций констант. Каждый раз, когда мы строим, мы делаем:
1. Определите пустую переменную класса коллекции 2. Добавляйте элементы в этот комбинированный класс один за другим 3. Передать коллекцию в качестве параметра метода
Например, чтобы передать переменную Set методу:
Set users = new HashSet();
users.add("Hollis");
users.add("hollis");
users.add("HollisChuang");
users.add("hollis666");
transferUsers(users);
Этот способ написания немного сложен. Есть ли краткий способ?
Сборник инициализации синхронизации бренда
На самом деле есть относительно простой способ, т.синтаксис двойной скобки(double-brace syntax) для создания и инициализации новой коллекции:
public class DoubleBraceTest {
public static void main(String[] args) {
Set users = new HashSet() {{
add("Hollis");
add("hollis");
add("HollisChuang");
add("hollis666");
}};
}
}
Точно так же синтаксис для создания и инициализации HashMap выглядит следующим образом:
Map<String,String> users = new HashMap<>() {{
put("Hollis","Hollis");
put("hollis","hollis");
put("HollisChuang","HollisChuang");
}};
Таким образом можно создавать и инициализировать не только Set и Map, но и классы коллекций в jdk.
Когда мы используем этот синтаксис с двойными скобками для инициализации класса коллекции, когда файлы Java компилируются, вы можете обнаружить странное явление, используйте javac для компиляции DoubleBraceTest:
javac DoubleBraceTest.java
Мы обнаружим, что получаем два файла классов:
DoubleBraceTest.class
DoubleBraceTest$1.class
Опытные друзья могут знать, что когда они видят эти два файла, необходимо использовать анонимные внутренние классы.
Правильно, результатом использования этой инициализации с двойными скобками является создание анонимного внутреннего класса. Созданный класс имеет неявный указатель this на внешний класс.
Эта форма не рекомендуется
Во-первых, создание и инициализация коллекций в этой форме приводит к созданию множества внутренних классов. Потому что каждый раз, когда вы инициализируете двойными фигурными скобками, создается новый класс. Как в этом примере:
Map hollis = new HashMap(){{
put("firstName", "Hollis");
put("lastName", "Chuang");
put("contacts", new HashMap(){{
put("0", new HashMap(){{
put("blogs", "http://www.hollischuang.com");
}});
put("1", new HashMap(){{
put("wechat", "hollischuang");
}});
}});
}};
Это приведет к созданию множества внутренних классов:
DoubleBraceTest$1$1$1.class
DoubleBraceTest$1$1$2.class
DoubleBraceTest$1$1.class
DoubleBraceTest$1.class
DoubleBraceTest.class
Эти внутренние классы создаются и должны быть загружены классовым погрузчиком, который приносит некоторые дополнительные накладные расходы.
Если вы используете приведенный выше код для создания и инициализации карты в методе и возвращаете эту карту из метода, вызывающая сторона метода может неосознанно удерживать ресурс, который не может быть удален сборщиком мусора.
public Map getMap() {
Map hollis = new HashMap(){{
put("firstName", "Hollis");
put("lastName", "Chuang");
put("contacts", new HashMap(){{
put("0", new HashMap(){{
put("blogs", "http://www.hollischuang.com");
}});
put("1", new HashMap(){{
put("wechat", "hollischuang");
}});
}});
}};
return hollis;
}
Мы пытаемся инициализировать такую карту двойными скобками, вызывая getMap
public class DoubleBraceTest {
public static void main(String[] args) {
DoubleBraceTest doubleBraceTest = new DoubleBraceTest();
Map map = doubleBraceTest.getMap();
}
}
Возвращенная карта теперь будет содержать ссылку на экземпляр DoubleBraceTest. Читатели могут попробовать подтвердить этот факт с помощью отладки или следующим образом.
Field field = map.getClass().getDeclaredField("this$0");
field.setAccessible(true);
System.out.println(field.get(map).getClass());
альтернативный план
Многие люди используют двойные скобки для инициализации коллекций, в основном потому, что удобнее инициализировать коллекции при их определении.
Но на самом деле схем для этого уже много, и нет необходимости использовать эту рискованную схему.
Использование служебного класса Arrays
Когда мы хотим инициализировать список, вы можете помочь классу Arrays, Arrays предоставляет asList, который можно преобразовать в список массивов:
List<String> list2 = Arrays.asList("hollis ", "Hollis", "HollisChuang");
Однако следует отметить, что ASLIST получает только внутренний класс Arrays, который представляет собой список просмотра массива, поэтому, если вы добавите в него ошибку, вы сообщите об ошибке.
Использовать поток
Поток — это новая функция, представленная в Java, которая может выполнять промежуточные операции (промежуточные операции), такие как фильтрация, сортировка и агрегирование элементов внутри входящего потока, и, наконец, получать результат предыдущей обработки терминальной операцией.
Мы можем инициализировать коллекцию с помощью Stream:
List<String> list1 = Stream.of("hollis", "Hollis", "HollisChuang").collect(Collectors.toList());
Используйте сторонние инструменты
Многие сторонние классы инструментов для сбора данных могут реализовать эту функцию, например, Guava и т. д.:
ImmutableMap.of("k1", "v1", "k2", "v2");
ImmutableList.of("a", "b", "c", "d");
О гуаве и определенных в ней неизменяемых коллекциях мы подробно расскажем позже.
Встроенные методы Java 9
Фактически, в Java 9 методы инициализации были встроены в классы коллекций, такие как List и Map, например, List содержит 12 перегруженных методов, которые используются для этого:
/**
* Returns an unmodifiable list containing zero elements.
*
* See <a href="#unmodifiable">Unmodifiable Lists</a> for details.
*
* @param <E> the {@code List}'s element type
* @return an empty {@code List}
*
* @since 9
*/
static <E> List<E> of() {
return ImmutableCollections.emptyList();
}
static <E> List<E> of(E e1) {
return new ImmutableCollections.List12<>(e1);
}
static <E> List<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.emptyList();
case 1:
return new ImmutableCollections.List12<>(elements[0]);
case 2:
return new ImmutableCollections.List12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.ListN<>(elements);
}
}
Об авторе:Hollis, человек с уникальным увлечением программированием, технический эксперт Alibaba, соавтор «Трех курсов для программистов» и автор серии статей «Дорога к Java-инженерам».
Обратите внимание на общедоступный номер【Hollis], фоновый ответ «Карта Бога» может получить расширенную карту разума инженеров Java.