[Java] A note about Java’s Stream API and SQL

2 minute read

A note about Java’s Stream API versus SQL.

Stream official documentation

Excerpts from the official Java 8 documentation. https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html

A sequence of elements that supports sequential and parallel aggregate operations. (Omitted) Although collections and streams are similar in appearance, they have different purposes. Collections are primarily focused on efficiently managing and accessing elements. Streams, on the other hand, have no direct means of accessing or manipulating elements, but instead focus on declaratively describing sources and computational operations that are performed centrally on those sources. (Omitted) Stream pipelines can run either sequentially or in parallel. This execution mode is one of the properties of the stream. When creating a stream, an initial selection is made for sequential or parallel execution.

It’s hard to understand even if I read the document because I don’t have enough understanding, but if I write it roughly, it looks like this.

  • Similar to collection
  • Do aggregate operations
  • It does not directly access or operate (get, remove) elements
  • Process can be selected sequentially or in parallel

Aggregation operation will be faster to understand if you can imagine SQL.

Stream API and SQL comparison list

|Stream API|Corresponding SQL|Description| |:—|:—|:—| An operation to convert the elements in |Stream#map|SELECT|Stream to another value or object | |Stream#filter|WHERE| Operation to filter only the data that matches the conditions. It is necessary to write an expression whose return value is boolean as an argument. | |Stream#max|MAX|Get maximum value| |Stream#min|MIN|Get minimum value| |IntStream#sum
Collectors#summingInt|SUM|Get totals|

Sample code

Prerequisites

  • Assuming that lombok plugin is installed
  • Scope is suitable

Person data and class

A table that stores person data and a class that retains that data are defined as follows.

■Person table

id name age job
1 yamada 25 —:
2 suzuki 28 —:
3 sato 30 —:
4 nakamura 41 —:
5 yamamoto 38 —:
6 akiyama 22 —:
7 tanabe 43 —:
8 ito 24 —:

■Person class

Persion.java


@Data
@AllArgsConstructor
public class Person {
    private int id;
    private String name;
    private int age;
}

Furthermore, a list that stores all the data of the Person table is defined as List<Person>. List<Person> is synonymous with

List<Person> personList = Arrays.asList(
    new Person(1, "yamada", 25),
    new Person(2, "suzuki", 28),
    new Person(3, "sato", 30))
    new Person(4, "nakamura", 41))
    new Person(5, "yamamoto", 38))
    new Person(6, "akiyama", 22))
    new Person(7, "tanabe", 43))
    new Person(8, "ito", 24))
);

Stream#map

Java


List<String> nameList = personList.stream()
        .map(Person::getName)
      .collect(Collectors.toList());

SQL


SELECT
  p.name
FROM
  Person p

["yamada", "suzuki", "sato", "nakamura, "yamamoto", "akiyama", "tanabe", ito] ## Stream#filter #### **`Java`** ```java List nameList = personList.stream() .filter(p -> p.getAge() >= 40) .map(Person::getName) .collect(Collectors.toList()); ``` #### **`SQL`** ```sql SELECT p.name FROM Person p WHERE p.age >= 40 ``` ["nakamura", "tanabe"] ## Stream#max #### **`Java`** ```java Integer max = personList.stream() .map(Person::getAge) .max(Comparator.comparingInt(x -> x)) .orElse(null); ``` #### **`SQL`** ```sql SELECT max(p.age) max_age FROM Person p ``` 43 ## Stream#min #### **`Java`** ```java Integer max = personList.stream() .map(Person::getAge) .min(Comparator.comparingInt(x -> x)) .orElse(null); ``` #### **`SQL`** ```sql SELECT min(p.age) min_age FROM Person p ``` twenty two ## IntStream#sum/Collectors#summingInt #### **`Java`** ```java int sum = personList.stream() .mapToInt(Persion::getAge) .sum(); int sum2 = personList.stream() .collect(Collectors.summingInt(Persion::getAge)); ``` #### **`SQL`** ```sql SELECT sum(p.age) sum_age FROM Person p ``` 251