> For the complete documentation index, see [llms.txt](https://tingreavinash.gitbook.io/the-tech-toolbox/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tingreavinash.gitbook.io/the-tech-toolbox/notes/java-fundamentals/java-8-features.md).

# Java 8 Features

### Lambda Expressions

* A lambda expression is a concise way to represent an anonymous function.
* It consists of a parameter list, an arrow (->), and a body.
* Example:

  ```java
  Runnable runnable = () -> System.out.println("Hello World");
  ```

### Functional Interfaces

* A functional interface is an interface that has exactly one abstract method.
* They can be used as the target type for lambda expressions and method references.
* Java 8 provides several built-in functional interfaces in the `java.util.function` package, such as `Predicate`, `Function`, and `Supplier`.
* Example:

  ```java
  Predicate<String> predicate = s -> s.length() > 0;
  ```

### Method References

* A method reference is a shorthand notation for a lambda expression that calls a method.
* There are four types of method references:
  1. Reference to a static method: `ContainingClass::staticMethodName`
  2. Reference to an instance method of a particular object: `object::instanceMethodName`
  3. Reference to an instance method of an arbitrary object of a particular type: `ContainingType::methodName`
  4. Reference to a constructor: `ClassName::new`
* Example:

  ```java
  Function<String, Integer> parseInt = Integer::parseInt;
  ```

### Streams

* A stream is a sequence of elements that can be processed in parallel or sequentially.
* They can be created from a collection, an array, or by using the `Stream.of` method.
* Stream operations can be either intermediate or terminal. Intermediate operations return a new stream and allow for chaining of operations, while terminal operations produce a result or a side-effect.
* Example:

  ```java
  List<String> names = Arrays.asList("John", "Jane", "Joe");
  names.stream().filter(name -> name.startsWith("J")).forEach(System.out::println);
  ```

### Optional

* An `Optional` is a container object that may or may not contain a non-null value.
* It can be used as a return type or as a field of a class.
* It provides methods for checking if a value is present and for retrieving the value if it is.
* Example:

  ```java
  Optional<String> optional = Optional.ofNullable(getName());
  optional.ifPresent(name -> System.out.println("Hello " + name));
  ```

### Date/Time API

* The new Date/Time API provides a better way to represent, manipulate, and format dates and times.
* The key classes are `LocalDate`, `LocalTime`, `LocalDateTime`, and `ZonedDateTime`.
* It provides methods for parsing and formatting dates and times.
* Example:

  ```java
  LocalDateTime now = LocalDateTime.now();
  DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  String formattedDate = now.format(formatter);
  System.out.println(formattedDate);
  ```

### Default and Static Methods in Interfaces

* Java 8 introduced default and static methods in interfaces.
* Default methods provide a default implementation that can be overridden by implementing classes.
* Static methods can be used in interfaces to provide utility methods.
* Example:

  ```java
  interface MyInterface {
      default void sayHello() {
          System.out.println("Hello");
      }
      static void printVersion() {
          System.out.println("Version 1.0");
      }
  }
  ```

### Concurrency Enhancements

* Java 8 introduced several enhancements to the concurrency API.
* The `CompletableFuture` class provides a way to represent and manipulate asynchronous computations.
* The `ConcurrentHashMap` class provides a thread-safe way to store key-value pairs.
* The `Atomic` classes provide a way to perform atomic operations on primitive data types.
* The `Parallel Streams` feature enables parallel processing of streams to improve performance.
* Example:

  ```java
  CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello World")
          .thenApply(s -> s.toUpperCase())
          .thenCombine(CompletableFuture.completedFuture("!"), (s1, s2) -> s1 + s2);
  System.out.println(future.get());
  ```
