Подтвердить что ты не робот

Создание нового объекта при использовании потоков Java 8

Существует ли разница в использовании следующих контрструктур, отличных от немного лучшей читаемости в последнем?

someList.stream().map(item -> new NewClass(item)).collect(Collectors.toList());

someList.stream().map(NewClass::new).collect(Collectors.toList());
4b9b3361

Ответ 1

Вообще нет никакой разницы. NewClass::new производит меньше байт-кода, так как в лямбда-версии автогенерированный закрытый метод создается java-компилятором из тела лямбда, а NewClass:new напрямую ссылается на дескриптор метода конструктора. Таким образом, используя ссылки на методы, вы можете иметь немного меньше размера файла класса. Однако существенной разницы в производительности не ожидается.

Другим отличием является процедура разрешения метода. Он не применим в вашем конкретном примере, но может применяться в другом коде. Например, у вас есть два конструктора:

public NewClass(String a) {...}
public NewClass(String a, String b) {...}

И у вас есть какой-то метод, который принимает функциональный интерфейс:

public myMethod(Function<String, NewClass> fn) {...}

Затем вы можете вызвать его как с лямбдой, так и с функциональным интерфейсом:

myMethod(str -> new NewClass(str));
myMethod(NewClass::new);

Но предположим, что позже вы добавляете новый метод с тем же именем:

public myMethod(BiFunction<String, String, NewClass> fn) {...}

Тогда вызов справочника метода станет неоднозначным и приведет к ошибке компиляции, поскольку NewClass::new теперь соответствует обоим конструкторам, а лямбда по-прежнему однозначна.