Java 8

Java 8 introduced several significant features and enhancements to the language, including:

Lambda Expressions:

Lambda expressions enable the writing of more concise and readable code, especially when working with collections. They essentially provide a way to represent one method interface (functional interface) using an expression. This feature facilitates functional programming in Java.

List<String> list = Arrays.asList("node", "java", "python", "ruby");
list.forEach(str -> System.out.println(str)); // lambda expressions

To gain better readability, we can replace lambda expression with method reference.

List<String> list = Arrays.asList("node", "java", "python", "ruby");
list.forEach(System.out::println);// method references

Stream API:

The Stream API provides a powerful way to process collections of objects. It allows for functional-style operations on collections such as map-reduce transformations, filtering, and sorting. Streams promote cleaner, more declarative code.

Functional Interfaces:

Java 8 introduced the @FunctionalInterface annotation, which allows the compiler to enforce the intended use of functional interfaces. A functional interface is an interface with exactly one abstract method, and it can be used as the assignment target for lambda expressions and method references.

UnaryOperator<T>T apply(T t)String::toLowerCaseMath::tan
BinaryOperator<T>T apply(T t1, T t2)BigInteger::addMath::pow
Function<T, R>R apply(T t)Arrays::asListInteger::toBinaryString
Predicate<T, U>boolean test(T t, U u)String::isEmptyCharacter::isDigit
Supplier<T>T get()LocalDate::nowInstant::now
Consumer<T>void accept(T t)System.out::printlnError::printStackTrace

Default Methods in Interfaces:

Interfaces can now have concrete methods (default methods) with an implementation. This feature was introduced to facilitate the evolution of interfaces without breaking existing implementations. It allows interfaces to have new methods added without forcing all implementing classes to implement those methods.

Optional Class:

The Optional class is a container object that may or may not contain a non-null value. It is used to represent optional values instead of using null references. This helps to avoid NullPointerExceptions and makes the code more readable by explicitly expressing the possibility of a value being absent.

Method References:

Method references provide a shorthand syntax for writing lambda expressions when the expression simply calls an existing method. They make code more concise and readable by allowing you to refer to methods directly by their names.

Date and Time API:

Java 8 introduced a new Date and Time API in the java.time package to address the shortcomings of the existing java.util.Date and java.util.Calendar classes. The new API provides better handling of date and time, including support for time zones and formatting.

  • java.time.LocalDate – date without time, no time-zone.
  • java.time.LocalTime – time without date, no time-zone.
  • java.time.LocalDateTime – date and time, no time-zone.
  • java.time.ZonedDateTime – date and time, with time-zone.
  • java.time.DateTimeFormatter – formatting (date -> text), parsing (text -> date) for java.time.
  • java.time.Instant – date and time for machine, seconds passed since the Unix epoch time (midnight of January 1, 1970 UTC)
  • java.time.Duration – Measures time in seconds and nanoseconds.
  • java.time.Period – Measures time in years, months and days.
  • java.time.TemporalAdjuster – Adjust date.
  • java.time.OffsetDateTime.

These features collectively made Java programming more expressive, concise, and efficient, encouraging developers to write cleaner and more maintainable code.