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