Since 1995, Java has changed our
world . . . and our expectations.
In the early 90s, extending the
power of network computing to the activities of everyday life was a radical
vision. In 1991, a small group of Sun engineers called the "Green
Team" believed that the next wave in computing was the union of digital
consumer devices and computers. Led by James Gosling, the team worked around
the clock and created the programming language that would revolutionize our
world – Java.
Java 8 the most anticipated version
of Java ever & is just around the corner! This long-awaited release has
been scheduled for March 18th, 2014.
New features of JAVA 8...
Streams
Streams are not meant to replace
ArrayLists or other collections. They are only meant to make manipulating the
data easier and faster. A stream is a one-time-use Object. Once it has been
traversed, it cannot be traversed again. Streams have the ability to filter,
map, and reduce while being traversed. There are two "modes" for a
stream: sequential and parallel.
Using a sequential stream:
List<Person> people = list.getStream.collect(Collectors.toList());
Using a parallel stream:
List originalList = someData;
split1 = originalList(0, mid);
split2 = originalList(mid,end);
new Runnable(split1.process());
new Runnable(split2.process());
List revisedList = split1 + split2;
The above example shows how the parallel
Stream would be processed and how it will take advantage of multiple core
processors.
Lambda
Lambda support is one of the most
visible enhancements in Java 8. A lambda expression is a function-a bit of
code-that you can pass to another method as an argument. Thus, you can cope
with changing requirements by using behaviour, represented by a lambda, as a
parameter. Java 8's functional programming features, like lambdas and the new
Stream API that enables a cleaner way to iterate through collections, can help
you write concise code that scales easily and performs well on multiple core
architectures.
E.g. we can write the following code in Java 8 to get a map of people’s names grouped by age.
Java 8
Stream<Person> people = Stream.of(new
Person("Ramesh", 24), new Person("Suresh", 30), new
Person("Mahesh", 28));
Map<Integer, List<String>> peopleByAge = people.collect(groupingBy(p -> p.age, mapping((Person p) -> p.name, toList())));
System.out.println(peopleByAge);
Map<Integer, List<String>> peopleByAge = people.collect(groupingBy(p -> p.age, mapping((Person p) -> p.name, toList())));
System.out.println(peopleByAge);
Output
{24=[Ramesh], 28=[Mahesh], 30=[Suresh]}
{24=[Ramesh], 28=[Mahesh], 30=[Suresh]}
We’re running the ‘collect’ function
over the collection, grouping by the ‘age’ property as we go and grouping the
names of people rather than the people themselves.
E.g. Sort list of people in
ascending order of their age.
Java 7
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.age - o2.age;
}
});
for (Person person : people) {
System.out.println(person);
}
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.age - o2.age;
}
});
for (Person person : people) {
System.out.println(person);
}
Java 8
List<Person> people = Arrays.asList(new Person("Ramesh", 24),new Person("Suresh", 30),new Person("Mahesh", 28));
people.stream().sorted((p1, p2) -> p1.age - p2.age).forEach(System.out::println);
List<Person> people = Arrays.asList(new Person("Ramesh", 24),new Person("Suresh", 30),new Person("Mahesh", 28));
people.stream().sorted((p1, p2) -> p1.age - p2.age).forEach(System.out::println);
Output
Person{name='Ramesh', age=24}
Person{name='Mahesh', age=28}
Person{name='Suresh', age=30}
Person{name='Ramesh', age=24}
Person{name='Mahesh', age=28}
Person{name='Suresh', age=30}
E.g. Lambdas will clean your
listener code.
Java 7
button.addClickListener(new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
// Your code here
}
});
button.addClickListener(new Button.ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
// Your code here
}
});
Java 8
button.addClickListener(e->System.out.println("Yes, it works"));
button.addClickListener(e->System.out.println("Yes, it works"));
Interface improvements
Interfaces can now define static
methods.
For example, java.util.Comparator
now has a static naturalOrder method.
public static <T extends Comparable<? super T>>
Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}
Interfaces can now provide default
methods. This allows programmers to add new methods without breaking existing
code that implements the interface.
For example, java.lang.Iterable now
has a default forEach method.
public default void forEach(Consumer<? super T> action)
{
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
Generic type inference improvements
This improves the ability of the
Java compiler to infer generic types and reduce explicit type-arguments in
generic method calls.
In Java 7, the code looks something
like this:
foo(Utility.<Type>bar());
Utility.<Type>foo().bar();
Utility.<Type>foo().bar();
In Java 8, improved inference in arguments and in chained calls allows you to write something like this:
foo(Utility.bar());
Utility.foo().bar();
Nashorn
Nashorn is the new, lightweight,
high-performance implementation of JavaScript integrated into the JDK. Nashorn
is the successor to Rhino, with improved performance and memory usage. It will
support the javax.script API, but will not include support for DOM/CSS nor
include a browser plugin API.
Java time
The new date/time API is contained
in the java.time package. All the classes are immutable and thread-safe. The
date and time types include Instant, LocalDate, LocalTime, LocalDateTime and
ZonedDateTime. Beyond dates and times, there are also the Duration and Period
types. Additional value types include Month, DayOfWeek, Year, Month, YearMonth,
MonthDay, OffsetTime and OffsetDateTime. Most of these new date/time classes
are supported by JDBC.
java.util.function
A large number of new functional
interfaces have been added to the java.util.function package. Here are a few
examples:
• Function<T, R> - take T as input, return R as output
• Predicate<T> - take T as input, return a boolean as output
• Consumer<T> - take T as input, don't return anything
• Supplier<T> - take no input, return T
• BinaryOperator<T> - take two T's as input, return one T as output.
Functional interfaces
A functional interface is an
interface that defines exactly one abstract method. The FunctionalInterface
annotation has been introduced to indicate that an interface is intended to be
a functional interface.
For example, java.lang.Runnable is a
functional interface.
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
public interface Runnable {
public abstract void run();
}
Note that the Java compiler will
treat any interface meeting the definition as a functional interface regardless
of whether or not the functional interface annotation is present.
And Lot More...
There are lot of other additions
like Collections API’s, Concurrency API’s, IO/NIO API’s, and Reflection
changes. Addition of new methods like ThreadLocal.withInitial(Supplier) which
allows for a more compact thread-local variable declarations. The long overdue
StringJoiner and String.join(...) are now part of Java 8.
Where it may lose the battle?
Maintainability and readability is
commonly way more important than the amount of code.
In a functional interface, default
methods are added to an interface and do not have to be overridden in the
interface implementation. These methods can be run directly from the interface.
< !--[if !supportLineBreakNewLine]-->
< !--[endif]-->
< !--[if !supportLineBreakNewLine]-->
< !--[endif]-->
This was done for backward
compatibility for collections in interfaces. It is to solve the problem of
allowing the Stream to be put into an interface without having to change all of
the classes to implement the new method. If the default method is not correct
for the implementation, it can be overridden in the implementer. What this
essentially does is allow a form of multiple inheritance. This becomes the
implementer's problem, as the implementer will be required to override the
method anyway. The implementer could then choose which super method to use, but
this means a lot of classes that implement interfaces could still be changed.
This is probably the detail that will concern most people in Java 8.
Not surprising, the Scala community
is incredulous because many of Java 8's additions merely look like Scala
replacing the => operator with ->. In some cases, Java 8's syntax has
been pointed out to be more verbose or less clear than Scala's. It's yet to be
determined what, if anything, it will do to languages like Scala that are built
around Lambda expressions.
On the one hand, if Java continues to evolve and implement everything around Lambda as Scala has done, then there may be no need for Scala. On the other hand, if it is left alone to provide only core functionality, such as helping with anonymous inner classes, then Scala and other languages will continue to thrive and ride on top of Java as they do now. This is the best outcome; it will allow other languages to continue to grow and be inventive without worrying about whether or not they will become obsolete.
Conclusion
Java 8 is a much better language
from the developer perspective than any version of Java before. It won’t remove
all those complaints about verbosity and not having all the features that
coding humanity has come up with so far. However, the introduction of lambda
expressions and first-class methods makes programming much more enjoyable.
No comments:
Post a Comment