When lambdas become objects
Brian Goetz
brian.goetz at oracle.com
Tue Nov 27 19:38:44 PST 2012
> I have a few questions about when lambdas are converted into objects, and
> how often.
>
> 1. Non-capturing, but inferring generic type:
>
> public static <T> Predicate<T> nonNull() {
> return t -> t != null;
> }
At first capture, a single instance is created; thereafter, the same
instance may be returned again on next capture.
> Does every invocation of nonNull() return the same Predicate instance?
Implementations are permitted to do so, and ours (mostly) does. But
this is not guaranteed and you should not assume that it does.
> 2. Capturing methods or member variables from the enclosing class:
>
> class FunDetector {
> private boolean isFun(Activity activity) { ... }
>
> public Predicate<Activity> isFunAcitivity() {
> return activity -> isFun(activity);
> }
> }
>
> Does every invocation of isFunActivity() return a separate Predicate
> instance? Or, would a given FunDetector instance always return the same
> Predicate instance?
Because isFun is an instance method, you have to capture the receiver
variable 'this', so each capture is likely to result in a new object.
(Note you could have written this both more compactly and more
explicitly as "return this::isFun".)
> 3. Lambda within a lambda, both capturing a variable from the calling
> method:
>
> (This example uses the ComparisonChain class from Guava:
> http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/index.html?com/google/common/collect/ComparisonChain.html)
>
> void weirdSort(List<String> list, boolean flag) {
> list.sort((a, b) -> ComparisonChain.start()
> .compare(
> a.charAt(0),
> b.charAt(0),
> (x, y) -> Character.compare(
> flag ? Character.toLowerCase(x) : Character.toTitleCase(x),
> flag ? Character.toLowerCase(y) : Character.toTitleCase(y)))
> .compare(
> flag ? a.length() : a.hashCode(),
> flag ? b.length() : b.hashCode())
> .result());
> }
>
> Does every invocation of weirdSort(list, flag) cause the creation of
> exactly two Comparators? Or does every comparison made by the outer
> Comparator lambda cause the creation of an additional Comparator (for the
> inner lambda)?
The latter. The inner lambda is captured when the outer lambda is
executed, and the inner lambda captures the 'flag' variable.
You could rewrite it to not do so, by pulling the inner lambda out to
the top level of weirdSort, and capturing that.
More information about the lambda-dev
mailing list