Advanced Java Concepts
Welcome to the final part of the Learn Java series! In this section, we will explore some advanced Java concepts that are crucial for mastering the language. We will cover topics such as concurrency, generics, lambda expressions, and streams. These concepts will help you write more efficient, scalable, and modern Java applications.
Concurrency
Concurrency allows multiple tasks to run simultaneously, improving the efficiency and performance of your applications. Java provides several ways to handle concurrency:
Threads
In Java, you can create and manage threads using the Thread
class or implementing the Runnable
interface. Here’s an example of creating and running a thread:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread is running.");
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
This code defines a class MyRunnable
that implements Runnable
and overrides the run()
method. In the Main
class, a Thread
object is created with an instance of MyRunnable
and started.
Executors
Executors provide a higher-level API for managing and controlling thread execution. Here’s an example using the ExecutorService
:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> {
System.out.println("Task 1 is running.");
});
executor.submit(() -> {
System.out.println("Task 2 is running.");
});
executor.shutdown();
}
}
In this example, an ExecutorService
is created with a fixed thread pool of 2 threads. Two tasks are submitted to the executor, and then the executor is shut down.
Generics
Generics allow you to define classes, interfaces, and methods with type parameters. This enables type safety and code reusability. Here’s an example of a generic class:
public class Box {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
public class Main {
public static void main(String[] args) {
Box stringBox = new Box<>();
stringBox.setItem("Hello Generics");
System.out.println(stringBox.getItem()); // Output: Hello Generics
}
}
The Box
class is a generic class that can hold an item of any type T
. In the Main
class, a Box
object is created with the type parameter String
.
Lambda Expressions
Lambda expressions provide a concise way to write anonymous methods, primarily used with functional interfaces. Here’s an example of using a lambda expression:
@FunctionalInterface
interface MathOperation {
int operate(int a, int b);
}
public class Main {
public static void main(String[] args) {
MathOperation addition = (a, b) -> a + b;
System.out.println("Result: " + addition.operate(5, 3)); // Output: Result: 8
}
}
In this example, MathOperation
is a functional interface with a single method operate
. A lambda expression is used to provide an implementation for the operate
method.
Streams
Streams provide a modern way to process sequences of elements (e.g., collections) using functional-style operations. Here’s an example of using streams to filter and process a list of numbers:
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.forEach(System.out::println);
}
}
In this example, a list of numbers is converted into a stream. The stream filters out odd numbers, squares the remaining even numbers, and prints each result.
Conclusion
In this lesson, we explored several advanced Java concepts, including concurrency, generics, lambda expressions, and streams. Mastering these topics will enable you to write more efficient, scalable, and modern Java applications. Continue practicing and experimenting with these concepts to deepen your understanding and enhance your Java programming skills.