Зачем в Java 9 добавили List.of

134
07 сентября 2019, 06:00

Зачем в Java 9 добавили List.of с несколькими сигнатурами?

Например, есть:

  1. <E> List<E> of(E e1, E e2, E e3)
  2. <E> List<E> of(E e1, E e2)
  3. <E> List<E> of(E e1) ...
  4. <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)

При этом в той же Java 9 сразу добавили: <E> List<E> of(E... elements), который заменяет все предыдущие методы. Тогда в чем их смысл?

Answer 1

JEP 269:

These will include varargs overloads, so that there is no fixed limit on the collection size. However, the collection instances so created may be tuned for smaller sizes. Special-case APIs (fixed-argument overloads) for up to ten of elements will be provided. While this introduces some clutter in the API, it avoids array allocation, initialization, and garbage collection overhead that is incurred by varargs calls. Significantly, the source code of the call site is the same regardless of whether a fixed-arg or varargs overload is called.

Джошуа Блох - Java Эффективное программирование (статья 42):

Нужно быть осторожными при использовании возможностей varargs в ситуациях, где критична производительность. Каждый запуск метода с переменным числом параметров приводит к созданию и инициализации массива. Если вы понимаете, что не можете позволить себе такие расходы, но вам нужна гибкость методов varargs, есть шаблон, который позволит совместить преимущества обоих подходов. Предположим, вы определили, что 95% обращений к методу содержит 3 и менее параметров. Тогда объявим 5 перегрузок метода, каждый с количеством обычных параметров от нуля до трёх, и один метод varargs для использования, когда количество аргументов превысит 3:

public void foo() { }
public void foo(int a1) { }
public void foo(int a1, int a2) { }
public void foo(int a1, int a2, int a3) { }
public void foo(int a1, int a2, int a3, int... rest) { }

Теперь вы знаете, что затраты на создание массивов составят лишь 5% от всех вызовов в случаях, где количество параметров будет больше трёх.

Answer 2

Для оптимизации.

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

Собственно вот пример из сырцов OpenJdk List класса для <E> List<E> of(E e1, E e2)

static final class List2<E> extends AbstractImmutableList<E> {
    @Stable
    private final E e0;
    @Stable
    private final E e1;
    List2(E e0, E e1) {
        this.e0 = Objects.requireNonNull(e0);
        this.e1 = Objects.requireNonNull(e1);
    }
    @Override
    public int size() {
        return 2;
    }
    @Override
    public E get(int index) {
        Objects.checkIndex(index, 2);
        if (index == 0) {
            return e0;
        } else { // index == 1
            return e1;
        }
    }
    @Override
    public boolean contains(Object o) {
        return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
    }
    @Override
    public int hashCode() {
        int hash = 31 + e0.hashCode();
        return 31 * hash + e1.hashCode();
    }
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        throw new InvalidObjectException("not serial proxy");
    }
    private Object writeReplace() {
        return new CollSer(CollSer.IMM_LIST, e0, e1);
    }
}

P.S. Могу добавить интересный аргумент. К примеру во всем известной IntelliJ Idea есть оптимизированная реализация для List, у которого всего один элемент. И даже есть видео, где один из разработчиков объясняет, что таким образом они стремятся сэкономить память.

READ ALSO
Отслеживание объекта с камеры. Как лучше реализовать?

Отслеживание объекта с камеры. Как лучше реализовать?

Есть задача: Отследить нужную белую точку на белом фоне, их может быть несколькоПользователь получает превью камеры, затем выбирает точку...

98
Spring Security Ошибка 403 &ldquo;The server understood the request but refuses to authorize it.&rdquo;

Spring Security Ошибка 403 “The server understood the request but refuses to authorize it.”

Есть класс User и enum Roles , содержащий РолиУстанавливаю параметры UserDetails в UserDetailsServiceImpl , также настроил конфигурацию Spring Security

136
java.awt.Robot не двигает курсор в Photoshop

java.awt.Robot не двигает курсор в Photoshop

Нужно, чтобы java могла двигать курсор в photoshopJava умеет двигать курсор и делает это нормально в остальных приложениях, но когда окно photoshop активно,...

127
Как Игроку обратиться к Карте в игре?

Как Игроку обратиться к Карте в игре?

В игре отрисовка и логика столкновений должны работать за счет этой карты

113