Чтобы добавить иллюстрацию к ответу Джованни, мы можем выделить разницу между f::handle
и obj -> f.handle(obj)
, если заменим f
вызовом метода:
static Set<String> f() {
System.out.println(" f() called");
return new HashSet<>();
}
public static void main(String[] args) {
List<String> empty = Collections.emptyList();
List<String> strings = Arrays.asList("foo", "bar");
System.out.println("method reference, no invocations");
empty.forEach(f()::add);
System.out.println("method reference, 2 invocations");
strings.forEach(f()::add);
System.out.println("lambda, no invocations");
empty.forEach(str -> f().add(str));
System.out.println("lambda, 2 invocations");
strings.forEach(str -> f().add(str));
}
Выход:
method reference, no invocations
f() called
method reference, 2 invocations
f() called
lambda, no invocations
lambda, 2 invocations
f() called
f() called
Итак, как вы видите, .forEach(f()::add)
сразу оценит f()
, а затем вызовет add(...)
для результата столько раз, сколько вызывается лямбда.
С другой стороны, str -> f().add(str)
ничего не делает заранее, но будет вызывать f() каждый раз, когда вызывается лямбда.
person
Misha
schedule
23.12.2014
final
. (Однако он все еще должен быть эффективно окончательным.) - person Louis Wasserman   schedule 22.12.2014s
после вызоваforEach
? - person Pshemo   schedule 22.12.2014