Imperative vs Declarative Programming Styles in Java

Imperative programming and declarative programming are two different programming paradigms with distinct approaches to solving problems.

Imperative programming is a programming paradigm that focuses on how to achieve a specific goal. It consists of a series of instructions or statements to achieve the desired outcome. Imperative programming is closer to how humans think and is the most common programming paradigm in languages like C, C++ and Java.

Declarative programming, on the other hand, focuses on what needs to be achieved, rather than how to achieve it. It specifies a set of rules or constraints and lets the compiler (or the underlying system) figure out exactly how to reach the desired outcome. Declarative programming is often more concise and easier to read, but can be less flexible than imperative programming.

Imperative programming has its roots in assembly language where we need to exactly spell out each operation that we want executed. It evolved into structured programming languages, such as C and Pascal, and object-oriented languages, such as Java and C++.

Declarative programming has its roots in logic programming, which uses a set of rules to derive conclusions from facts. It evolved into functional programming languages, such as Haskell and Lisp, and declarative languages, such as SQL. Examples of declarative programming include functional programming and database query languages.

For example, to loop through an array find even numbers, and multiply each by 2 to create a new array, here’s how we’d do it traditionally in Java using imperative style of programming:

public static int[] findAndDoubleEvenNumbers(int[] arr) {
    int[] result = new int[arr.length];
    int index = 0;
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] % 2 == 0) {
            result[index] = arr[i] * 2;
            index++;
        }
    }
    return Arrays.copyOf(result, index);
}

We’ll see later how to write this same code using declarative style. But for now, here’s an example of declarative programming in SQL, which selects all the customers who have made a purchase in the last 15 days:

SELECT *
FROM customers
WHERE last_purchase_date >= DATE_SUB(NOW(), INTERVAL 30 DAY);

Here, we specified what data is desired without explicitly stating how to obtain it. The query selects all records where the last_purchase_date is within the last 15 days. It does not provide instructions on how to retrieve this data or what algorithms to use to filter the records. Instead, it defines a logical constraint or rule that the RDBMS uses to execute the query and return the desired results. The declarative approach of SQL allows developers to focus on the desired outcome, rather than the implementation details, making queries more concise and easier to read.

Java and Declarative Style

Java is not typically considered a declarative language, as its syntax and features are primarily geared towards imperative and object-oriented programming. However, starting with Java 8, we can write certain parts of our code in a more declarative style. For example, we can write our previous example in a declarative style:

public static int[] findAndDoubleEvenNumbers(int[] arr) {
    return Arrays.stream(arr)
        .filter(num -> num % 2 == 0)
        .map(num -> num * 2)
        .toArray();
}

Here, we first create a stream from the input array using Arrays.stream(). We then use the filter() operation to keep only the even numbers in the stream, and the map() operation to double each even number. Finally, we use the toArray() operation to collect the elements of the stream into an array.

This code is more declarative than the original code since we do not specify the exact steps to be taken to find and double the even numbers. Instead, we described the desired output in terms of higher-level operations on a stream of data. This makes the code more expressive, concise, and easier to read and understand.

Speak Your Mind