├── .gitignore ├── README.MD ├── blob └── Data_Model.jpg ├── pom.xml └── src ├── main ├── java │ └── space │ │ └── gavinklfong │ │ └── demo │ │ └── streamapi │ │ ├── AppCommandRunner.java │ │ ├── DemoApplication.java │ │ ├── models │ │ ├── Customer.java │ │ ├── Order.java │ │ └── Product.java │ │ └── repos │ │ ├── CustomerRepo.java │ │ ├── OrderRepo.java │ │ └── ProductRepo.java └── resources │ ├── application.properties │ ├── data.sql │ └── table_script.ddl ├── site └── site.xml └── test ├── java └── space │ └── gavinklfong │ └── demo │ └── streamapi │ └── StreamApiTest.java └── resources └── application.properties /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.versionsBackup 5 | pom.xml.next 6 | release.properties 7 | dependency-reduced-pom.xml 8 | buildNumber.properties 9 | .mvn/timing.properties 10 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 11 | .mvn/wrapper/maven-wrapper.jar 12 | /.metadata/ 13 | .idea 14 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # Java Stream API Exercises 2 | 3 | ## Introduction 4 | 5 | This GitHub project was created to serve as a playground for practicing Java Stream API. There are 15 exercises which introduce the API usage including filtering, transformation, sorting and the output to various formats. 6 | 7 | It is a Spring Boot project with a example data model, repositories and a set of pre-defined data. The system automatically loads data into H2 in-memory database when the Spring Boot app starts up. Therefore, you can fetch data from database by calling repositories and experiment the usage of Java Stream API. 8 | 9 | ## IDE Setup 10 | 11 | This project depends on Lombok Library which is an awesome code auto generation tool, it greatly simplify the source code. Read [this article](https://blog.devgenius.io/how-to-magically-speed-up-java-coding-76fa1a68e0f4) if you would like to know more about the usage. 12 | 13 | To configure your IDE for the support of Lombok, check out [the official documentation](https://projectlombok.org/setup/overview) for detail. 14 | 15 | ## Data Model 16 | 17 | The example data model consists of Customer, Order and Product. Customers can place multiple orders and each order would contain a number of products. 18 | 19 | ![Data Model](https://github.com/gavinklfong/stream-api-exercises/blob/main/blob/Data_Model.jpg?raw=true) 20 | 21 | ## Exercises 22 | 23 | The exercises and the sample solutions can be found in test source `space.gavinklfong.demo.streamapi.StreamApiTest` 24 | 25 | You may refer to this article for detail walk through about the exercises. 26 | 27 | [15 Practical Exercises Help You Master Java Stream API](https://medium.com/dev-genius/15-practical-exercises-help-you-master-java-stream-api-3f9c86b1cf82) 28 | -------------------------------------------------------------------------------- /blob/Data_Model.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gavinklfong/stream-api-exercises/ca14b6f438ac9d58911b635a26fc0591fa2ad8e8/blob/Data_Model.jpg -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.4.5 9 | 10 | 11 | space.gavinklfong.demo 12 | streamapi 13 | 0.0.1-SNAPSHOT 14 | demo 15 | Exercises for Java Stream API 16 | 17 | 11 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-data-jpa 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-devtools 31 | runtime 32 | true 33 | 34 | 35 | com.h2database 36 | h2 37 | runtime 38 | 39 | 40 | org.projectlombok 41 | lombok 42 | true 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-test 47 | test 48 | 49 | 50 | 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-maven-plugin 56 | 57 | 58 | 59 | org.projectlombok 60 | lombok 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/space/gavinklfong/demo/streamapi/AppCommandRunner.java: -------------------------------------------------------------------------------- 1 | package space.gavinklfong.demo.streamapi; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.stereotype.Component; 7 | import space.gavinklfong.demo.streamapi.repos.CustomerRepo; 8 | import space.gavinklfong.demo.streamapi.repos.OrderRepo; 9 | import space.gavinklfong.demo.streamapi.repos.ProductRepo; 10 | 11 | import javax.transaction.Transactional; 12 | 13 | @Slf4j 14 | @Component 15 | public class AppCommandRunner implements CommandLineRunner { 16 | 17 | @Autowired 18 | private CustomerRepo customerRepos; 19 | 20 | @Autowired 21 | private OrderRepo orderRepos; 22 | 23 | @Autowired 24 | private ProductRepo productRepos; 25 | 26 | @Transactional 27 | @Override 28 | public void run(String... args) throws Exception { 29 | log.info("Customers:"); 30 | customerRepos.findAll() 31 | .forEach(c -> log.info(c.toString())); 32 | 33 | log.info("Orders:"); 34 | orderRepos.findAll() 35 | .forEach(o -> log.info(o.toString())); 36 | 37 | log.info("Products:"); 38 | productRepos.findAll() 39 | .forEach(p -> log.info(p.toString())); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/space/gavinklfong/demo/streamapi/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package space.gavinklfong.demo.streamapi; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/space/gavinklfong/demo/streamapi/models/Customer.java: -------------------------------------------------------------------------------- 1 | package space.gavinklfong.demo.streamapi.models; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.GenerationType; 6 | import javax.persistence.Id; 7 | import javax.persistence.Table; 8 | 9 | import lombok.AllArgsConstructor; 10 | import lombok.Builder; 11 | import lombok.Data; 12 | import lombok.NoArgsConstructor; 13 | 14 | @Builder 15 | @Data 16 | @Entity 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @Table 20 | public class Customer { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | private Long id; 25 | 26 | private String name; 27 | 28 | private Integer tier; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/space/gavinklfong/demo/streamapi/models/Order.java: -------------------------------------------------------------------------------- 1 | package space.gavinklfong.demo.streamapi.models; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | import java.time.LocalDate; 7 | import java.util.Set; 8 | 9 | @Builder 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @Entity 14 | @Table(name = "product_order") 15 | public class Order { 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.IDENTITY) 19 | private Long id; 20 | 21 | @Column(name="order_date") 22 | private LocalDate orderDate; 23 | 24 | @Column(name="delivery_date") 25 | private LocalDate deliveryDate; 26 | 27 | private String status; 28 | 29 | @ManyToOne 30 | @JoinColumn(name = "customer_id") 31 | private Customer customer; 32 | 33 | @ManyToMany 34 | @JoinTable( 35 | name = "order_product_relationship", 36 | joinColumns = { @JoinColumn(name = "order_id") }, 37 | inverseJoinColumns = { @JoinColumn(name = "product_id") } 38 | ) 39 | @ToString.Exclude 40 | @EqualsAndHashCode.Exclude 41 | Set products; 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/space/gavinklfong/demo/streamapi/models/Product.java: -------------------------------------------------------------------------------- 1 | package space.gavinklfong.demo.streamapi.models; 2 | 3 | import java.util.Set; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | import javax.persistence.ManyToMany; 10 | import javax.persistence.Table; 11 | 12 | import lombok.AllArgsConstructor; 13 | import lombok.Builder; 14 | import lombok.Data; 15 | import lombok.EqualsAndHashCode; 16 | import lombok.NoArgsConstructor; 17 | import lombok.ToString; 18 | import lombok.With; 19 | 20 | @Builder 21 | @Data 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | @Entity 25 | @Table 26 | public class Product { 27 | 28 | @Id 29 | @GeneratedValue(strategy = GenerationType.IDENTITY) 30 | private Long id; 31 | 32 | private String name; 33 | 34 | private String category; 35 | 36 | @With 37 | private Double price; 38 | 39 | @ManyToMany(mappedBy = "products") 40 | @ToString.Exclude 41 | @EqualsAndHashCode.Exclude 42 | private Set orders; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/space/gavinklfong/demo/streamapi/repos/CustomerRepo.java: -------------------------------------------------------------------------------- 1 | package space.gavinklfong.demo.streamapi.repos; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import space.gavinklfong.demo.streamapi.models.Customer; 9 | 10 | @Repository 11 | public interface CustomerRepo extends CrudRepository { 12 | 13 | List findAll(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/space/gavinklfong/demo/streamapi/repos/OrderRepo.java: -------------------------------------------------------------------------------- 1 | package space.gavinklfong.demo.streamapi.repos; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import space.gavinklfong.demo.streamapi.models.Order; 9 | 10 | @Repository 11 | public interface OrderRepo extends CrudRepository { 12 | 13 | List findAll(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/space/gavinklfong/demo/streamapi/repos/ProductRepo.java: -------------------------------------------------------------------------------- 1 | package space.gavinklfong.demo.streamapi.repos; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import space.gavinklfong.demo.streamapi.models.Product; 9 | 10 | @Repository 11 | public interface ProductRepo extends CrudRepository { 12 | 13 | List findAll(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.hibernate.ddl-auto=update 2 | spring.datasource.url = jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE 3 | 4 | spring.jpa.show-sql=false 5 | spring.jpa.properties.hibernate.generate_statistics=false 6 | spring.jpa.properties.hibernate.show_sql=false 7 | -------------------------------------------------------------------------------- /src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO customer (id, name, tier) VALUES (1, 'Stefan Walker', 1); 2 | INSERT INTO customer (id, name, tier) VALUES (2, 'Daija Von', 1); 3 | INSERT INTO customer (id, name, tier) VALUES (3, 'Ariane Rodriguez', 1); 4 | INSERT INTO customer (id, name, tier) VALUES (4, 'Marques Nikolaus', 2); 5 | INSERT INTO customer (id, name, tier) VALUES (5, 'Rachelle Greenfelder', 0); 6 | INSERT INTO customer (id, name, tier) VALUES (6, 'Larissa White', 2); 7 | INSERT INTO customer (id, name, tier) VALUES (7, 'Fae Heidenreich', 1); 8 | INSERT INTO customer (id, name, tier) VALUES (8, 'Dino Will', 2); 9 | INSERT INTO customer (id, name, tier) VALUES (9, 'Eloy Stroman', 1); 10 | INSERT INTO customer (id, name, tier) VALUES (10, 'Brisa O''Connell', 1); 11 | INSERT INTO product (id, name, category, price) VALUES (1, 'omnis quod consequatur', 'Games', 184.83); 12 | INSERT INTO product (id, name, category, price) VALUES (2, 'vel libero suscipit', 'Toys', 12.66); 13 | INSERT INTO product (id, name, category, price) VALUES (3, 'non nemo iure', 'Grocery', 498.02); 14 | INSERT INTO product (id, name, category, price) VALUES (4, 'voluptatem voluptas aspernatur', 'Toys', 536.80); 15 | INSERT INTO product (id, name, category, price) VALUES (5, 'animi cum rem', 'Games', 458.20); 16 | INSERT INTO product (id, name, category, price) VALUES (6, 'dolorem porro debitis', 'Toys', 146.52); 17 | INSERT INTO product (id, name, category, price) VALUES (7, 'aspernatur rerum qui', 'Books', 656.42); 18 | INSERT INTO product (id, name, category, price) VALUES (8, 'deleniti earum et', 'Baby', 41.46); 19 | INSERT INTO product (id, name, category, price) VALUES (9, 'voluptas ut quidem', 'Books', 697.57); 20 | INSERT INTO product (id, name, category, price) VALUES (10, 'eos sed debitis', 'Baby', 366.90); 21 | INSERT INTO product (id, name, category, price) VALUES (11, 'laudantium sit nihil', 'Toys', 95.50); 22 | INSERT INTO product (id, name, category, price) VALUES (12, 'ut perferendis corporis', 'Grocery', 302.19); 23 | INSERT INTO product (id, name, category, price) VALUES (13, 'sint voluptatem ut', 'Toys', 295.37); 24 | INSERT INTO product (id, name, category, price) VALUES (14, 'quos sunt ipsam', 'Grocery', 534.64); 25 | INSERT INTO product (id, name, category, price) VALUES (15, 'qui illo error', 'Baby', 623.58); 26 | INSERT INTO product (id, name, category, price) VALUES (16, 'aut ex ducimus', 'Books', 551.39); 27 | INSERT INTO product (id, name, category, price) VALUES (17, 'accusamus repellendus minus', 'Books', 240.58); 28 | INSERT INTO product (id, name, category, price) VALUES (18, 'aut accusamus quia', 'Baby', 881.38); 29 | INSERT INTO product (id, name, category, price) VALUES (19, 'doloremque incidunt sed', 'Games', 988.49); 30 | INSERT INTO product (id, name, category, price) VALUES (20, 'libero omnis velit', 'Baby', 177.61); 31 | INSERT INTO product (id, name, category, price) VALUES (21, 'consectetur cupiditate sunt', 'Toys', 95.46); 32 | INSERT INTO product (id, name, category, price) VALUES (22, 'itaque ea qui', 'Baby', 677.78); 33 | INSERT INTO product (id, name, category, price) VALUES (23, 'non et nulla', 'Grocery', 70.49); 34 | INSERT INTO product (id, name, category, price) VALUES (24, 'veniam consequatur et', 'Books', 893.44); 35 | INSERT INTO product (id, name, category, price) VALUES (25, 'magnam adipisci voluptate', 'Grocery', 366.13); 36 | INSERT INTO product (id, name, category, price) VALUES (26, 'reiciendis consequuntur placeat', 'Toys', 359.27); 37 | INSERT INTO product (id, name, category, price) VALUES (27, 'dolores ipsum sit', 'Toys', 786.99); 38 | INSERT INTO product (id, name, category, price) VALUES (28, 'ut hic tempore', 'Toys', 316.09); 39 | INSERT INTO product (id, name, category, price) VALUES (29, 'quas quis deserunt', 'Toys', 772.78); 40 | INSERT INTO product (id, name, category, price) VALUES (30, 'excepturi nesciunt accusantium', 'Toys', 911.46); 41 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (1, '2021-02-28', '2021-03-08', 'NEW', 5); 42 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (2, '2021-02-28', '2021-03-05', 'NEW', 3); 43 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (3, '2021-04-10', '2021-04-18', 'DELIVERED', 5); 44 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (4, '2021-03-22', '2021-03-27', 'PENDING', 3); 45 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (5, '2021-03-04', '2021-03-12', 'NEW', 1); 46 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (6, '2021-03-30', '2021-04-07', 'DELIVERED', 9); 47 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (7, '2021-03-05', '2021-03-09', 'PENDING', 8); 48 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (8, '2021-03-27', '2021-04-05', 'NEW', 4); 49 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (9, '2021-04-14', '2021-04-18', 'NEW', 10); 50 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (10, '2021-03-10', '2021-03-19', 'NEW', 8); 51 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (11, '2021-04-01', '2021-04-04', 'DELIVERED', 1); 52 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (12, '2021-02-24', '2021-02-28', 'PENDING', 5); 53 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (13, '2021-03-15', '2021-03-21', 'NEW', 5); 54 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (14, '2021-03-30', '2021-04-07', 'PENDING', 4); 55 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (15, '2021-03-13', '2021-03-14', 'DELIVERED', 5); 56 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (16, '2021-03-13', '2021-03-21', 'NEW', 1); 57 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (17, '2021-03-31', '2021-03-31', 'DELIVERED', 6); 58 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (18, '2021-03-25', '2021-03-31', 'PENDING', 9); 59 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (19, '2021-02-28', '2021-03-09', 'DELIVERED', 9); 60 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (20, '2021-03-23', '2021-03-30', 'NEW', 5); 61 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (21, '2021-03-19', '2021-03-24', 'DELIVERED', 9); 62 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (22, '2021-02-27', '2021-03-01', 'NEW', 5); 63 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (23, '2021-04-19', '2021-04-24', 'PENDING', 4); 64 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (24, '2021-03-24', '2021-03-24', 'DELIVERED', 1); 65 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (25, '2021-03-03', '2021-03-10', 'NEW', 1); 66 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (26, '2021-03-17', '2021-03-26', 'NEW', 10); 67 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (27, '2021-03-20', '2021-03-25', 'NEW', 1); 68 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (28, '2021-04-09', '2021-04-16', 'DELIVERED', 2); 69 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (29, '2021-04-06', '2021-04-08', 'PENDING', 1); 70 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (30, '2021-04-19', '2021-04-20', 'DELIVERED', 1); 71 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (31, '2021-03-03', '2021-03-04', 'NEW', 3); 72 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (32, '2021-03-15', '2021-03-24', 'DELIVERED', 2); 73 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (33, '2021-04-18', '2021-04-24', 'PENDING', 1); 74 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (34, '2021-03-28', '2021-03-28', 'NEW', 6); 75 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (35, '2021-03-15', '2021-03-17', 'NEW', 1); 76 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (36, '2021-03-04', '2021-03-08', 'DELIVERED', 2); 77 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (37, '2021-03-18', '2021-03-25', 'NEW', 8); 78 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (38, '2021-04-11', '2021-04-20', 'NEW', 8); 79 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (39, '2021-04-12', '2021-04-17', 'NEW', 9); 80 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (40, '2021-03-12', '2021-03-12', 'PENDING', 3); 81 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (41, '2021-02-24', '2021-02-26', 'NEW', 5); 82 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (42, '2021-04-08', '2021-04-14', 'DELIVERED', 9); 83 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (43, '2021-03-03', '2021-03-11', 'NEW', 3); 84 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (44, '2021-03-12', '2021-03-14', 'DELIVERED', 4); 85 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (45, '2021-04-01', '2021-04-06', 'DELIVERED', 1); 86 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (46, '2021-03-16', '2021-03-22', 'NEW', 10); 87 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (47, '2021-04-07', '2021-04-12', 'PENDING', 2); 88 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (48, '2021-04-05', '2021-04-06', 'NEW', 2); 89 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (49, '2021-04-10', '2021-04-13', 'NEW', 7); 90 | INSERT INTO product_order (id, order_date, delivery_date, status, customer_id) VALUES (50, '2021-03-18', '2021-03-21', 'NEW', 9); 91 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (1, 19); 92 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (1, 21); 93 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (1, 5); 94 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (2, 17); 95 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (2, 11); 96 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (2, 14); 97 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (2, 13); 98 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (3, 5); 99 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (3, 3); 100 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (3, 19); 101 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (3, 13); 102 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (3, 15); 103 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (4, 22); 104 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (4, 26); 105 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (4, 12); 106 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (5, 5); 107 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (6, 5); 108 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (6, 12); 109 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (7, 8); 110 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (7, 25); 111 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (7, 21); 112 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (7, 1); 113 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (7, 13); 114 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (7, 10); 115 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (8, 12); 116 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (8, 8); 117 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (9, 8); 118 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (10, 14); 119 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (10, 8); 120 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (11, 12); 121 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (11, 6); 122 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (11, 21); 123 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (11, 22); 124 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (11, 27); 125 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (11, 11); 126 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (12, 19); 127 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (12, 13); 128 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (12, 11); 129 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (12, 6); 130 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (13, 11); 131 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (13, 24); 132 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (13, 26); 133 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (13, 23); 134 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (14, 18); 135 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (15, 16); 136 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (15, 13); 137 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (15, 7); 138 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (16, 23); 139 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (16, 29); 140 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (16, 18); 141 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (16, 16); 142 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (16, 22); 143 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (16, 26); 144 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (17, 18); 145 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (17, 4); 146 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (18, 13); 147 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (18, 3); 148 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (18, 27); 149 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (18, 2); 150 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (19, 26); 151 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (19, 22); 152 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (19, 18); 153 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (19, 14); 154 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (19, 15); 155 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (19, 13); 156 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (20, 22); 157 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (21, 21); 158 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (21, 26); 159 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (22, 7); 160 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (22, 6); 161 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (23, 27); 162 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (23, 7); 163 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (23, 11); 164 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (23, 5); 165 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (24, 24); 166 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (24, 2); 167 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (24, 6); 168 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (24, 28); 169 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (24, 4); 170 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (25, 28); 171 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (25, 17); 172 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (25, 2); 173 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (25, 29); 174 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (25, 19); 175 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (26, 4); 176 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (27, 6); 177 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (27, 15); 178 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (27, 24); 179 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (28, 22); 180 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (28, 9); 181 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (29, 22); 182 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (30, 29); 183 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (30, 6); 184 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (30, 8); 185 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (31, 16); 186 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (31, 12); 187 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (31, 28); 188 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (32, 8); 189 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (32, 5); 190 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (33, 12); 191 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (33, 26); 192 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (33, 21); 193 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (33, 23); 194 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (33, 29); 195 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (33, 13); 196 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (34, 1); 197 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (34, 6); 198 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (34, 22); 199 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (34, 19); 200 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (34, 13); 201 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (34, 27); 202 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (35, 5); 203 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (35, 11); 204 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (35, 26); 205 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (35, 9); 206 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (36, 28); 207 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (36, 7); 208 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (37, 15); 209 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (37, 11); 210 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (38, 18); 211 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (38, 11); 212 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (38, 14); 213 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (38, 20); 214 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (38, 7); 215 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (39, 1); 216 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (39, 21); 217 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (40, 12); 218 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (40, 10); 219 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (40, 11); 220 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (40, 29); 221 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (40, 1); 222 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (41, 13); 223 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (41, 19); 224 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (41, 5); 225 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (41, 29); 226 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (41, 14); 227 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (41, 4); 228 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (42, 2); 229 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (43, 6); 230 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (44, 20); 231 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (44, 18); 232 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (44, 8); 233 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (44, 24); 234 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (44, 26); 235 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (44, 13); 236 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (45, 23); 237 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (45, 1); 238 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (45, 25); 239 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (45, 15); 240 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (46, 16); 241 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (46, 24); 242 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (46, 19); 243 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (46, 13); 244 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (46, 11); 245 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (47, 23); 246 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (47, 28); 247 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (47, 20); 248 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (47, 21); 249 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (48, 15); 250 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (48, 3); 251 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (48, 26); 252 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (48, 7); 253 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (48, 19); 254 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (48, 10); 255 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (49, 5); 256 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (49, 13); 257 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (49, 29); 258 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (49, 3); 259 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (49, 12); 260 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (49, 17); 261 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (50, 15); 262 | INSERT INTO order_product_relationship (order_id, product_id) VALUES (50, 16); 263 | -------------------------------------------------------------------------------- /src/main/resources/table_script.ddl: -------------------------------------------------------------------------------- 1 | create table customer ( 2 | id bigint generated by default as identity, 3 | name varchar(255), 4 | tier integer, 5 | primary key (id) 6 | ) 7 | 8 | 9 | create table order_product_relationship ( 10 | order_id bigint not null, 11 | product_id bigint not null, 12 | primary key (order_id, product_id) 13 | ) 14 | 15 | create table product ( 16 | id bigint generated by default as identity, 17 | category varchar(255), 18 | name varchar(255), 19 | price double, 20 | primary key (id) 21 | ) 22 | 23 | create table product_order ( 24 | id bigint generated by default as identity, 25 | order_date date, 26 | customer_id bigint, 27 | primary key (id) 28 | ) 29 | 30 | alter table order_product_relationship add constraint FKn8aeo7cic1d0ejbbxu3vxlb4c 31 | foreign key (product_id) references product 32 | 33 | alter table order_product_relationship add constraint FK722amt5gugjshh8fhjt6i66i3 34 | foreign key (order_id) references product_order 35 | 36 | alter table product_order add constraint FKa90wgrcf86ft7kh3pjivc5c5e 37 | foreign key (customer_id) references customer 38 | 39 | -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | streamapi 7 | https://maven.apache.org/images/apache-maven-project.png 8 | https://www.apache.org/ 9 | 10 | 11 | 12 | https://maven.apache.org/images/maven-logo-black-on-white.png 13 | https://maven.apache.org/ 14 | 15 | 16 | 17 | org.apache.maven.skins 18 | maven-fluido-skin 19 | 1.7 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/test/java/space/gavinklfong/demo/streamapi/StreamApiTest.java: -------------------------------------------------------------------------------- 1 | package space.gavinklfong.demo.streamapi; 2 | 3 | import java.time.LocalDate; 4 | import java.util.Comparator; 5 | import java.util.DoubleSummaryStatistics; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Optional; 10 | import java.util.function.BiFunction; 11 | import java.util.function.BiPredicate; 12 | import java.util.function.Function; 13 | import java.util.function.Predicate; 14 | import java.util.stream.Collectors; 15 | 16 | import org.junit.jupiter.api.DisplayName; 17 | import org.junit.jupiter.api.Test; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 20 | 21 | import lombok.extern.slf4j.Slf4j; 22 | import space.gavinklfong.demo.streamapi.models.Customer; 23 | import space.gavinklfong.demo.streamapi.models.Order; 24 | import space.gavinklfong.demo.streamapi.models.Product; 25 | import space.gavinklfong.demo.streamapi.repos.CustomerRepo; 26 | import space.gavinklfong.demo.streamapi.repos.OrderRepo; 27 | import space.gavinklfong.demo.streamapi.repos.ProductRepo; 28 | 29 | @Slf4j 30 | @DataJpaTest 31 | public class StreamApiTest { 32 | 33 | @Autowired 34 | private CustomerRepo customerRepo; 35 | 36 | @Autowired 37 | private OrderRepo orderRepo; 38 | 39 | @Autowired 40 | private ProductRepo productRepo; 41 | 42 | @Test 43 | @DisplayName("Obtain a list of product with category = \"Books\" and price > 100") 44 | public void exercise1() { 45 | long startTime = System.currentTimeMillis(); 46 | List result = productRepo.findAll() 47 | .stream() 48 | .filter(p -> p.getCategory().equalsIgnoreCase("Books")) 49 | .filter(p -> p.getPrice() > 100) 50 | .collect(Collectors.toList()); 51 | long endTime = System.currentTimeMillis(); 52 | 53 | log.info(String.format("exercise 1 - execution time: %1$d ms", (endTime - startTime))); 54 | result.forEach(p -> log.info(p.toString())); 55 | } 56 | 57 | @Test 58 | @DisplayName("Obtain a list of product with category = \"Books\" and price > 100 (using Predicate chaining for filter)") 59 | public void exercise1a() { 60 | Predicate categoryFilter = product -> product.getCategory().equalsIgnoreCase("Books"); 61 | Predicate priceFilter = product -> product.getPrice() > 100; 62 | 63 | long startTime = System.currentTimeMillis(); 64 | List result = productRepo.findAll() 65 | .stream() 66 | .filter(product -> categoryFilter.and(priceFilter).test(product)) 67 | .collect(Collectors.toList()); 68 | long endTime = System.currentTimeMillis(); 69 | 70 | log.info(String.format("exercise 1a - execution time: %1$d ms", (endTime - startTime))); 71 | result.forEach(p -> log.info(p.toString())); 72 | } 73 | 74 | @Test 75 | @DisplayName("Obtain a list of product with category = \"Books\" and price > 100 (using BiPredicate for filter)") 76 | public void exercise1b() { 77 | BiPredicate categoryFilter = (product, category) -> product.getCategory().equalsIgnoreCase(category); 78 | 79 | long startTime = System.currentTimeMillis(); 80 | List result = productRepo.findAll() 81 | .stream() 82 | .filter(product -> categoryFilter.test(product, "Books") && product.getPrice() > 100) 83 | .collect(Collectors.toList()); 84 | long endTime = System.currentTimeMillis(); 85 | 86 | log.info(String.format("exercise 1b - execution time: %1$d ms", (endTime - startTime))); 87 | result.forEach(p -> log.info(p.toString())); 88 | } 89 | 90 | @Test 91 | @DisplayName("Obtain a list of order with product category = \"Baby\"") 92 | public void exercise2() { 93 | long startTime = System.currentTimeMillis(); 94 | List result = orderRepo.findAll() 95 | .stream() 96 | .filter(o -> 97 | o.getProducts() 98 | .stream() 99 | .anyMatch(p -> p.getCategory().equalsIgnoreCase("Baby")) 100 | ) 101 | .collect(Collectors.toList()); 102 | 103 | long endTime = System.currentTimeMillis(); 104 | 105 | log.info(String.format("exercise 2 - execution time: %1$d ms", (endTime - startTime))); 106 | result.forEach(o -> log.info(o.toString())); 107 | 108 | } 109 | 110 | @Test 111 | @DisplayName("Obtain a list of product with category = “Toys” and then apply 10% discount\"") 112 | public void exercise3() { 113 | long startTime = System.currentTimeMillis(); 114 | 115 | List result = productRepo.findAll() 116 | .stream() 117 | .filter(p -> p.getCategory().equalsIgnoreCase("Toys")) 118 | .map(p -> p.withPrice(p.getPrice() * 0.9)) 119 | .collect(Collectors.toList()); 120 | 121 | long endTime = System.currentTimeMillis(); 122 | log.info(String.format("exercise 3 - execution time: %1$d ms", (endTime - startTime))); 123 | result.forEach(o -> log.info(o.toString())); 124 | 125 | } 126 | 127 | @Test 128 | @DisplayName("Obtain a list of products ordered by customer of tier 2 between 01-Feb-2021 and 01-Apr-2021") 129 | public void exercise4() { 130 | long startTime = System.currentTimeMillis(); 131 | List result = orderRepo.findAll() 132 | .stream() 133 | .filter(o -> o.getCustomer().getTier() == 2) 134 | .filter(o -> o.getOrderDate().compareTo(LocalDate.of(2021, 2, 1)) >= 0) 135 | .filter(o -> o.getOrderDate().compareTo(LocalDate.of(2021, 4, 1)) <= 0) 136 | .flatMap(o -> o.getProducts().stream()) 137 | .distinct() 138 | .collect(Collectors.toList()); 139 | 140 | long endTime = System.currentTimeMillis(); 141 | log.info(String.format("exercise 4 - execution time: %1$d ms", (endTime - startTime))); 142 | result.forEach(o -> log.info(o.toString())); 143 | } 144 | 145 | @Test 146 | @DisplayName("Get the 3 cheapest products of \"Books\" category") 147 | public void exercise5() { 148 | long startTime = System.currentTimeMillis(); 149 | // Optional result = productRepo.findAll() 150 | // .stream() 151 | // .filter(p -> p.getCategory().equalsIgnoreCase("Books")) 152 | // .sorted(Comparator.comparing(Product::getPrice)) 153 | // .findFirst(); 154 | 155 | Optional result = productRepo.findAll() 156 | .stream() 157 | .filter(p -> p.getCategory().equalsIgnoreCase("Books")) 158 | .min(Comparator.comparing(Product::getPrice)); 159 | 160 | long endTime = System.currentTimeMillis(); 161 | log.info(String.format("exercise 5 - execution time: %1$d ms", (endTime - startTime))); 162 | log.info(result.get().toString()); 163 | 164 | } 165 | 166 | @Test 167 | @DisplayName("Get the 3 most recent placed order") 168 | public void exercise6() { 169 | long startTime = System.currentTimeMillis(); 170 | List result = orderRepo.findAll() 171 | .stream() 172 | .sorted(Comparator.comparing(Order::getOrderDate).reversed()) 173 | .limit(3) 174 | .collect(Collectors.toList()); 175 | 176 | long endTime = System.currentTimeMillis(); 177 | log.info(String.format("exercise 6 - execution time: %1$d ms", (endTime - startTime))); 178 | result.forEach(o -> log.info(o.toString())); 179 | } 180 | 181 | @Test 182 | @DisplayName("Get a list of products which was ordered on 15-Mar-2021") 183 | public void exercise7() { 184 | long startTime = System.currentTimeMillis(); 185 | List result = orderRepo.findAll() 186 | .stream() 187 | .filter(o -> o.getOrderDate().isEqual(LocalDate.of(2021, 3, 15))) 188 | .peek(o -> System.out.println(o.toString())) 189 | .flatMap(o -> o.getProducts().stream()) 190 | .distinct() 191 | .collect(Collectors.toList()); 192 | 193 | long endTime = System.currentTimeMillis(); 194 | log.info(String.format("exercise 7 - execution time: %1$d ms", (endTime - startTime))); 195 | result.forEach(o -> log.info(o.toString())); 196 | } 197 | 198 | @Test 199 | @DisplayName("Calculate the total lump of all orders placed in Feb 2021") 200 | public void exercise8() { 201 | long startTime = System.currentTimeMillis(); 202 | double result = orderRepo.findAll() 203 | .stream() 204 | .filter(o -> o.getOrderDate().compareTo(LocalDate.of(2021, 2, 1)) >= 0) 205 | .filter(o -> o.getOrderDate().compareTo(LocalDate.of(2021, 3, 1)) < 0) 206 | .flatMap(o -> o.getProducts().stream()) 207 | .mapToDouble(Product::getPrice) 208 | .sum(); 209 | 210 | long endTime = System.currentTimeMillis(); 211 | log.info(String.format("exercise 8 - execution time: %1$d ms", (endTime - startTime))); 212 | log.info("Total lump sum = " + result); 213 | } 214 | 215 | @Test 216 | @DisplayName("Calculate the total lump of all orders placed in Feb 2021 (using reduce with BiFunction)") 217 | public void exercise8a() { 218 | BiFunction accumulator = (acc, product) -> acc + product.getPrice(); 219 | 220 | long startTime = System.currentTimeMillis(); 221 | double result = orderRepo.findAll() 222 | .stream() 223 | .filter(o -> o.getOrderDate().compareTo(LocalDate.of(2021, 2, 1)) >= 0) 224 | .filter(o -> o.getOrderDate().compareTo(LocalDate.of(2021, 3, 1)) < 0) 225 | .flatMap(o -> o.getProducts().stream()) 226 | .reduce(0D, accumulator, Double::sum); 227 | 228 | long endTime = System.currentTimeMillis(); 229 | log.info(String.format("exercise 8a - execution time: %1$d ms", (endTime - startTime))); 230 | log.info("Total lump sum = " + result); 231 | } 232 | 233 | @Test 234 | @DisplayName("Calculate the average price of all orders placed on 15-Mar-2021") 235 | public void exercise9() { 236 | long startTime = System.currentTimeMillis(); 237 | double result = orderRepo.findAll() 238 | .stream() 239 | .filter(o -> o.getOrderDate().isEqual(LocalDate.of(2021, 3, 15))) 240 | .flatMap(o -> o.getProducts().stream()) 241 | .mapToDouble(Product::getPrice) 242 | .average().getAsDouble(); 243 | 244 | long endTime = System.currentTimeMillis(); 245 | log.info(String.format("exercise 9 - execution time: %1$d ms", (endTime - startTime))); 246 | log.info("Average = " + result); 247 | } 248 | 249 | @Test 250 | @DisplayName("Obtain statistics summary of all products belong to \"Books\" category") 251 | public void exercise10() { 252 | long startTime = System.currentTimeMillis(); 253 | DoubleSummaryStatistics statistics = productRepo.findAll() 254 | .stream() 255 | .filter(p -> p.getCategory().equalsIgnoreCase("Books")) 256 | .mapToDouble(Product::getPrice) 257 | .summaryStatistics(); 258 | 259 | long endTime = System.currentTimeMillis(); 260 | log.info(String.format("exercise 10 - execution time: %1$d ms", (endTime - startTime))); 261 | log.info(String.format("count = %1$d, average = %2$f, max = %3$f, min = %4$f, sum = %5$f", 262 | statistics.getCount(), statistics.getAverage(), statistics.getMax(), statistics.getMin(), statistics.getSum())); 263 | 264 | } 265 | 266 | @Test 267 | @DisplayName("Obtain a mapping of order id and the order's product count") 268 | public void exercise11() { 269 | long startTime = System.currentTimeMillis(); 270 | Map result = orderRepo.findAll() 271 | .stream() 272 | .collect( 273 | Collectors.toMap( 274 | Order::getId, 275 | order -> order.getProducts().size()) 276 | ); 277 | 278 | long endTime = System.currentTimeMillis(); 279 | log.info(String.format("exercise 11 - execution time: %1$d ms", (endTime - startTime))); 280 | log.info(result.toString()); 281 | } 282 | 283 | @Test 284 | @DisplayName("Obtain a data map of customer and list of orders") 285 | public void exercise12() { 286 | long startTime = System.currentTimeMillis(); 287 | Map> result = orderRepo.findAll() 288 | .stream() 289 | .collect(Collectors.groupingBy(Order::getCustomer)); 290 | 291 | long endTime = System.currentTimeMillis(); 292 | log.info(String.format("exercise 12 - execution time: %1$d ms", (endTime - startTime))); 293 | log.info(result.toString()); 294 | } 295 | 296 | @Test 297 | @DisplayName("Obtain a data map of customer_id and list of order_id(s)") 298 | public void exercise12a() { 299 | long startTime = System.currentTimeMillis(); 300 | HashMap> result = orderRepo.findAll() 301 | .stream() 302 | .collect( 303 | Collectors.groupingBy( 304 | order -> order.getCustomer().getId(), 305 | HashMap::new, 306 | Collectors.mapping(Order::getId, Collectors.toList()))); 307 | long endTime = System.currentTimeMillis(); 308 | log.info(String.format("exercise 12a - execution time: %1$d ms", (endTime - startTime))); 309 | log.info(result.toString()); 310 | } 311 | 312 | @Test 313 | @DisplayName("Obtain a data map with order and its total price") 314 | public void exercise13() { 315 | long startTime = System.currentTimeMillis(); 316 | Map result = orderRepo.findAll() 317 | .stream() 318 | .collect( 319 | Collectors.toMap( 320 | Function.identity(), 321 | order -> order.getProducts().stream() 322 | .mapToDouble(Product::getPrice).sum()) 323 | ); 324 | 325 | long endTime = System.currentTimeMillis(); 326 | log.info(String.format("exercise 13 - execution time: %1$d ms", (endTime - startTime))); 327 | log.info(result.toString()); 328 | } 329 | 330 | @Test 331 | @DisplayName("Obtain a data map with order and its total price (using reduce)") 332 | public void exercise13a() { 333 | long startTime = System.currentTimeMillis(); 334 | Map result = orderRepo.findAll() 335 | .stream() 336 | .collect( 337 | Collectors.toMap( 338 | Order::getId, 339 | order -> order.getProducts().stream() 340 | .reduce(0D, (acc, product) -> acc + product.getPrice(), Double::sum) 341 | )); 342 | 343 | long endTime = System.currentTimeMillis(); 344 | log.info(String.format("exercise 13a - execution time: %1$d ms", (endTime - startTime))); 345 | log.info(result.toString()); 346 | } 347 | 348 | @Test 349 | @DisplayName("Obtain a data map of product name by category") 350 | public void exercise14() { 351 | long startTime = System.currentTimeMillis(); 352 | Map> result = productRepo.findAll() 353 | .stream() 354 | .collect( 355 | Collectors.groupingBy( 356 | Product::getCategory, 357 | Collectors.mapping(Product::getName, Collectors.toList())) 358 | ); 359 | 360 | 361 | long endTime = System.currentTimeMillis(); 362 | log.info(String.format("exercise 14 - execution time: %1$d ms", (endTime - startTime))); 363 | log.info(result.toString()); 364 | } 365 | 366 | @Test 367 | @DisplayName("Get the most expensive product per category") 368 | void exercise15() { 369 | long startTime = System.currentTimeMillis(); 370 | Map> result = productRepo.findAll() 371 | .stream() 372 | .collect( 373 | Collectors.groupingBy( 374 | Product::getCategory, 375 | Collectors.maxBy(Comparator.comparing(Product::getPrice))) 376 | ); 377 | long endTime = System.currentTimeMillis(); 378 | log.info(String.format("exercise 15 - execution time: %1$d ms", (endTime - startTime))); 379 | log.info(result.toString()); 380 | // result.forEach((k,v) -> { 381 | // log.info("key=" + k + ", value=" + v.get()); 382 | // }); 383 | 384 | } 385 | 386 | @Test 387 | @DisplayName("Get the most expensive product (by name) per category") 388 | void exercise15a() { 389 | long startTime = System.currentTimeMillis(); 390 | Map result = productRepo.findAll() 391 | .stream() 392 | .collect( 393 | Collectors.groupingBy( 394 | Product::getCategory, 395 | Collectors.collectingAndThen( 396 | Collectors.maxBy(Comparator.comparingDouble(Product::getPrice)), 397 | optionalProduct -> optionalProduct.map(Product::getName).orElse(null) 398 | ) 399 | )); 400 | long endTime = System.currentTimeMillis(); 401 | log.info(String.format("exercise 15a - execution time: %1$d ms", (endTime - startTime))); 402 | log.info(result.toString()); 403 | } 404 | 405 | } 406 | -------------------------------------------------------------------------------- /src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.hibernate.ddl-auto=update 2 | spring.datasource.url = jdbc:h2:mem:testdb:DB_CLOSE_ON_EXIT=FALSE 3 | 4 | spring.jpa.show-sql=false 5 | spring.jpa.properties.hibernate.generate_statistics=false 6 | spring.jpa.properties.hibernate.show_sql=false 7 | --------------------------------------------------------------------------------