
Streams in Java 8  - bra-ket
http://download.java.net/jdk8/docs/api/java/util/stream/package-summary.html
======
pron
While lambdas and streams (along with default methods, or traits) are
certainly the most important features of Java 8, I'm particularly interested
in the pluggable type systems[1].

These are pluggable, orthogonal (intersection?) types, that can even be
introduced or inferred for code that has already been compiled without them.
I'm not a type systems expert by any means, but I haven't seen anything like
it in any other language, certainly not a mainstream one.

There are currently Java 8 type systems for nullability, immutability and
more.

[1]: [http://types.cs.washington.edu/checker-
framework/](http://types.cs.washington.edu/checker-framework/)

------
barrkel

        sorted(Comparator<? super T> comparator)
    

Eurgh. Why isn't this a projection to a comparable type (or better, a
projection to a tuple of comparable types, for use with lexicographical
ordering)?

Say you have class Country { int population; int name; }. You want the names
of the top 3 countries by population:

    
    
        countries.orderByDesc(x -> x.population).limit(3).map(x -> x.name)
    

But instead, you must do something like:

    
    
        countries.sorted((x, y) -> Integer.compare(y.population, x.population).limit(3).map(x -> x.name)
    

It gets much uglier when you want a lexicographical ordering by several
attributes.

~~~
jargonjustin
Java's Comparator type is more general (you don't necessarily need to project
the type for comparison) and an existing abstraction. It's not hard to
introduce a combinator to transform the representation as a library, as in:

    
    
        countries.sorted(by(x -> x.population)).limit(3).map(x -> x.name)
    

where `by` looks something like:

    
    
        <S, T> Comparator<T> by(Projection<S, T> projection);
    
        interface Projection<S, T> {
           Comparable<S> project(T value);
        }

~~~
barrkel
Sure; and you'd have to import the thing that contains 'by'.

It's still ugly, and would prevent e.g. a radix sort being used when
projecting an integer as the sort key, or American flag sort for strings.

------
coldtea
> _However, there are good reasons to prefer a reduce operation over a
> mutative accumulation such as the above. Not only is a reduction "more
> abstract" \-- it operates on the stream as a whole rather than individual
> elements -- but a properly constructed reduce operation is inherently
> parallelizable, so long as the function(s) used to process the elements are
> associative and stateless._

I've read this kind of thing everywhere, but is there any
language/runtime/compiler that DOES DO this, or is it mostly a case of "an
adequately advanced compiler" syndrome?

Especially for examples as the simple accumulation (addition) above, it seems
especially difficult for the runtime to judge how to break down, what the
parallelization overhead would be etc.

~~~
berdario
If I haven't misunderstood you, Clojure does:
[http://clojure.com/blog/2012/05/08/reducers-a-library-and-
mo...](http://clojure.com/blog/2012/05/08/reducers-a-library-and-model-for-
collection-processing.html)

Also, this talk that I found on HN some time ago explains some of the gory
details behind the idea: [http://vimeo.com/6624203](http://vimeo.com/6624203)

~~~
coldtea
>* If I haven't misunderstood you, Clojure does*

Yes, that's an example of what I was talking about, and I know you can also do
it with Apple's Grand Central Dispatch API.

But is Clojure's stuff implicit or do you explicitly ask for the parallel
thing to happen?

What I'm asking is essentially: sure, a reduce/map/filter/etc can potentially
run in parallel. But does that ever happen automatically when using common
API's for map/reduce/etc, or do you have to explicitly tell it to do so?

And if it happens automatically, how does the scheduller knows it's a good
idea to run stuff in parallel? For some tasks the overhead might even make the
time needed worse.

------
bra-ket
also [https://blog.codecentric.de/en/2013/10/java-8-first-steps-
la...](https://blog.codecentric.de/en/2013/10/java-8-first-steps-lambdas-
streams/)

~~~
dclara
Thank you.

------
jebblue
This hurts my eyes, it doesn't look like Java, what would this look like in
Java:

    
    
         int sum = widgets.stream()
                          .filter(b -> b.getColor() == RED)
                          .mapToInt(b -> b.getWeight())
                          .sum();

~~~
talklittle

        List<Widget> filtered = filter(widgets, new Filter<Widget>() {
            @Override public boolean keep(Widget w) {
                return w.getColor() == RED;
            }
        });
    
        List<Integer> weights = mapToInt(filtered, new Mapper<Widget, Integer>() {
            @Override public Integer map(Widget w) {
                return w.getWeight();
            }
        });
    
        int sum = sum(weights);

~~~
overgard
Seems too short. Maybe you could split it into 5 files? You don't even have a
factory. Much less a factory factory. This code will never cut it in the
_enterprise_ world.

~~~
jebblue
It turns out there's a good blog article that explains why the less
enterprisey way is better since it remove the iteration loop of the collection
and lets the computer [figure out how to express the sum of weights of the red
objects in a collection of blocks]:

[http://blog.hartveld.com/2013/03/jdk-8-33-stream-
api.html](http://blog.hartveld.com/2013/03/jdk-8-33-stream-api.html)

I've been around too long to trust the computer to figure out how best to do
something. If I'm wrong then Java 8 leads the way to the end of programmers,
similar to how robotics mostly ended how cars were manufactured.

------
zmmmmm
The one feature that Python has that regularly makes me jealous when I'm using
other languages is the generator / iterator mechanism. It's possible to write
code that is composable and modular in a functional way, and automatically
scales to massive data with minimal memory use because the streaming mechanism
is built in to the language at the ground level. I _hope_ this is bringing the
same to Java for real and that this is not just syntactic sugar on top of
regular collection operations.

~~~
ygra
From the docs: »•Possibly unbounded. While collections have a finite size,
streams need not. Short-circuiting operations such as limit(n) or findFirst()
can allow computations on infinite streams to complete in finite time.»

So they can't just take collections here and pretend they're streams (but you
can obtain streams from collections).

But nice to see that the days of writing explicit loops just to filter a
collection in Java are over. That being said, I still like Python's or C#'s
syntactic enhancements to write generators/IEnumerables. The Spliterator in
Java doesn't sound as easy to use and seems more aimed at low-level library
code instead of user code. In the latter case you'd probably just get the
stream from a collection again instead of creating it yourself. (You can
apparently base it on a normal iterator, though, but the docs warn about it
having bad performance in parallel scenarios.)

------
blueblob
This is really cool, that they are making parallelization easier but does
anyone else feel like every time they add new syntax to java it becomes harder
and harder to read?

~~~
tsotha
It makes reading java more like reading lisp, which is a different way of
thinking entirely. Personally I think it's a mistake to put functional
programming into an OO language - it makes code harder to maintain as there
are too many ways to do the same thing. C++ has become virtually unusable as a
result of all the different languages they've mashed into it, and I'd hate to
see java go down the same road.

~~~
frankzinger
_" C++ has become virtually unusable..."_

Geez, the C++ hate is unbelievable. I use it every day, and it's a _great_
language. No way is it "virtually unusable". Some of the criticisms are
justified, but the way people carry on about it is just absolutely beyond
overblown.

------
bhauer
Streams are among my favorite Java 8 additions.

More about the goodies in Java 8:
[http://www.techempower.com/blog/2013/03/26/everything-
about-...](http://www.techempower.com/blog/2013/03/26/everything-about-
java-8/)

------
mark_l_watson
I have been experimenting with lambdas and streams for several months - great
additions to the language.

The one thing that I really hope for a future release of Java is a better
literal syntax for dealing with maps and JSON.

------
overgard
Yay. They finally caught up to C# 6 years later.

[Edit: to the haters -- where am I wrong other than that I'm making fun of
your favorite language?]

~~~
alkonaut
Stream<T>, IntStream, LongStream, DoubleStream?

You can't make this stuff up.

EDIT: what I'm trying to say is: why his remark is inflammatory and
unnecessary, it's also wrong. This API is perhaps the single worse example of
why java makes API's look worse than C#, and there is nothing to be done about
it until the JVM stops erasing types.

~~~
pron
Java's type erasure, while once considered a disadvantage, is now being
recognized as one of the reasons other statically typed languages can be
ported to the JVM. If Java reified types, it would make interoperability with
other type systems extremely hard.

~~~
overgard
Yet somehow they made F# and scala run on the CLR. So: I'm calling bullshit.

~~~
javafu2
F# team ask for modifications of the CLR (covariant delegates), porting a
language on the CLR if you are not Microsoft is hard.

Scala never really run on the CLR, it's a vaporware, sorry a work in progress.

~~~
adriaanm
Yep, scala's .net back-end is discontinued, and one of the main challenges (I
worked on it a bit) was indeed generating the proper generic signatures. (I
hear people are using ikvm these days.)

------
Randgalt
So cool.

------
rismay
Java has come a long way. Why not just merge with Scala?

~~~
pron
Because Scala has a very different (I would say completely opposite)
philosophy than Java. In a paper outlining Java philosophy[1], the _very first
thing_ James Gosling has to say about the language is this: "It was not an
academic research project studying programming languages: Doing language
research was actively an antigoal."

When describing the design of language, again, the very first thing Gosling
says is, "Java is a blue collar language. It's not PhD thesis material but a
language for a job. Java feels very familiar to many different programmers
because I had a very strong tendency to prefer things that had been used a lot
over things that just sounded like a good idea."

So: no research, no PhD, only proven stuff and nothing new. Regardless of your
opinion of Scala (I don't like it), I think it's not controversial to say that
Scala is on the exact opposite side of the spectrum.

[1]: [http://dfjug.org/thefeelofjava.pdf](http://dfjug.org/thefeelofjava.pdf)

~~~
runT1ME
Except your argument is invalid because java has continued to add features and
keywords to address its flaws.

It is moving towards scala, just at an incredibly slow rate.

~~~
pron
But moving at an incredibly slow rate _is_ exactly what the Gosling document
says: Java will only implement features that are familiar and proven, namely
years after they've been introduced. Also, Java's philosophy says that no
feature is to be adopted, no matter how nice, unless it solves a _very, very,
very painful problem_. Many people, myself included, think it's a very wise
stance for such a widely adopted language.

Scala is first and foremost a research language. It has some very good
features and some terrible features. Also it is completely unopinionated. But
that's how it's supposed to be: as a research language, its main goal is to
figure out what works and what doesn't, so that mainstream languages years
from now will know what works and what doesn't.

~~~
runT1ME
If java was taking things out as it added new things in, then we'd have a good
debate on our hands. Alas, they don't seem to be taking this stance, and
instead are adding in more and more (just slowly) without removing any of the
cruft.

Despite reading your many "scala" rants on HN, I still don't know which
features you think are 'terrible', just that you think there are some that
confuse you and/or are allow you to something multiple ways (abstract classes
vs. interfaces with concrete implementations say what???).

Care to actually articulate the 'terrible' features this time?

~~~
pron
Java can't take stuff out, at least not anything major. Java's adoption is two
or three orders of magnitude higher than most languages out there (except
C/C++); you can't make so many millions of developers go back and change 10 or
15 year-old code. One of the reasons it's this popular is that it's
consistently backwards compatible.

I don't want to be dragged into the Scala discussion again (after all, these
are just opinions; I realize some people really like Scala, but for some
reason, Scala people just find it hard to accept the very real fact that some
people don't like it, and it's not because they haven't tried it or don't
understand it).

