Brian Goetz
brian.goetz at oracle.com
Thu Sep 5 13:05:50 PDT 2013
>> we ran a Hackday <http://wikieducator.org/JCrete2013:Hackathon> on
>> lambdas on 22nd of August in Crete.
Cool!
>> 1. Instead of having to type:
>> return Collections.unmodifiableList(products.stream().filter(p ->
>> p.getPrice() > minPrice && p.getPrice() <
>> maxPrice).collect(Collectors.toList()));
>> we should be able to type:
>> return products.stream().filter(p -> p.getPrice() > minPrice &&
>> p.getPrice() < maxPrice).collect(Collectors.*toUnmodifiableList*()));
>> which should use a mutable list for internal calculations, but in the end
>> it would return an unmodifiableList.
OK, so the request here is "Please offer us a Collector that collects to
an immutable List." The good news is twofold:
1. You can use existing combinators to get there:
.collect(collectingAndThen(toList(), Collections::immutableList));
2. You can write your own Collector to do this; such a Collector is
probably six lines of code.
>> 2. All these mapToInt(), mapToDouble() etc. methods make the API uglier
>> and more difficult to maintain in the future. Are the reasons for
>> introducing these methods for performance reasons to avoid autoboxing?
Slightly more to it than that, but yes. Earlier, we had overloads:
Stream<U> map(Function<T,U>)
IntStream map(ToIntFunction<T>)
and of course, some lambdas, like:
map(t -> 3)
are compatible with both.
The EG decided to go to explicit names for several reasons (despite the
existence of overload resolution schemes that could address some cases
well). One was that the machinery needed to address overload resolution
introduced complexity elsewhere; another was that it still did not
address all the "obvious" overload situations anyway; a third was that
having the type explicitly in the code helped make it clear whether the
result was an IntStream or a Stream<Integer>. Otherwise, pipelines like
list.map(t -> someIntBearingFunction(t))
....
were less explicit about what type of stream they resulted in. So there
are both pros and cons to the both approaches. Some people like this
better. Others don't. Won't be able to please everyone.
Note to Zhong and friends: This issue has been discussed to death, and
is now closed. This is not an invitation to reopen it.
>> 3. The developers appreciated the new Comparators API. However, in the
>> following example
>> Comparator<Book> byTitle = Comparator.comparing((Book book) ->
>> book.getTitle());
>> shouldn't be able to infer that book is of type Book since it is the type
>> in Comparator<Book>?
Yes. Also should work with Book::getTitle. Have you tried the latest
build?
>> There has been of course the usual argumentation that instead of
>>
>> products.stream().filter(p -> p.getPrice() > minPrice && p.getPrice() <
>> maxPrice).collect(Collectors.toList());
>>
>> they 'd like to have
>>
>> products.filter(getPrice() > minPrice && getPrice() < maxPrice).toList();
Two requests here. The first has to do with an even more shorthanded
form of lambda, which is syntactically indistinguishable from a
boolean-valued expression. Short answer: no way.
The second is "why not a toList()" convenience method on Stream. A fair
question, and one we considered. We decided it was not necessary.
>> but there have also been positive feedback about the first syntax since
>> notifies the developer about lazyness.
Right. A lambda expression should look different, since it is
different. And the "p ->" is not a big price to pay.
More information about the lambda-dev
mailing list