Interview Questions Java 8 introduced several significant features and enhancements to the language and its core libraries. These features aimed to improve productivity, enhance performance, and promote functional programming paradigms. Here are some key Java 8 features with examples:
1. Lambda Expressions
Lambda expressions enable functional programming in Java by allowing you to treat functionality as a method argument or create anonymous functions.
Example: Sorting with Comparator using Lambda
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Prior to Java 8
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
// With Lambda expression
Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
// Using forEach and Lambda
names.forEach(name -> System.out.println(name));
2. Stream API
The Stream API provides a new way to process data in Java by leveraging functional programming principles. It enables sequential or parallel processing of collections.
Example: Filtering and Collecting with Streams
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Filtering names starting with 'A' and collecting to a new list
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
// Using parallel stream for concurrent processing
names.parallelStream()
.forEach(name -> System.out.println(name));
3. Functional Interfaces
Functional interfaces have a single abstract method and can be used as lambda expressions. They are annotated with @FunctionalInterface.
Example: Functional Interface and Lambda Expression
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}
public class Main {
public static void main(String[] args) {
// Lambda expression to implement the calculate method
Calculator add = (a, b) -> a + b;
System.out.println("Addition: " + add.calculate(5, 3));
}
}
4. Method References
Method references provide a shorthand notation for Lambda expressions to refer to methods or constructors.
Example: Method Reference
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Prior to Java 8
names.forEach(name -> System.out.println(name));
// Using Method Reference
names.forEach(System.out::println);
5. Default Methods in Interfaces
Interfaces can have methods with a default implementation. This feature facilitates backward compatibility by allowing interfaces to evolve without breaking existing implementations.
Example: Default Method in Interface
interface Greeting {
default void greet() {
System.out.println("Hello, world!");
}
}
class GreetingImpl implements Greeting {
// No need to implement greet() here
}
public class Main {
public static void main(String[] args) {
Greeting greeting = new GreetingImpl();
greeting.greet(); // Output: Hello, world!
}
}
6. Optional Class
The Optional class is a container object used to represent optional values. It helps to avoid null pointer exceptions.
Example: Using Optional
Optional<String> name = Optional.ofNullable(null);
// Checking if value is present
if (name.isPresent()) {
System.out.println("Name: " + name.get());
} else {
System.out.println("Name not provided.");
}
7. Date and Time API (java.time)
The new Date and Time API (java.time) provides a more comprehensive way to handle date and time values.
Example: Date and Time API
import java.time.*;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Creating a LocalDate
LocalDate date = LocalDate.now();
System.out.println("Current Date: " + date);
// Formatting a LocalDate
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
String formattedDate = date.format(formatter);
System.out.println("Formatted Date: " + formattedDate);
}
}
8. CompletableFuture
The CompletableFuture class provides a powerful way to work with asynchronous computations and handle dependencies among tasks.
Example: CompletableFuture
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(s -> s + " World");
System.out.println(future.get()); // Output: Hello World
}
}
9. Stream API Enhancements
Java 8 introduced several enhancements to the Stream API, including forEach, map, filter, reduce, and collect.
Example: Stream API Enhancements
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Using forEach to print each name
names.forEach(System.out::println);
// Using map to transform elements
List<String> upperCaseNames = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
// Using reduce to concatenate all names
String concatenatedNames = names.stream()
.reduce("", (s1, s2) -> s1 + " " + s2);
System.out.println("Concatenated Names: " + concatenatedNames);