Search

Showing posts with label Java 8. Show all posts
Showing posts with label Java 8. Show all posts

Terminating operations , Collectors - java 8 features

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.

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 = persons.stream()
    .filter(p -> p.getAge() > 18)
    .map(Adult::new)
    .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 = persons.stream()
    .filter(p -> p.getAge() > 18)
    .map(Student::new)
    .collect(Collectors.toList());
Or in case if we would like to use a specific collection implementation for collecting the results:
List students = persons.stream()
    .filter(p -> p.getAge() > 18)
    .map(Student::new)
    .collect(Collectors.toCollection(ArrayList::new));

Java 8 Roadmap

JDK 8 is a superset of JRE 8, and contains everything that is in JRE 8, plus tools such as the compilers and debuggers necessary for developing applets and applications. JRE 8 provides the libraries, the Java Virtual Machine (JVM), and other components to run applets and applications written in the Java programming language. Note that the JRE includes components not required by the Java SE specification, including both standard and non-standard Java components.
The following conceptual diagram illustrates the components of Oracle's Java SE products:
Description of Java Conceptual Diagram
JDK

Java Language
Java Language

Tools &
Tool APIs
java
javac
javadoc
jar
javap
Scripting
Security
Monitoring
JConsole
VisualVM
JMC
JFR
JPDA
JVM TI
IDL
RMI
Java DB
Deployment
Internationalization
Web Services
Troubleshooting
JRE
Deployment
Java Web Start
Applet / Java Plug-in
User Interface
Toolkits
JavaFX
Swing
Java 2D
AWT
Accessibility
Drag and Drop
Input Methods
Image I/O
Print Service
Sound
Java SE
API
Integration
Libraries
IDL
JDBC
JNDI
RMI
RMI-IIOP
Scripting
Other Base
Libraries
Beans
Security
Serialization
Extension Mechanism
JMX
XML JAXP
Networking
Override Mechanism
JNI
Date and Time
Input/Output
Internationalization
lang and util
Base Libraries
lang and util
Math
Collections
Ref Objects
Regular Expressions
Logging
Management
Instrumentation
Concurrency Utilities
Reflection
Versioning
Preferences API
JAR
Zip
Java Virtual Machine
Java HotSpot Client and Server VM



Other miscellaneous additions to java.lang, java.util, and elsewhere - java 8 features

There are lot of other additions to other packages we have not yet mentioned. Here are a few of the notable ones. ThreadLocal.withInitial(Supplier) allows for a more compact thread-local variable declaration. The long overdue StringJoiner and String.join(...) are now part of Java 8. Comparator provides some new methods for doing chained and field-based comparisons. The default String pool map size is bigger at around 25-50K.

There is too much there to talk about, but I'll pick out a few noteworthy items.
ThreadLocal.withInitial(Supplier<T>) makes declaring thread-local variables with initial values much nicer. Previously you would supply an initial value like this:
ThreadLocal<List<String>> strings =
    new ThreadLocal<List<String>>() {
        @Override
        protected List<String> initialValue() {
             return new ArrayList<>();
        }
    };
Now it's like this:
ThreadLocal<List<String>> strings =
    ThreadLocal.withInital(ArrayList::new);
Optional<T> appears in the stream API as the return value for methods like min/max, findFirst/Any, and some forms of reduce. It's used because there might not be any elements in the stream, and it provides a fluent API for handling the "some result" versus "no result" cases. You can provide a default value, throw an exception, or execute some action only if the result exists.
It's very, very similar to Guava's Optional class. It's nothing at all like Option in Scala, nor is it trying to be, and the name similarity there is purely coincidental.
Aside: it's interesting that Java 8's Optional and Guava's Optional ended up being so similar, despite the absurd amount of debate that occurred over its addition to both libraries.
"FYI.... Optional was the cause of possibly the single greatest conflagration on the internal Java libraries discussion lists ever."
"On a purely practical note, the discussions surrounding Optional have exceeded its design budget by several orders of magnitude."
StringJoiner and String.join(...) are long, long overdue. They are so long overdue that the vast majority of Java developers likely have already written or have found utilities for joining strings, but it is nice for the JDK to finally provide this itself. Everyone has encountered situations where joining strings is required, and it is a Good Thing™ that we can now express that through a standard API that every Java developer (eventually) will know.
Comparator provides some very nice new methods for doing chained comparisons and field-based comparisons. For example:
people.sort(
    Comparator.comparing(Person::getLastName)
        .thenComparing(Person::getFirstName)
        .thenComparing(
            Person::getEmailAddress,
            Comparator.nullsLast(CASE_INSENSITIVE_ORDER)));
These additions provide good, readable shorthand for complex sorts. Many of the use cases served by Guava's ComparisonChain and Ordering utility classes are now served by these JDK additions. And for what it's worth, I think the JDK verions read better than the functionally-equivalent versions expressed in Guava-ese.