10 ms·
Streams in Java 8
- bra-ket 13y agoalso https://blog.codecentric.de/en/2013/10/java-8-first-steps-lambdas-streams/ https://blog.codecentric.de/en/2013/10/java-8-first-steps-la...
- dclara 13y agoThank you.
- Randgalt 13y agoSo cool.
- deleted 13y ago[deleted]
- pron 13y agoWhile 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/
- deleted 13y ago[deleted]
- pron 13y agoThat was introduced back in Java 7.
- eweise 13y agoIsn't that what the loan pattern does and is easily accomplished with lambdas? Doesn't seem like a special case that needs to be supported by changing the language.
- javafu2 13y agoYou can not modified a variable declared in the outer scope inside a lambda. int a = 0; list.forEach(element -> { a++; // no way ! }); That's why it's a lambda and not a closure BTW.
- mbell 13y agoIt's still a closure, just a closure with immutable capture, just like Python. Also like Python, you can get around it by boxing the variable you would like to modify (or using nonlocal in Python 3). IMO the lack of exception transparency is going to be more of an issue with Java's lambdas.
- javafu2 13y agoFor most of the used programming languages, a lambda captures values (like in Java or Python), and closure capture variables or scope (like in Scheme or Ruby), hence the name, a closure close (bind) the free variable of the closure to the ones of the lexical scope. The lack of checked exception transparency is for me something that goes in the right direction. The hidden message is 'Use checked exception only for IOs and please don't create your own exceptions, use already existing ones !'
- mbell 13y agoA lambda doesn't capture anything, it's just an anonymous function. A lambda can be a closure, but it doesn't have to be. Closures come in two primary flavors, bind by value or bind by reference. Some languages implement only one of these, some implement both, some bind in completely different ways (e.g. lazy binding in Haskell).
- AYBABTME 13y ago
- simulacrum 13y agotry-with-resources actually came in with Java 7
- overgard 13y agoYay. 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?]
- lowboy 13y agoTo answer your question, your comment is just snark that doesn't contribute to the conversation. That's probably where you went wrong.
- overgard 13y agoYou can accuse me of trolling, but I think the fact that java took this long to adopt these pretty basic features isn't besides the point, it IS the point.
- javafu2 13y agoIn my opinion, lambdas were not introduced in Java before now because Java as already anonymous classes that are at a high level conceptually the same things even if a lambda is more lightweight syntactically and at runtime than an anonymous class
- jryle70 13y agoJava certainly moves very slowly. I recall reading debates on how to support Lambda long before Java 7. The reasons, IMO, are twofolds: 1) The huge install base in enterprise: changing language feature is a big deal, and like it or not, enterprises are conservative in this aspect. One only needs to look at all the garbages included with Windows in the name of backward compatibility. 2) Design by committee: Many vendors have stake in Java eco systems, all with their own agendas. To get them to agree on something take time. In some ways, Java is victim of its own success. On the other hand, JVM is a very solid platform. Those impatient can go with Scala or Clojure. I could be snarky like you were and said Scala was light year ahead of C# in terms of feature evolving, but of course I know C# is a fantastic language which serves its users very well.
- lowboy 13y ago
- rismay 13y agoJava has come a long way. Why not just merge with Scala?
- pron 13y agoBecause 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 13y agoExcept 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 13y agoBut 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.
- jebblue 13y agoThis 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 13y agoList<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);
- jebblue 13y agoNice, thanks! Now _that_ I get.
- overgard 13y agoSeems 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 13y agoIt 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.
- Jayschwa 13y agoint sum = 0; for (w : widgets) { if (w.getColor() == RED) sum += w.getWeight(); }
- barrkel 13y agosorted(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 13y agoJava'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 13y agoSure; 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.
- javafu2 13y agoIt already exists in the API. Your type Projection is a Function, and by is called comparing in interface Comparator. so one can write: ``` contries.sorted(comparingInt(Country::getPopulation)). ... ```
- bhauer 13y agoStreams are among my favorite Java 8 additions. More about the goodies in Java 8: http://www.techempower.com/blog/2013/03/26/everything-about-java-8/ http://www.techempower.com/blog/2013/03/26/everything-about-...
- blueblob 13y agoThis 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?
- wtetzner 13y agoI think the lambda syntax makes it considerably easier to read.
- wtetzner 13y agoI think the lambda syntax makes it considerably easier to read.
- tsotha 13y agoIt 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 13y ago"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.
- zmmmmm 13y agoThe 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 13y agoFrom 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.)
- coldtea 13y ago>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 13y agoIf I haven't misunderstood you, Clojure does: http://clojure.com/blog/2012/05/08/reducers-a-library-and-model-for-collection-processing.html http://clojure.com/blog/2012/05/08/reducers-a-library-and-mo... 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 13y ago>* 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.
- mark_l_watson 13y agoI 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.