2011-04-05 1 views

ответ

202

Главное отличие состоит в том, что Collections.emptyList() возвращает непреложный список, то есть список, к которому вы не можете добавить элементы.

В редких случаях, когда вы do хотите изменить возвращенный список, это, таким образом, не является вариантом.

Я бы сказал, что возвращение неизменяемого списка прекрасно (и даже предпочтительный вариант), если в договоре (документации) явно не указано иное.


Кроме того, emptyList()might not create a new object with each call.

Реализации этого метода не нужно создавать отдельный объект List для каждого вызова. Использование этого метода, вероятно, будет иметь сопоставимые затраты на использование поля с похожими именами. (В отличие от этого метода, поле не обеспечивает безопасность типа.)

Реализация emptyList выглядит следующим образом:

public static final <T> List<T> emptyList() { 
    return (List<T>) EMPTY_LIST; 
} 

Так что, если ваш метод (который возвращает пустой список) называется очень часто , этот подход может даже дать вам немного лучшую производительность как процессора, так и памяти.

+3

Итак, будет ли 'Collections.emptyList()' более подходящим, скажем, проверка ошибок и тому подобное? – mre

+3

Да, я бы так сказал. – aioobe

+1

Клиенты API не получат 'NullPointerException', возвращая' Collections.emptyList() 'вместо' null'. – realPK

24

Collections.emptyList является неизменным, поэтому существует разница между двумя версиями, поэтому вы должны учитывать пользователей возвращаемого значения.

Возврат new ArrayList<Foo> всегда создает новый экземпляр объекта, поэтому он имеет очень небольшую дополнительную стоимость, связанную с ним, что может дать вам основание использовать Collections.emptyList. Мне нравится использовать emptyList только потому, что это более читаемо.

4

Я бы с Collections.emptyList(), если возвращаемый список не модифицируется каким-либо образом (как список неизменен), в противном случае я бы с вариантом 2.

Выгода Collections.emptyList() является то, что тот же статический экземпляр возвращается каждый раз, и поэтому для каждого вызова не создается экземпляр.

40

Начиная с Java 5.0 вы можете указать тип элемента в контейнере:

Collections.<Foo>emptyList() 

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

+22

Начиная с Java 7, вы можете позволить компилятору вывести параметр типа общего вызова метода из целевого типа: 'List list = Collections.emptyList()' –

2

Используйте Collections.emptyList(), если вы хотите, чтобы возвращаемый список никогда не изменялся.Это то, что возвращается при вызове emptyList():

/** 
* The empty list (immutable). 
*/ 
public static final List EMPTY_LIST = new EmptyList(); 
+3

ничего нового по сравнению с более ранними ответами, есть ли? – kleopatra

+0

Я приехал сюда, пытаясь выяснить, имела ли при вызове 'Collections.emptyList()' стоимость строительства. Увидев детали реализации (хотя, вероятно, не одинаковые на всех JVM), подтвердите, что это не так. @Atul, от чего это JVM? – wjl

1

Данные ответы подчеркивают тот факт, что emptyList() возвращает неизменный List, но не дают альтернативы. Конструктор ArrayList(int initialCapacity) особые случаи 0 так возвращающиеся new ArrayList<>(0) вместо new ArrayList<>() также может быть жизнеспособным решением:

/** 
* Shared empty array instance used for empty instances. 
*/ 
private static final Object[] EMPTY_ELEMENTDATA = {}; 

[...]

/** 
* Constructs an empty list with the specified initial capacity. 
* 
* @param initialCapacity the initial capacity of the list 
* @throws IllegalArgumentException if the specified initial capacity 
*   is negative 
*/ 
public ArrayList(int initialCapacity) { 
    if (initialCapacity > 0) { 
     this.elementData = new Object[initialCapacity]; 
    } else if (initialCapacity == 0) { 
     this.elementData = EMPTY_ELEMENTDATA; 
    } else { 
     throw new IllegalArgumentException("Illegal Capacity: "+ 
              initialCapacity); 
    } 
} 

(источники из Java 1.8.0_72)

+0

Я не согласен с вашим подходом. Вы сохраняете бит памяти и CPU при инициализации, но если список, который вы вернули, когда-либо изменен, вы теряете это время, когда список перераспределяет новый массив. Если с течением времени в список добавлено много элементов, это может привести к увеличению узкого места производительности из-за [гораздо более медленного роста] (http://grepcode.com/file/repository.grepcode.com/java /root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.ensureCapacity%28int%29). Я предпочитаю придерживаться конвенции немодифицируемого пустого списка или пригодного для использования, модифицируемого списка. –

+1

Как я пытался подчеркнуть свою формулировку (_might быть жизнеспособной_): все зависит от вашего варианта использования. Я бы вообще-то возвращал mutable _or_ unmutable Collections, а не смесь в зависимости от того, насколько они пусты или нет. И чтобы противостоять «гораздо более медленному требованию»: [это] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/ArrayList.java# ArrayList.ensureCapacityInternal% 28int% 29) - текущая реализация. –

+0

О, мужчина, посмотри на меня со ссылкой на JDK 2 основных версии устарели. Таким образом, java8 полностью избегает узкого места, перепрыгивая до стандартной емкости с начальным размером 0. Извините, я был так неправ. –

5

Будьте осторожны. Если вы вернете Collections.emptyList(), а затем попробуйте сделать с ним некоторые изменения, например add() или smth, и у вас будет UnsupportedOperationException(), потому что Collections.emptyList() возвращает неизменный объект.