The latest expert opinions, articles, and guides for the Java professional.

Java 8 Revealed: Lambdas, Default Methods and Bulk Data Operations

What if you no longer had to redeploy your Java code to see changes? The choice is yours. In just a few clicks you can Say Goodbye to Java Redeploys forever.

Terminating operations

Usually, dealing with a stream will involve these steps:

  1. Obtain a stream from some source.
  2. Perform one or more intermediate operations, like filter, map, etc.
  3. Perform one terminal operation.

A terminal operation must be the final operation invoked on a stream. Once a terminal operation is invoked, the stream is “consumed” and is no longer usable.

There are several types of terminal operations available:

  • reducers like reduce(..), count(..), findAny(..), findFirst(..) terminate stream processing. Depending on the intention, the terminal operation can be a short-circuiting one. For instance, findFirst(..) will terminate the stream processing as soon as it encounters a matching element.
  • collectors, as the name implies, are for collecting the processed elements into a resulting collection.
  • forEach performs some action for each element in the stream.
  • iterators are the good ‘ol way to work with collections if none of the options above satisfies our needs.

The most interesting terminal operation type are the so-called “collectors”.


While stream abstraction is continuous by its nature, we can describe the operations on streams but to acquire the final results we have to collect the data somehow. The Stream API provides a number of so-called “terminal” operations. The collect() method is one of the terminal operations that allow us to collect the results:

List students =
    .filter(p -> p.getAge() > 18)
    .collect(new Collector<Student, List>() { ... });

Fortunately, in most cases you wouldn’t need to implement the Collector interfaces yourself. Instead, there’s a Collectors utility class for convenience:

List students =
    .filter(p -> p.getAge() > 18)

Or in case if we would like to use a specific collection implementation for collecting the results:

List students =
    .filter(p -> p.getAge() > 18)

Parallel and sequential

One interesting feature of the new Stream API is that it doesn’t require to operations to be either parallel or sequential from beginning till the end. It is possible to start consuming the data concurrently, then switch to sequential processing and back at any point in the flow:

List students =
    .filter(p -> p.getAge() > 18)  // filtering will be performed concurrently

The cool part here is that the concurrent part of data processing flow will manage itself automatically, without requiring us to deal with the concurrency issues.

Summary, Conclusion and a Goodbye Comic

In the current report we have covered three main topics in the upcoming Java 8:

  1. Lambda expressions
  2. Default methods
  3. Bulk data operations for Java collections

As we have seen, lambdas are greatly improve readability of the code and making Java the language more expressive, especially when we move on to new Stream API. Default methods, in turn, are essential for API evolution, connecting the Collections API with lambdas for our convenience. Nevertheless, the ultimate goal of all this new features is to introduce parallel libraries and to seamlessly take advantage of the multi-core hardware.

I’m gonna make this a really short conclusion here as well, which basically comes down to this: while the JVM itself is a great piece of engineering, whether you want to admit it or not, the Java platform is still alive and kicking. These new changes will allow us to leverage the platform and the language in a much more efficient way, and will ideally give the critics of Java a bit more substance to chew on.

Responses (48)

  1. Avatar  


    June 25, 2013 @ 8:15 pm

    should not it be persons.foreach(… ?

  2. Avatar  


    June 25, 2013 @ 8:24 pm

    Fixed. thx!

  3. Avatar  


    June 25, 2013 @ 11:04 pm

    Great post, thank you sir!

  4. Avatar  


    June 25, 2013 @ 11:45 pm

    “Not that we can actually amend the lambda parameter type declaration:” Should it be ‘omit’ instead of ‘amend’?

  5. Avatar  


    June 27, 2013 @ 2:17 pm

    it should. thx.

  6. Avatar  

    Adam Boesch

    June 27, 2013 @ 5:48 pm

    List persons = …
    Stream personsOver18 = -> p.getAge() > 18);

    This may seem obvious, but doesn’t the List need to be typed? Like for example:

    List persons = …
    Stream personsOver18 = -> p.getAge() > 18);

    Or are you just omitting it for readability reasons?

  7. Avatar  


    June 27, 2013 @ 7:14 pm

    Thanks for the question.

    It is just that I shamelessly forgot to add the generic type into the example, but let’s assume that is for the readability reasons :)

  8. Avatar  

    Martijn Blankestijn

    July 1, 2013 @ 6:35 am

    In the PDF (page 19) the last part (with ‘.map(Student::new);’ is missing on page 19

  9. Avatar  


    July 9, 2013 @ 11:43 am

    “Lambdas, it turns out, are great for improving the readability of your code and the expressiveness of the language.”

    This is one argument that I have seen on many places, but I don’t understand it. Does less information mean better readability? Or is it the amount of characters that you “have to” type?

    If less code/information means that it is more readable, then the following should be even more readable:

    cmp -> (x y) ? 1 : 0);

    I mean, it’s obvious that you are comparing x and y, so why would you “have to” declare them as parameters? The order could be determined by the order of appearance in the expression. Further on, what difference does it make if cmp is of Comparator type or not as long as you are providing an object with only one function that returns a value of desired type?

    I am sure that if I went on I could cut down the complete expression to something like:

    cmp(x,y) . ? 1 : 0;

    Very little code without any “unnecessary” information, but then you would have to spend a half an hour at every line of code trying to figure out what it does.

  10. Avatar  

    Jan Friderici

    July 11, 2013 @ 9:49 am

    Concise code (or normal English) is readable. Concise does not mean you should (or can) omit important information. It means you can (and should) omit redundant information.

  11. Avatar  


    July 12, 2013 @ 11:18 am

    Well, binary code is concise and doesn’t omit any important information, but it sure as hell isn’t readable. In written language, you have punctuation, and text formatting in documents in order to make it more readable. None of that is important information, but it improves readability.

  12. Avatar  


    July 12, 2013 @ 7:10 pm

    Removing boilerplate makes code more readable. Patching Java language to use lambdas does not make it more readable in it self, but the removal of thread control and creation anonymous classes by hand does make it more readable and useful. In the end it was done to make Java more relevant against other JVM languages.

  13. Avatar  

    Jan Friderici

    July 15, 2013 @ 3:29 pm

    Binary code is everything but concise. A simple expression (in C, C++ or Java) can result in many single instructions.

    Punctuation can change the meaning of a sentence. eg “Stop clubbing baby seals” vs “Stop clubbing, baby seals”.

    Concise means to express much in few words, the exact opposite of binary code. Punctuation can be used to write concise or wordy sentences.

  14. Avatar  

    master faster

    July 17, 2013 @ 6:30 am

    where is the pdf version?

  15. Avatar  


    July 19, 2013 @ 4:14 pm

    There’s a button, “Dude, get the pdf” – push that.

  16. Avatar  

    Matthew McClellan

    July 28, 2013 @ 11:18 pm

    The floating icons on the left are really annoying when your trying to read this site on mobile

  17. Avatar  

    Bruno Kim Medeiros Cesar

    July 29, 2013 @ 2:35 am

    Thanks for this post, it made me finally test Java 8.

    There’s a small error: IntStream.range does not accept an increment argument, so your example in Page 18 (at the PDF) doesn’t compile. Although I would mostly consider it an error from the implementor side…

  18. Avatar  


    July 29, 2013 @ 5:00 am

    The API is evolving atm. At the time of writing I might have used a version where IntStream.range accepted the increment. I’m considering updating the doc when Java 8 is out.

  19. Avatar  


    August 27, 2013 @ 1:29 pm

    Hello, Anton

    I’m Larry Wang, working
    at Tencent as a java developer and I’ve read
    this report, which is informative and easy to understand. Now, I’ve been privately making a Chinese translation
    of “Java 8 Revealed” for a few days, for the purpose that java
    developers in my country whose English is not so good ,could learn the report.
    So I will need your authorization to release the Chinese version after the
    translation is finished, and of course I will indicate the source.

    Hope you will consent to my request. ^-^

  20. Avatar  


    August 28, 2013 @ 8:45 am


    Could you contact me by email – anton/at/zeroturnaround/dot/com

  21. Avatar  

    Ilja Gužovski

    September 18, 2013 @ 10:02 am

    Hello, Anton! Post is great! I have a question about your vision of default methods: Will they replace abstract classes? For now, I see that the main advantage of them will be gone, and all of them could be replaced with new java 8 interfaces?

  22. Avatar  


    September 18, 2013 @ 10:06 am

    Well, while you can replace abstract classes with the default methods, still you can’t get rid of them. Interfaces may only have the default methods, but no state. The fields in interfaces are effectively constants. And in abstract classes those are mutable.
    Of course, default methods eat a good portion of abstract class use cases, but they are different things still.

  23. Avatar  

    Ilja Gužovski

    September 18, 2013 @ 10:14 am

    Thanks for such a quick reply! Yeah, I have forgotten about the variables in the abstract classes.

  24. Avatar  


    October 11, 2013 @ 7:30 pm

    Am I the only one who realizes how much java sucks and is a poor imitation of C#? “The main driver behind the new lambda feature” is of course that C# already had this feature in 2007. Code in interfaces? what the f*ck is that? don’t you realize interfaces are CONTRACTS? How is anyone supposed to put code in interfaces? does my contract library need to have a dependency on an ORM library for example, if my “defender” (wtf is that?) methods need to call things from the ORM? I can’t believe how ridiculous this all is, and nobody seems to notice that.

  25. Avatar  


    October 11, 2013 @ 8:13 pm

    “of course that C# already had this feature in 2007” — and LISP had it like 50 years ago, so it doesn’t matter. Of course it is very cool that C# had lambdas in 2007, all the cool kids have lambdas. So Java wants those too :)

    “Code in interfaces? what the f*ck is that?” – Did you actually read the article? There’s a good explanation of _why_ this is done this way. To make it short – “collections interface evolution + backwards compatibility”. I hope you understand.

  26. Avatar  


    October 11, 2013 @ 10:14 pm

    That’s the problem with java, why do you need backwards compatibility? make java like .Net, where you can have many versions of the runtime coexisting in the same machine, then have your code target a specific version. j

    ava sucks at every imaginable level. It’s a retarded language.

    C# 5 has async / await, while java 8 (not even released to this day) is struggling to implement a “wannabe” LINQ feature. How does this supposed lambda stuff provide a unique and consistent model that is independent of the backend? It doesn’t. LINQ shares the same syntax and the same methods across all it’s implementations (from LINQ-to-Object to LINQ-to-Entities to LINQ-to-Twitter to LINQ-to-Mygrandma)

  27. Avatar  


    October 11, 2013 @ 10:22 pm

    And No, I will never understand why java violates every single aspect of OOP by putting CODE in INTERFACES. That’s the stupidest thing I’ve heard in my whole life. And they say that “C# Extension Methods are an undesirable feature”. Please, go ahead and show me a REAL WORLD example of these supposed defender methods working in an N-Tier Client/Server application without making the client-side take dependencies on server-side code. Please.

  28. Avatar  


    October 11, 2013 @ 10:30 pm

    You don’t even try to understand. Emotions won’t help.

  29. Avatar  


    October 11, 2013 @ 10:34 pm

    “make java like .Net” — it is too late. Luckily for C#, some people who worked on Java at the early days learned from mistakes and moved to MS to work on C#/.NET — that probably explains how C# dodged the mistakes that Java did.

    “java sucks at every imaginable level. It’s a retarded language” — you’re free to not program Java, that’s a fair trade off :)

    What kind of argument are you trying to build up?

  30. Avatar  


    October 11, 2013 @ 10:41 pm

    I’m expressing malcontent for the statement “C# Extension Methods are an undesirable feature” I read somewhere in the java discussions.

    Extension Methods have really made LINQ possible, and lambdas are actually an addition to all that, but they’re not “the Core” of it. In it’s Core, LINQ is just a bunch of Extension Methods that take Delegates as parameters and perform stuff on IEnumerables and usually return new IEnumerables (projections, we call them).

    “Luckily for C#” – So are you admitting that C# is superior? OMG it’s going to rain.

    And don’t forget that if you want to COPY LINQ, you will need something like System.Linq.Expressions (AKA Expression Trees)

  31. Avatar  


    October 11, 2013 @ 10:47 pm

    “I read somewhere in the java discussions.” — well, it is not this blog where it was mentioned. So you probably hopped on a wrong page. Reddit is a better place for this kind of trolling.

    In my view, C#, as a langauge is superior, yes. It is also different in some minor ways. Does it matter?

    “And don’t forget that if you want to COPY LINQ…” — dude, do you still think I’m the Java language designer? Wake up!

  32. Avatar  


    October 11, 2013 @ 10:53 pm

    Some minor ways? you must be kidding.

    – Properties.
    – Delegates and Events
    – Partial classes
    – Value Types!!
    – Real Generics!!
    – …. I could go on forever.

    BTW, C# also made mistakes, but they fixed them, and didn’t bother at all about “backwards compatibility”. Of course C# 5 isn’t backwards compatible with C# 4, why would you care about that? is Windows 8 “backwards compatible” with DOS 1.0? No, of course not. Nobody cares about dinosaur technology.

    java needs to grow up. it “could” have been the greatest thing to ever happen to software development, since it “could” have been multi-platform C#, but it’s not. It’s like a stubborn old man who refuses to evolve.

  33. Avatar  


    October 11, 2013 @ 10:56 pm

    Dude, you don’t like Java and don’t program Java. So why bother?

  34. Avatar  


    October 11, 2013 @ 10:59 pm

    You’re right. I’m out of here. Let me get back to my beautiful generics and LINQ. Let me know if you want to discuss about a real programming language, and not a ridiculous dinosaur.

  35. Avatar  


    October 11, 2013 @ 11:01 pm

    I wish you all the luck, have fun! :)

  36. Avatar  

    മൂസ Moosa

    November 18, 2013 @ 8:57 am

    Even if Java sucks in certain areas, you guys should be the last to mock it. Actually C# was “inspired” from Java and even if they had the benefit of learning from some of the mistakes of Java, it would forever remain “Copy#”

  37. Avatar  


    February 3, 2014 @ 3:52 pm

    Your argument is no longer relevant. “C# was inspired by java” IN 1990. It’s 2014. C# has EVOLVED, and all the evolution has come from C# improving itself, not from copying java, which did NOTHING and stayed in the 90’s.

    and then you see these changes in java, which are clearly trying to copy C#’s evolution.

    Yes, I’m pretty sure a Chevrolet Camaro from 2014 still retains the “initial architecture” and ideas from a Ford-T. That doesn’t make the Ford-T less useless in the present world.

    C# is ubiquitous and no longer WIndows-only. I’m already creating beautiful Android apps in C# on Xamarin. java is OBSOLETE. face it. BTW, “you guys should be the last to mock it” is not a strong counter-argument to all the technical criticisms I do.

  38. Avatar  

    മൂസ Moosa

    February 3, 2014 @ 4:37 pm

    Your first comment was full of rantings rather than “technical criticisms “. Anyway, here is what I have to say:

    “Am I the only one who realizes how much java sucks and is a poor imitation of C#?”
    As you wrote in the second comment, C# has probably evolved better than Java, but how would you justify your original argument that Java is an imitation of C#???C# was created much later to Java as Microsoft’s response to the success of Java.

    “and then you see these changes in java, which are clearly trying to copy C#’s evolution.”


    this would have been true if the “ideas” that C# adopted during its evolution were original ideas. Lambdas exist since a long time in other PLs and Martin Odersky, the creator of Scala tried to bring Lambda, Generic etc. to a much earlier version of Java, rather unsuccessfully.

    C# could evolve faster because the breadth and depth of C# userbase was light-years behind Java, so they did not have all the baggage that comes with success such as b/w compatibility, maintaining bloated features and libraries, bulky community, powerful enterprise level customers, all of which who had to be kept happy with each major release.

  39. Avatar  


    February 3, 2014 @ 4:45 pm

    Ok. I should have said “java is implementing lambdas because java developers are starting to realize java sucks due to not evolving since 25 years”. Is it better now?

    And the “backwards compatibility” argument is just silly to me.

    Real Solution:
    Improve the language. Improve the compiler. Improve the Framework. CHANGE the Version NUMBER. Have your code target a SPECIFIC version number of everything (Language and framework), just like .Net does. NOTHING gets broken when you upgrade anything. Versions coexist peacefully.
    Now THAT is a solution to backwards compatibility.

    Not evolving a single thing in 50 years does not look like a good solution to me.

    And your argument that “C# could evolve faster” is irrelevant. C# is STILL evolving faster and will evolve even faster because they created a new compiler. And your “user base” argument is no longer true. there are millions of successful (enterprise and non-enterprise) C# applications out there now.

  40. Avatar  

    Big Al

    March 6, 2014 @ 6:33 pm

    Some developers are way to tied to their tools of choice. We all need a bit more serenity in our lives.

  41. Avatar  

    Ramakata Oblonsky

    March 20, 2014 @ 1:01 am

    C# is much more advanced than Java, why do we do any secret. Although personally I like JavaScript more. SO all of us keep hope that Satya will move C# in public domain soon. Hey Satya, do you hear us?

  42. Avatar  


    March 20, 2014 @ 8:21 am

    Hello, Anton! Thank you great post on Java 8.

    I tried to compile this snippet

    Comparator cmp = (x, y) -> (x y) ? 1 : 0);

    But it fails with bad type for >, (x.intValue() y.intValue()) ? 1 : 0);

    Unfortunately it’s not so nice as first one.

  43. Avatar  


    March 20, 2014 @ 8:26 am

    At the time of writing it was a valid code. It seems the way it is handled is changed a bit. But try this:

    Comparator cmp = (x, y) -> (x y) ? 1 : 0);

    Should totally work.

  44. Avatar  


    March 20, 2014 @ 8:28 am

    Yup! It works and still nice. Thank you!

  45. Avatar  


    April 19, 2014 @ 10:23 am

    HighCore, you dont really understand the Java philosophy and the origins because you are a desktop user.

    Java emanated from Sun, an enterprise company dabbling with huge servers with extreme demands, regarding uptime, performance, scalability, etc. In such enterprise environments, uptime and reliability is everything. Hence, you do NOT do any changes that breaks backwards compatibility. These huge servers have an uptime of many years, even decades (one OpenVMS server had 17 years uptime, Mainframes have decades of uptime, and Unix servers too) and are very complex running lot of software under heavy load. In Enterprise environments, you want stability and no changes, they are VERY conservative. That is the single reason Java is evolving very slowly. Sun said they will not toss in every cool feature because in some years it might be un-cool. Instead, Java’s libraries will evolve very rapidly, but not the language. Great effort has been taken to preserve the byte code, which explains many of the Java 8 design decisions.

    If you come from a desktop environment, you dont care about uptime of decades, no. You just reboot and install the latest patch. And if it breaks – no worries, in worst case you just reinstall everything – and who cares? You dont have 1000s of users on your desktop screaming at you when your PC is down.

    Try to understand that Java is targeted for Enterprise conservative servers (possibly juggling billions of dollars), and C# is targeted to desktop users. Therefore, the design decisions are different.

    C# is suffering from bloat, every hot cool feature is added to C#. In a couple of years you wont use that feature and regret you added it. All Microsofts products suffers from bloat, lean and mean does not exist. Have you seen the Windows API? It is a freak, and a huge bloat. Compare that to the Unix API which is lean and mean in comparison, not bloated. Just like Java.

    Another drawback with C# is that is very slow. Java is very fast, it rivals C++ and in theory it can be faster than C++ with adaptive optimizing compilers. Java scales way better too. There is a reason the largest stock exchanges in the world are written in Java or C++. NASDAQ stock exchange system, the fastest in the world with latency of 100 microseconds, is written in Java.

    London Stock Exchange tried to use an Stock Exchange running on dotnet on Windows which costed 50 millions pounds, but after a few crashes (loosing millions of pounds) LSE scrapped “TradElect” and bought “MilleniumIT” (Linux + Solaris) for another 10s of millions, within a year. And TradeElect running on Windows was slow too.
    Dotnet and Windows is not targeted for Enterprise conservative stable servers. It is targeted for desktops, fast changing environment where stability is not paramount.

    This is the reason C# will never find it’s way into huge servers running stock exchanges with extreme performance and extreme uptime. MS tried, and failed. Because of the design decisions: fast changing language, not stable, too slow, scales bad, etc. All these features that you herald, is the reason that makes C# bad in Enterprise.

    Until you work in such an environment, you will not understand why backwards compatibilty is important.

  46. Avatar  


    June 4, 2014 @ 1:14 pm

    If Microsoft had open sourced C# and the frameworks as Sun did with Java and included the industry in the spec development, there would have been no Java today. C# is just a more narrow platform but does its thing very well.

  47. Avatar  


    July 31, 2014 @ 2:00 pm

    What’s wrong with these people arguing C# vs Java?! It’s even more pathetic than a french forum!

  48. Avatar  

    Slava Semushin

    August 5, 2016 @ 11:19 am

    At the page link to java.util.function API is broken. This is a new one:

    P.S. Other links to are also broken.

RSS feed for comments on this post.

Leave a comment