├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── de
│ └── codecentric
│ └── java8examples
│ ├── Invoice.java
│ ├── InvoiceItem.java
│ ├── Person.java
│ ├── defaultmethods
│ ├── AbstractGreetingService.java
│ ├── AlternativeGreetingService.java
│ ├── CombinedGreetingService.java
│ ├── DefaultGreetingService.java
│ ├── DerivedGreetingService.java
│ ├── ExtendedGreetingService.java
│ └── GreetingService.java
│ ├── lambdas
│ ├── LambdaBasedActionLister.java
│ ├── LambdaExample.java
│ └── SpringJdbcSupportWithLambdas.java
│ ├── methodreference
│ └── Foo.java
│ └── streaming
│ ├── CollectingAndReducing.java
│ └── FilteringAndMapping.java
└── test
└── java
└── de
└── codecentric
└── java8examples
├── TestData.java
├── defaultmethods
└── GreetingServiceTest.java
├── lambdas
├── LambdaBasedComparatorTest.java
└── LambdaExampleTest.java
├── methodreference
└── MethodReferenceExampleTest.java
├── streaming
├── CollectingAndReducingTest.java
└── FilteringAndMappingTest.java
└── timeapi
└── TimeApiTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.iml
3 | target
4 | /.classpath
5 | /.project
6 | /.settings
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This repository contains some examples for the new features introuced in Java 8, such as:
2 |
3 | * Default Methods
4 | * Method References
5 | * Lambdas
6 | * Streaming API
7 | * Time API (JSR-310)
8 |
9 | You can get Java 8 from www.jdk8.java.net/download.html
10 |
11 | IDE-Support with Spring Tool Suite
12 | * Download STS 3.4.0 http://spring.io/tools/sts/all
13 | * Install Java 8 Support via Update Site http://dist.springsource.com/snapshot/TOOLS/java8/e43
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | de.codecentric
8 | java8-examples
9 | 0.1-SNAPSHOT
10 |
11 |
12 |
13 | joda-time
14 | joda-time
15 | 2.3
16 |
17 |
18 | org.springframework
19 | spring-jdbc
20 | 3.2.5.RELEASE
21 |
22 |
23 | junit
24 | junit
25 | 4.11
26 | test
27 |
28 |
29 | org.hamcrest
30 | hamcrest-library
31 | 1.3
32 | test
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.apache.maven.plugins
40 | maven-eclipse-plugin
41 |
42 | true
43 | true
44 | 1.8
45 | 1.8
46 | UTF-8
47 |
48 | 2.9
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-compiler-plugin
53 |
54 | 1.8
55 | 1.8
56 | UTF-8
57 |
58 | 3.1
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/Invoice.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.List;
5 | import java.util.stream.Collectors;
6 |
7 | import sun.reflect.generics.reflectiveObjects.NotImplementedException;
8 |
9 | public class Invoice {
10 |
11 | private String sender;
12 | private String recipient;
13 | private List items;
14 |
15 | public String getSender() {
16 | return sender;
17 | }
18 |
19 | public String getRecipient() {
20 | return recipient;
21 | }
22 |
23 | public List getItems() {
24 | return items;
25 | }
26 |
27 | public BigDecimal getTotal() {
28 | return getItems().stream()
29 | .map(invoice -> invoice
30 | .getPricePerUnit()
31 | .multiply(BigDecimal.valueOf(invoice.getQuantity())))
32 | .collect(Collectors.reducing(
33 | BigDecimal.ZERO,
34 | (sum, elem) -> sum.add(elem)));
35 | }
36 |
37 | public Invoice(String sender, String recipient, List items) {
38 | this.sender = sender;
39 | this.recipient = recipient;
40 | this.items = items;
41 | }
42 |
43 | @Override
44 | public boolean equals(Object o) {
45 | if (this == o) return true;
46 | if (o == null || getClass() != o.getClass()) return false;
47 |
48 | Invoice invoice = (Invoice) o;
49 |
50 | if (items != null ? !items.equals(invoice.items) : invoice.items != null) return false;
51 | if (recipient != null ? !recipient.equals(invoice.recipient) : invoice.recipient != null) return false;
52 | if (sender != null ? !sender.equals(invoice.sender) : invoice.sender != null) return false;
53 |
54 | return true;
55 | }
56 |
57 | @Override
58 | public int hashCode() {
59 | int result = sender != null ? sender.hashCode() : 0;
60 | result = 31 * result + (recipient != null ? recipient.hashCode() : 0);
61 | result = 31 * result + (items != null ? items.hashCode() : 0);
62 | return result;
63 | }
64 |
65 | @Override
66 | public String toString() {
67 | return "Invoice{" +
68 | "sender='" + sender + '\'' +
69 | ", recipient='" + recipient + '\'' +
70 | ", items=" + items +
71 | '}';
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/InvoiceItem.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class InvoiceItem {
6 |
7 | private String product;
8 | private Integer quantity;
9 | private BigDecimal pricePerUnit;
10 |
11 | public String getProduct() {
12 | return product;
13 | }
14 |
15 | public Integer getQuantity() {
16 | return quantity;
17 | }
18 |
19 | public BigDecimal getPricePerUnit() {
20 | return pricePerUnit;
21 | }
22 |
23 | public InvoiceItem(String product, Integer quantity, BigDecimal pricePerUnit) {
24 | this.product = product;
25 | this.quantity = quantity;
26 | this.pricePerUnit = pricePerUnit;
27 | }
28 |
29 | @Override
30 | public boolean equals(Object o) {
31 | if (this == o) return true;
32 | if (o == null || getClass() != o.getClass()) return false;
33 |
34 | InvoiceItem that = (InvoiceItem) o;
35 |
36 | if (pricePerUnit != null ? !pricePerUnit.equals(that.pricePerUnit) : that.pricePerUnit != null) return false;
37 | if (product != null ? !product.equals(that.product) : that.product != null) return false;
38 | if (quantity != null ? !quantity.equals(that.quantity) : that.quantity != null) return false;
39 |
40 | return true;
41 | }
42 |
43 | @Override
44 | public int hashCode() {
45 | int result = product != null ? product.hashCode() : 0;
46 | result = 31 * result + (quantity != null ? quantity.hashCode() : 0);
47 | result = 31 * result + (pricePerUnit != null ? pricePerUnit.hashCode() : 0);
48 | return result;
49 | }
50 |
51 | @Override
52 | public String toString() {
53 | return "InvoiceItem{" +
54 | "product='" + product + '\'' +
55 | ", quantity=" + quantity +
56 | ", pricePerUnit=" + pricePerUnit +
57 | '}';
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/Person.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples;
2 |
3 | import java.time.LocalDate;
4 | import java.time.Period;
5 |
6 | /**
7 | * A simple class that represents a person
8 | */
9 | public class Person {
10 |
11 | public enum Gender {
12 | MALE, FEMALE
13 | }
14 |
15 | private final String firstName;
16 | private final String lastName;
17 | private final LocalDate birthDay;
18 | private Gender gender;
19 |
20 | public Person(String firstname, String lastName, LocalDate birthDay, Gender gender) {
21 | this.firstName = firstname;
22 | this.lastName = lastName;
23 | this.birthDay = birthDay;
24 | this.gender = gender;
25 | }
26 |
27 | public String getFirstName() {
28 | return firstName;
29 | }
30 |
31 | public String getLastName() {
32 | return lastName;
33 | }
34 |
35 | public LocalDate getBirthDay() {
36 | return birthDay;
37 | }
38 |
39 | public Gender getGender() {
40 | return gender;
41 | }
42 |
43 | public void setGender(Gender gender) {
44 | this.gender = gender;
45 | }
46 |
47 | public int getAge() {
48 | return Period.between(getBirthDay(), LocalDate.now()).getYears();
49 | }
50 |
51 | @Override
52 | public boolean equals(Object o) {
53 | if (this == o) return true;
54 | if (o == null || getClass() != o.getClass()) return false;
55 |
56 | Person person = (Person) o;
57 |
58 | if (birthDay != null ? !birthDay.equals(person.birthDay) : person.birthDay != null) return false;
59 | if (gender != person.gender) return false;
60 | if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) return false;
61 | if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) return false;
62 |
63 | return true;
64 | }
65 |
66 | @Override
67 | public int hashCode() {
68 | int result = firstName != null ? firstName.hashCode() : 0;
69 | result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
70 | result = 31 * result + (birthDay != null ? birthDay.hashCode() : 0);
71 | result = 31 * result + (gender != null ? gender.hashCode() : 0);
72 | return result;
73 | }
74 |
75 | @Override
76 | public String toString() {
77 | return "Person{" +
78 | "firstName='" + firstName + '\'' +
79 | ", lastName='" + lastName + '\'' +
80 | ", birthDay=" + birthDay +
81 | ", gender=" + gender +
82 | '}';
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/defaultmethods/AbstractGreetingService.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.defaultmethods;
2 |
3 | /**
4 | * An abstract base class for GreetingService implementations that forces derived classes to implement {@link #greet()}
5 | * by making it abstract.
6 | */
7 | abstract class AbstractGreetingService implements GreetingService {
8 |
9 | @Override
10 | public abstract String greet();
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/defaultmethods/AlternativeGreetingService.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.defaultmethods;
2 |
3 | /**
4 | * An alternative implementation of GreetingService the provides it's own implementation of {@link #greet()}.
5 | */
6 | public interface AlternativeGreetingService {
7 |
8 | default String greet() {
9 | return "Alternative Greeting!";
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/defaultmethods/CombinedGreetingService.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.defaultmethods;
2 |
3 | /**
4 | * A greeting service implementation that inherits {@link #greet()} from two unrelated interfaces. It has to provide
5 | * an implementation for {@code greet()}.
6 | */
7 | public class CombinedGreetingService implements GreetingService, AlternativeGreetingService {
8 |
9 | /**
10 | * An implementation of the {@code greet()} method which is defined in both, {@link GreetingService} and
11 | * {@link AlternativeGreetingService}. This implementation simply delegates to the default {@code greet()}
12 | * implementation of the {@code GreetingService} interface
13 | *
14 | * @return the result of calling {@link GreetingService#greet()}.
15 | */
16 | @Override
17 | public String greet() {
18 | return GreetingService.super.greet();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/defaultmethods/DefaultGreetingService.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.defaultmethods;
2 |
3 | /**
4 | * A default implementation of GreetingService that doesn't need to implement anything, because an implementation of
5 | * {@link #greet} is provided by GreetingService as default method.
6 | */
7 | public class DefaultGreetingService implements GreetingService {
8 | // nothing to implement here...
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/defaultmethods/DerivedGreetingService.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.defaultmethods;
2 |
3 | /**
4 | * A GreetingService implementation that uses {@link AbstractGreetingService} as base class and therefore has to
5 | * redefine {@link #greet()}.
6 | */
7 | public class DerivedGreetingService extends AbstractGreetingService {
8 |
9 | @Override
10 | public String greet() {
11 | return "Salut le monde!";
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/defaultmethods/ExtendedGreetingService.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.defaultmethods;
2 |
3 | /**
4 | * A GreetingService implementation that overrides to provided default method.
5 | */
6 | public class ExtendedGreetingService implements GreetingService {
7 |
8 | private String name;
9 |
10 | public ExtendedGreetingService(String name) {
11 | this.name = name;
12 | }
13 |
14 | @Override
15 | public String greet() {
16 | return "Hello " + name + "!";
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/defaultmethods/GreetingService.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.defaultmethods;
2 |
3 | /**
4 | * A service that greets you.
5 | */
6 | public interface GreetingService {
7 |
8 | /**
9 | * Creates a greeting message. The provided default implementation simply returns "Hello world!"
10 | *
11 | * @return A greeting message.
12 | */
13 | default String greet() {
14 | return "Hello World!";
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/lambdas/LambdaBasedActionLister.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.lambdas;
2 |
3 | import javax.swing.*;
4 |
5 | /**
6 | * Test case showing how a {@link java.awt.event.ActionListener} can be implemented using a lambda expression.
7 | */
8 | public class LambdaBasedActionLister extends JFrame {
9 |
10 | private int clicks = 0;
11 |
12 | public LambdaBasedActionLister() {
13 | JButton btn = new JButton("0");
14 | btn.setSize(50, 50);
15 | add(btn);
16 |
17 | // lambda magic goes here:
18 | btn.addActionListener(e -> {
19 | btn.setText(Integer.toString(clicks++));
20 | });
21 |
22 | setSize(100, 100);
23 | pack();
24 | setVisible(true);
25 | setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
26 | }
27 |
28 | public static void main(String[] args) {
29 | new LambdaBasedActionLister();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/lambdas/LambdaExample.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.lambdas;
2 |
3 | import java.util.function.Consumer;
4 | import java.util.function.Function;
5 | import java.util.function.Predicate;
6 |
7 | /**
8 | * An example for the use of functional interfaces which can be implemented using lambda expressions. Wraps an
9 | * element of type {@code E} and let's you apply functional interfaces like {@link Function}, {@link Predicate}, and
10 | * {@link Consumer} to the wrapped element.
11 | *
12 | * Look at the LambdaExampleTest to see lambdas in action.
13 | *
14 | * @param The type of the element to be wrapped
15 | */
16 | public class LambdaExample {
17 |
18 | private E elem;
19 |
20 | public LambdaExample(E elem) {
21 | this.elem = elem;
22 | }
23 |
24 | /**
25 | * Applies the given {@link Function} to the wrapped element and returns the result.
26 | * @param function the function to apply to the wrapped element.
27 | * @param the return type of the function application
28 | * @return the result of applying the given function to the wrapped element.
29 | */
30 | public R apply(Function super E, ? extends R> function) {
31 | return function.apply(elem);
32 | }
33 |
34 | /**
35 | * Tests whether the wrapped element satisfies the given predicate.
36 | * @param predicate the predicate used for testing
37 | * @return true, if the wrapped element satisfies the given predicate and false otherwise
38 | */
39 | public boolean matches(Predicate super E> predicate) {
40 | return predicate.test(elem);
41 | }
42 |
43 | /**
44 | * Passes the wrapped element to the given consumer.
45 | * @param consumer the consumer to pass the wrapped element to
46 | */
47 | public void consume(Consumer super E> consumer) {
48 | consumer.accept(elem);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/lambdas/SpringJdbcSupportWithLambdas.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.lambdas;
2 |
3 | import java.sql.ResultSet;
4 | import java.sql.SQLException;
5 |
6 | import de.codecentric.java8examples.Person;
7 | import org.springframework.jdbc.core.RowMapper;
8 | import org.springframework.jdbc.core.support.JdbcDaoSupport;
9 |
10 | /**
11 | * A class that uses spring JdbcSupport and implements {@link RowMapper RowMappers} using lambda expressions.
12 | */
13 | public class SpringJdbcSupportWithLambdas extends JdbcDaoSupport {
14 |
15 | public Person findPersonById(String id) {
16 | return getJdbcTemplate().queryForObject(
17 | // not secured against SQL injections, don't do this in production code!
18 | "SELECT * FROM persons WHERE id = " + id,
19 | new RowMapper() {
20 | @Override
21 | public Person mapRow(ResultSet rs, int i) throws SQLException {
22 | return new Person(rs.getString("FIRST_NAME"), rs.getString("LAST_NAME"), rs.getDate(3).toLocalDate(), Person.Gender.MALE);
23 | }
24 | });
25 | }
26 |
27 | public Person findPersonByIdWithLambdas(String id) {
28 | return getJdbcTemplate().queryForObject(
29 | "SELECT * FROM persons WHERE id = " + id,
30 | (rs, i) -> new Person(rs.getString("FIRST_NAME"), rs.getString("LAST_NAME"), rs.getDate(3).toLocalDate(), Person.Gender.MALE));
31 | }
32 |
33 | // if things get messy, use a method reference
34 | // overall this is more verbose but maybe better for readability?
35 | public Person findPersonByIfWithMethodReference(String id) {
36 | return getJdbcTemplate().queryForObject("SELECT * FROM persons WHERE id = " + id, this::mapPerson);
37 | }
38 |
39 | private Person mapPerson(ResultSet rs, int i) throws SQLException {
40 | return new Person(
41 | rs.getString("FIRST_NAME"),
42 | rs.getString("LAST_NAME"),
43 | rs.getDate(3).toLocalDate(),
44 | Person.Gender.MALE);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/methodreference/Foo.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.methodreference;
2 |
3 | /**
4 | * A Foo that does something...
5 | */
6 | public class Foo {
7 |
8 | public String doSomething() {
9 | return "Foo.doSomething()";
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/streaming/CollectingAndReducing.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.streaming;
2 |
3 | import de.codecentric.java8examples.Invoice;
4 | import de.codecentric.java8examples.InvoiceItem;
5 | import de.codecentric.java8examples.Person;
6 |
7 | import java.math.BigDecimal;
8 | import java.util.AbstractMap.SimpleEntry;
9 | import java.util.*;
10 | import java.util.function.Function;
11 | import java.util.stream.Collectors;
12 |
13 | /**
14 | * Your task: Implement the following methods and make the tests passs.
15 | */
16 | public class CollectingAndReducing {
17 |
18 | /**
19 | * Compute the average age of the given list of Persons.
20 | */
21 | public static Double averageAge(List persons) {
22 | return persons.stream()
23 | .mapToInt(Person::getAge)
24 | .average().getAsDouble();
25 |
26 | }
27 |
28 | /**
29 | * How old is the oldest person in the given list.
30 | */
31 | public static Integer maxAge(List persons) {
32 | return persons.stream()
33 | .mapToInt(Person::getAge)
34 | .max().getAsInt();
35 | }
36 |
37 | /**
38 | * Compute Age-Statistics (max, min, average, ...) for the given list of Persons.
39 | */
40 | public static IntSummaryStatistics ageStatistics(List persons) {
41 | return persons.stream()
42 | .mapToInt(Person::getAge)
43 | .summaryStatistics();
44 | }
45 |
46 | /**
47 | * Build a comma-separated list of the firstnames of a list of Persons.
48 | *
49 | * Example-Result: "Maggie, Marge, Mary"
50 | */
51 | public static String buildCommaSeparatedListOfFirstNames(List persons) {
52 | return persons.stream()
53 | .map(Person::getFirstName)
54 | .collect(Collectors.joining(", "));
55 | }
56 |
57 | /**
58 | * Identify the cheapest product (by pricePerUnit) in all invoices.
59 | */
60 | public static String cheapestProduct(List invoices) {
61 | return invoices.stream()
62 | .flatMap(invoice -> invoice.getItems().stream())
63 | .min(Comparator.comparing(InvoiceItem::getPricePerUnit))
64 | .get().getProduct();
65 | }
66 |
67 | /**
68 | * Identify the invoice with the highest total amount.
69 | */
70 | public static Invoice mostExpensiveInvoice(List invoices) {
71 | return invoices.stream()
72 | .collect(Collectors.maxBy(
73 | Comparator.comparing(Invoice::getTotal))).get();
74 | }
75 |
76 | /**
77 | * Just what the method name says.
78 | */
79 | public static Map> groupInvoicesByRecipient(List invoices) {
80 | return invoices.stream()
81 | .collect(Collectors.groupingBy(Invoice::getRecipient));
82 | }
83 |
84 | /**
85 | * Compute the total amount, that each receiver spent.
86 | *
87 | * Hint: Use the two-argument version of Collectors.groupingBy together with Collectors.mapping.
88 | */
89 | public static Map expensesByRecipient(List invoices) {
90 | return invoices.stream()
91 | .collect(Collectors.groupingBy(
92 | Invoice::getRecipient,
93 | Collectors.mapping(
94 | Invoice::getTotal,
95 | Collectors.reducing(
96 | BigDecimal.ZERO,
97 | (sum, elem) -> sum.add(elem)))));
98 | }
99 |
100 | /**
101 | * How many items of each product have been purchased?
102 | */
103 | public static Map countByProduct(List invoices) {
104 | return invoices.stream()
105 | .flatMap(invoice -> invoice.getItems().stream())
106 | .collect(Collectors.groupingBy(
107 | InvoiceItem::getProduct,
108 | Collectors.summingInt(InvoiceItem::getQuantity)));
109 | }
110 |
111 | /**
112 | * For every product, compute the cheapest dealer. Return as a Map where the key is the product name and the value
113 | * is the dealer (=sender of the invoice).
114 | */
115 | public static Map cheapestDealersByProduct(List invoices) {
116 | return Collections.emptyMap();
117 | }
118 |
119 | /**
120 | * From a given list of invoices, compute for every dealer the available products together with its price.
121 | */
122 | public static Map> computeDealerInventory(List invoices) {
123 | Function, String> classifier =
124 | (SimpleEntry entry) -> (String) entry.getKey();
125 | Function, ProductWithPrice> mapper =
126 | (SimpleEntry entry) -> (ProductWithPrice) entry.getValue();
127 |
128 | Map> invoicesBySender = invoices.stream()
129 | .collect(Collectors.groupingBy(Invoice::getSender));
130 | return invoicesBySender.entrySet().stream()
131 | .>flatMap(entry -> entry.getValue().stream()
132 | .flatMap((Invoice invoice) -> invoice.getItems().stream())
133 | .map((InvoiceItem item) -> new SimpleEntry(
134 | entry.getKey(),
135 | new ProductWithPrice(item.getProduct(), item.getPricePerUnit()))))
136 | .distinct()
137 | .collect(Collectors.groupingBy(
138 | classifier,
139 | Collectors.mapping(
140 | mapper,
141 | Collectors.toList())));
142 | }
143 |
144 | /**
145 | * For every buyer, compute a list of his favorite products (that is: a list of products ordered by the total count
146 | * of items bought).
147 | * For example: Homer bought 5 beers at Moes, 2 beers and a burger at Crustys. Then the result should look like this:
148 | * {"Homer" -> ["Beer", "Burger"]}
149 | */
150 | public static Map> favoriteArticlesByBuyer(List invoices) {
151 | return Collections.emptyMap();
152 | }
153 |
154 | public static class ProductWithPrice {
155 | private String productName;
156 | private BigDecimal price;
157 |
158 | public ProductWithPrice(String productName, BigDecimal price) {
159 | this.productName = productName;
160 | this.price = price;
161 | }
162 |
163 | public String getProductName() {
164 | return productName;
165 | }
166 |
167 | public BigDecimal getPrice() {
168 | return price;
169 | }
170 |
171 | @Override
172 | public boolean equals(Object o) {
173 | if (this == o) return true;
174 | if (o == null || getClass() != o.getClass()) return false;
175 |
176 | ProductWithPrice that = (ProductWithPrice) o;
177 |
178 | if (price != null ? !price.equals(that.price) : that.price != null) return false;
179 | if (productName != null ? !productName.equals(that.productName) : that.productName != null) return false;
180 |
181 | return true;
182 | }
183 |
184 | @Override
185 | public int hashCode() {
186 | int result = productName != null ? productName.hashCode() : 0;
187 | result = 31 * result + (price != null ? price.hashCode() : 0);
188 | return result;
189 | }
190 |
191 | @Override
192 | public String toString() {
193 | return "ProductWithPrice{" +
194 | "productName='" + productName + '\'' +
195 | ", price=" + price +
196 | '}';
197 | }
198 | }
199 |
200 | }
201 |
--------------------------------------------------------------------------------
/src/main/java/de/codecentric/java8examples/streaming/FilteringAndMapping.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.streaming;
2 |
3 | import java.time.LocalDate;
4 | import java.time.Period;
5 | import java.util.List;
6 | import java.util.Set;
7 | import java.util.stream.Collectors;
8 | import java.util.stream.Stream;
9 |
10 | import de.codecentric.java8examples.Invoice;
11 | import de.codecentric.java8examples.InvoiceItem;
12 | import de.codecentric.java8examples.Person;
13 |
14 | /**
15 | * Your task: Implement the following methods and make the tests passs.
16 | */
17 | public class FilteringAndMapping {
18 |
19 | /**
20 | * Extract a list of names (firstname and lastname separated by space) from a given list of Person objects.
21 | */
22 | public static List extractNames(List persons) {
23 | return persons.stream()//
24 | . map(p -> p.getFirstName() + " " + p.getLastName())//
25 | .collect(Collectors. toList());
26 | }
27 |
28 | /**
29 | * Extract a sorted (ascending by lastname) list of names (firstname and lastname separated by space) from a given list of Person objects.
30 | */
31 | public static List extractNamesSortedByLastname(List persons) {
32 | return persons.stream()//
33 | .sorted((Person p1, Person p2) -> (p1.getLastName().compareTo(p2.getLastName())))//
34 | . map(p -> p.getFirstName() + " " + p.getLastName())//
35 | .collect(Collectors. toList());
36 | }
37 |
38 | /**
39 | * From a given list of Person objects, extract a list of female firstnames
40 | */
41 | public static List extractFemaleFirstnames(List persons) {
42 | return persons.stream()//
43 | .filter(p -> p.getGender().equals(Person.Gender.FEMALE))//
44 | . map(p -> p.getFirstName())//
45 | .collect(Collectors. toList());
46 | }
47 |
48 | /**
49 | * Extract all females older than 18 years from a given list of Person objects.
50 | */
51 | public static List extractAdultWomen(List persons) {
52 | return persons.stream()//
53 | .filter(p -> p.getGender().equals(Person.Gender.FEMALE))//
54 | .filter((Person p) -> Period.between(p.getBirthDay(), LocalDate.now()).getYears() >= 18)//
55 | .collect(Collectors. toList());
56 | }
57 |
58 | /**
59 | * From a given list of Person objects, extract a set of firstnames of the people whose lastname starts with the given string.
60 | */
61 | public static Set extractFirstnamesWhereLastnameStartsWith(List persons, String startsWith) {
62 | return persons.stream()//
63 | .filter((Person p) -> p.getLastName().startsWith(startsWith))//
64 | . map(p -> p.getFirstName())//
65 | .collect(Collectors. toSet());
66 | }
67 |
68 | /**
69 | * From a given list of invoices, extract a set of all product names.
70 | */
71 | public static Set extractAllProducts(List invoices) {
72 | return invoices.stream()//
73 | . flatMap((Invoice i) -> i.getItems().stream())//
74 | . map((InvoiceItem i) -> i.getProduct())//
75 | .collect(Collectors. toSet());
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/test/java/de/codecentric/java8examples/TestData.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples;
2 |
3 | import java.math.BigDecimal;
4 | import java.time.LocalDate;
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | /**
10 | * Utility class that generates some test data for us.
11 | */
12 | public class TestData {
13 | public static List listOfPersons() {
14 | return Arrays.asList(
15 | new Person("Jane", "Jungle", LocalDate.of(1978, 12, 15), Person.Gender.FEMALE),
16 | new Person("Mary", "Smith", LocalDate.of(1980, 10, 19), Person.Gender.FEMALE),
17 | new Person("John", "Dole", LocalDate.of(1973, 5, 31), Person.Gender.MALE),
18 | new Person("Michael", "Abrahams", LocalDate.of(1967, 2, 1), Person.Gender.MALE),
19 | new Person("Chris", "Cross", LocalDate.of(1985, 8, 22), Person.Gender.MALE),
20 | new Person("Pete", "Power", LocalDate.of(1981, 3, 18), Person.Gender.MALE),
21 | new Person("Maggie", "Simpson", LocalDate.of(2012, 10, 18), Person.Gender.FEMALE)
22 | );
23 | }
24 |
25 | public static List listOfInvoices() {
26 | return Arrays.asList(
27 | new Invoice("Crusty Burger", "Homer", Arrays.asList(
28 | new InvoiceItem("Burger", 5, BigDecimal.valueOf(5)),
29 | new InvoiceItem("Coke", 1, BigDecimal.valueOf(5)))),
30 | new Invoice("Crusty Burger", "Bart", Arrays.asList(
31 | new InvoiceItem("Coke", 1, BigDecimal.valueOf(5)))),
32 | new Invoice("Moe", "Homer", Arrays.asList(
33 | new InvoiceItem("Beer", 13, BigDecimal.valueOf(1.5)),
34 | new InvoiceItem("Burger", 3, BigDecimal.valueOf(4.5)))),
35 | new Invoice("Kwik-E-Mart", "Homer", Arrays.asList(
36 | new InvoiceItem("Beer", 9, BigDecimal.valueOf(0.9)),
37 | new InvoiceItem("Chips", 2, BigDecimal.valueOf(0.5)))),
38 | new Invoice("Moe", "Marge", Arrays.asList(
39 | new InvoiceItem("Beer", 1, BigDecimal.valueOf(1.5)))),
40 | new Invoice("Kwik-E-Mart", "Bart", Arrays.asList(
41 | new InvoiceItem("Coke", 2, BigDecimal.valueOf(2.5)),
42 | new InvoiceItem("Chips", 2, BigDecimal.valueOf(0.5)))),
43 | new Invoice("Kwik-E-Mart", "Marge", Arrays.asList(
44 | new InvoiceItem("Cake", 2, BigDecimal.valueOf(3.4)),
45 | new InvoiceItem("Corn Flakes", 5, BigDecimal.valueOf(2.3)))),
46 | new Invoice("Moe", "Homer", Arrays.asList(
47 | new InvoiceItem("Beer", 5, BigDecimal.valueOf(1.5)))),
48 | new Invoice("Flander's Left-Handed Store", "Marge", Arrays.asList(
49 | new InvoiceItem("Left-Handed Scissors", 1, BigDecimal.valueOf(10.0))))
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/java/de/codecentric/java8examples/defaultmethods/GreetingServiceTest.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.defaultmethods;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Test;
6 |
7 | /**
8 | * Test case showing how default methods work.
9 | */
10 | public class GreetingServiceTest {
11 |
12 | @Test
13 | public void greetFromDefault() throws Exception {
14 | assertEquals("Hello World!", new DefaultGreetingService().greet());
15 | }
16 |
17 | @Test
18 | public void greetFromExtended() throws Exception {
19 | assertEquals("Hello Pete!", new ExtendedGreetingService("Pete").greet());
20 | }
21 |
22 | @Test
23 | public void greetFromDerived() throws Exception {
24 | assertEquals("Salut le monde!", new DerivedGreetingService().greet());
25 | }
26 |
27 | @Test
28 | public void testName() throws Exception {
29 | assertEquals("Hello World!", new CombinedGreetingService().greet());
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/de/codecentric/java8examples/lambdas/LambdaBasedComparatorTest.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.lambdas;
2 |
3 | import static de.codecentric.java8examples.TestData.listOfPersons;
4 | import static org.hamcrest.number.OrderingComparison.lessThanOrEqualTo;
5 | import static org.junit.Assert.assertThat;
6 |
7 | import java.util.Collections;
8 | import java.util.Comparator;
9 | import java.util.List;
10 |
11 | import de.codecentric.java8examples.Person;
12 | import org.junit.Before;
13 | import org.junit.Test;
14 |
15 | /**
16 | * Test case showing how a {@link Comparator} can be implemented using a lambda expression.
17 | */
18 | public class LambdaBasedComparatorTest {
19 |
20 | private List persons;
21 |
22 | @Before
23 | public void setUp() throws Exception {
24 | persons = listOfPersons();
25 | }
26 |
27 | @Test
28 | public void lambdaBasedComparator() throws Exception {
29 | // comparator is defined on the fly
30 | Comparator byLastNameAsc = (p1, p2) -> p1.getLastName().compareTo(p2.getLastName());
31 |
32 | Collections.sort(persons, byLastNameAsc);
33 |
34 | for (int i = 0; i < persons.size(); i++) {
35 | Person current = persons.get(i);
36 | if (i < persons.size() - 1) {
37 | Person next = persons.get(i + 1);
38 | assertThat(current.getLastName().compareTo(next.getLastName()), lessThanOrEqualTo(0));
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/test/java/de/codecentric/java8examples/lambdas/LambdaExampleTest.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.lambdas;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import java.time.LocalDate;
7 | import java.util.function.Predicate;
8 |
9 | import de.codecentric.java8examples.Person;
10 | import org.junit.Before;
11 | import org.junit.Test;
12 |
13 | /**
14 | * Test case showing how lambda expressions work.
15 | */
16 | public class LambdaExampleTest {
17 |
18 | private LambdaExample example;
19 | private Person peter;
20 |
21 | @Before
22 | public void setUp() throws Exception {
23 | // Nerd info: 5/15/1962 was the release date of Amazing Fantasy #15, where Spider Man had his first appearance
24 | peter = new Person("Peter", "Parker", LocalDate.of(1962, 8, 15), Person.Gender.MALE);
25 | example = new LambdaExample<>(peter);
26 | }
27 |
28 | @Test
29 | public void peterIsOlderThan30() throws Exception {
30 | // old school
31 | assertTrue(example.matches(new Predicate() {
32 | @Override
33 | public boolean test(Person person) {
34 | return person.getAge() > 30;
35 | }
36 | }));
37 | }
38 |
39 | @Test
40 | public void peterIsOlderThan30WithBlockLambda() throws Exception {
41 | // new: implement the predicate using a block lambda expression
42 | assertTrue(example.matches((Person p) -> {
43 | return p.getAge() > 30;
44 | }));
45 | }
46 |
47 | @Test
48 | public void peterIsOlderThan30WithOneLineLambda() throws Exception {
49 | // implement the predicate using a one line lambda expression
50 | assertTrue(example.matches((Person person) -> person.getAge() > 30));
51 | }
52 |
53 | @Test
54 | public void peterIsOlderThan30WithTypeInference() throws Exception {
55 | // even shorter: let the compiler work out the correct type
56 | assertTrue(example.matches(p -> p.getAge() > 30));
57 | }
58 |
59 | @Test
60 | public void getAgeFromWrappedElementViaFunctionApplication() throws Exception {
61 | // type is inferred from context
62 | assertEquals("Parker", example.apply(p -> p.getLastName()));
63 | // different notation using a method reference
64 | assertEquals("Parker", example.apply(Person::getLastName));
65 | }
66 |
67 | @Test
68 | public void changeStateOfWrappedElementViaConsumer() throws Exception {
69 | // this will change the state of the wrapped element!
70 | example.consume(p -> p.setGender(oppositeOf(p.getGender())));
71 |
72 | assertEquals(Person.Gender.FEMALE, peter.getGender());
73 | }
74 |
75 | private static Person.Gender oppositeOf(Person.Gender gender) {
76 | if (gender.equals(Person.Gender.MALE))
77 | return Person.Gender.FEMALE;
78 | else
79 | return Person.Gender.MALE;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/test/java/de/codecentric/java8examples/methodreference/MethodReferenceExampleTest.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.methodreference;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import java.util.concurrent.Callable;
6 |
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | /**
11 | * Test case showing the use of method references.
12 | */
13 | public class MethodReferenceExampleTest {
14 |
15 | private Foo myFoo;
16 |
17 | @Before
18 | public void setUp() throws Exception {
19 | myFoo = new Foo();
20 | }
21 |
22 | @Test
23 | public void callbackWithoutMethodReference() throws Exception {
24 | Callable callable = new Callable() {
25 | @Override
26 | public String call() throws Exception {
27 | return myFoo.doSomething();
28 | }
29 | };
30 |
31 | assertEquals(myFoo.doSomething(), callable.call());
32 | }
33 |
34 | @Test
35 | public void callbackWithMethodReference() throws Exception {
36 | Callable callable = myFoo::doSomething;
37 |
38 | assertEquals(myFoo.doSomething(), callable.call());
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/test/java/de/codecentric/java8examples/streaming/CollectingAndReducingTest.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.streaming;
2 |
3 | import de.codecentric.java8examples.Invoice;
4 | import de.codecentric.java8examples.InvoiceItem;
5 | import de.codecentric.java8examples.Person;
6 | import de.codecentric.java8examples.TestData;
7 | import org.junit.Test;
8 |
9 | import java.math.BigDecimal;
10 | import java.util.*;
11 |
12 | import static junit.framework.Assert.assertNotNull;
13 | import static org.hamcrest.Matchers.*;
14 | import static org.hamcrest.MatcherAssert.assertThat;
15 |
16 | /**
17 | * Tests for mapping and filtering feature of the streaming api. Once you have completed the stub-methods in
18 | * {@link FilteringAndMapping}, these tests should pass.
19 | */
20 | public class CollectingAndReducingTest {
21 | private List persons = TestData.listOfPersons();
22 | private List invoices = TestData.listOfInvoices();
23 | private List recipients = Arrays.asList("Homer", "Bart", "Marge");
24 |
25 | @Test
26 | public void testAverageAge() throws Exception {
27 | assertThat(
28 | CollectingAndReducing.averageAge(persons),
29 | closeTo(30.57D, 0.01));
30 | }
31 |
32 | @Test
33 | public void testMaxAge() throws Exception {
34 | assertThat(
35 | CollectingAndReducing.maxAge(persons),
36 | equalTo(46));
37 | }
38 |
39 | @Test
40 | public void testAgeStatistics() throws Exception {
41 | IntSummaryStatistics statistic = CollectingAndReducing.ageStatistics(persons);
42 | assertNotNull(statistic);
43 | assertThat(statistic.getAverage(), equalTo(30.571428571428573));
44 | assertThat(statistic.getCount(), equalTo(7l));
45 | assertThat(statistic.getMax(), equalTo(46));
46 | assertThat(statistic.getMin(), equalTo(1));
47 | assertThat(statistic.getSum(), equalTo(214l));
48 | }
49 |
50 | @Test
51 | public void testBuildCommaSeparatedListOfFirstNames() throws Exception {
52 | assertThat(
53 | CollectingAndReducing.buildCommaSeparatedListOfFirstNames(persons),
54 | equalTo("Jane, Mary, John, Michael, Chris, Pete, Maggie"));
55 | }
56 |
57 | @Test
58 | public void testCheapestProduct() throws Exception {
59 | assertThat(
60 | CollectingAndReducing.cheapestProduct(invoices),
61 | equalTo("Chips"));
62 | }
63 |
64 | @Test
65 | public void testMostExpensiveInvoice() throws Exception {
66 | assertThat(
67 | CollectingAndReducing.mostExpensiveInvoice(invoices),
68 | equalTo(invoices.get(2)));
69 |
70 | }
71 |
72 | @Test
73 | public void testGroupInvoicesByRecipient() throws Exception {
74 | Map> invoicesByRecipient =
75 | CollectingAndReducing.groupInvoicesByRecipient(invoices);
76 | assertThat(invoicesByRecipient.keySet(), hasSize(recipients.size()));
77 |
78 | for (String recipient: recipients) {
79 | for (Invoice invoice: invoices) {
80 | if (recipient.equals(invoice.getRecipient())) {
81 | assertThat(invoicesByRecipient.get(recipient),
82 | hasItem(invoice));
83 | } else {
84 | assertThat(invoicesByRecipient.get(recipient),
85 | not(hasItem(invoice)));
86 | }
87 | }
88 | }
89 | }
90 |
91 | @Test
92 | public void testExpensesByRecipient() throws Exception {
93 | Map expencesByRecipient =
94 | CollectingAndReducing.expensesByRecipient(invoices);
95 | assertThat(expencesByRecipient.keySet(), hasSize(recipients.size()));
96 | for (String recipient: recipients) {
97 | BigDecimal expenses = BigDecimal.ZERO;
98 | for (Invoice invoice: invoices) {
99 | if (recipient.equals(invoice.getRecipient())) {
100 | expenses = expenses.add(invoice.getTotal());
101 | }
102 | }
103 | assertThat(expencesByRecipient.get(recipient), equalTo(expenses));
104 | }
105 | }
106 |
107 | @Test
108 | public void testCountByProduct() throws Exception {
109 | Map expected = new HashMap<>();
110 | for (Invoice invoice: invoices) {
111 | for (InvoiceItem item: invoice.getItems()) {
112 | String product = item.getProduct();
113 | if (expected.get(product) == null) {
114 | expected.put(product, Integer.valueOf(0));
115 | }
116 | expected.put(
117 | product,
118 | expected.get(product) + item.getQuantity());
119 | }
120 | }
121 |
122 | Map actual = CollectingAndReducing.countByProduct(invoices);
123 | assertThat(actual.keySet(), hasSize(expected.size()));
124 | for (Map.Entry entry: expected.entrySet()) {
125 | assertThat(actual, hasEntry(entry.getKey(), entry.getValue()));
126 | }
127 | }
128 |
129 | @Test
130 | public void testCheapestDealersByProduct() throws Exception {
131 |
132 | }
133 |
134 | @Test
135 | public void testComputeDealerInventory() throws Exception {
136 | HashMap> expected = new HashMap<>();
137 | for (Invoice invoice: invoices) {
138 | String sender = invoice.getSender();
139 | if (expected.get(sender) == null) {
140 | expected.put(sender, new ArrayList());
141 | }
142 | List itemsOfSender = expected.get(sender);
143 | for (InvoiceItem item: invoice.getItems()) {
144 | CollectingAndReducing.ProductWithPrice newItem = new CollectingAndReducing.ProductWithPrice(item.getProduct(), item.getPricePerUnit());
145 | if (!itemsOfSender.contains(newItem)) {
146 | itemsOfSender.add(newItem);
147 | }
148 | }
149 | }
150 |
151 | Map> actual =
152 | CollectingAndReducing.computeDealerInventory(invoices);
153 |
154 | assertThat(actual.keySet(), hasSize(expected.size()));
155 | for (String sender: expected.keySet()) {
156 | assertThat("Unexpected item set for dealer " + sender, actual.get(sender), containsInAnyOrder(expected.get(sender).toArray()));
157 | }
158 | }
159 |
160 | @Test
161 | public void testFavoriteArticlesByBuyer() throws Exception {
162 |
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/src/test/java/de/codecentric/java8examples/streaming/FilteringAndMappingTest.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.streaming;
2 |
3 | import de.codecentric.java8examples.Invoice;
4 | import de.codecentric.java8examples.Person;
5 | import de.codecentric.java8examples.TestData;
6 | import org.hamcrest.MatcherAssert;
7 | import org.junit.Test;
8 |
9 | import java.util.List;
10 |
11 | import static org.hamcrest.Matchers.contains;
12 | import static org.hamcrest.Matchers.containsInAnyOrder;
13 | import static org.junit.Assert.assertThat;
14 |
15 | /**
16 | * Tests for mapping and filtering feature of the streaming api. Once you have completed the stub-methods in {@link FilteringAndMapping}, these tests should
17 | * pass.
18 | */
19 | public class FilteringAndMappingTest {
20 |
21 | private List persons = TestData.listOfPersons();
22 |
23 | private List invoices = TestData.listOfInvoices();
24 |
25 | @Test
26 | public void collectFirstNamesOfFemales() throws Exception {
27 | // Matchers.contains should really be called "containsExactlyTheseElementsAndNoOtherElementsInExactlyThisOrder"
28 | // I hate hamcrest :(
29 | assertThat(FilteringAndMapping.extractFemaleFirstnames(persons), contains("Jane", "Mary", "Maggie"));
30 | }
31 |
32 | @Test
33 | public void extractNames() {
34 | assertThat(FilteringAndMapping.extractNames(persons.subList(0, 6)),
35 | contains("Jane Jungle", "Mary Smith", "John Dole", "Michael Abrahams", "Chris Cross", "Pete Power"));
36 | }
37 |
38 | @Test
39 | public void extractNamesSortedByLastname() {
40 | assertThat(FilteringAndMapping.extractNamesSortedByLastname(persons.subList(0, 6)),
41 | contains("Michael Abrahams", "Chris Cross", "John Dole", "Jane Jungle", "Pete Power", "Mary Smith"));
42 | }
43 |
44 | @Test
45 | public void extractAdultWomen() {
46 | // Yes, I know, this test is time-dependent and will break in a few months/years...
47 | assertThat(FilteringAndMapping.extractAdultWomen(persons), contains(persons.get(0), persons.get(1)));
48 | }
49 |
50 | @Test
51 | public void extractFirstnamesWhereLastnameStartsWith() {
52 | assertThat(FilteringAndMapping.extractFirstnamesWhereLastnameStartsWith(persons, "S"), contains("Maggie", "Mary"));
53 | }
54 |
55 | @Test
56 | public void testExtractAllProducts() throws Exception {
57 | MatcherAssert.assertThat(FilteringAndMapping.extractAllProducts(invoices),
58 | containsInAnyOrder("Beer", "Burger", "Corn Flakes", "Chips", "Coke", "Cake", "Left-Handed Scissors"));
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/test/java/de/codecentric/java8examples/timeapi/TimeApiTest.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.java8examples.timeapi;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertFalse;
5 | import static org.junit.Assert.assertTrue;
6 |
7 | import java.text.DateFormat;
8 | import java.text.ParseException;
9 | import java.text.SimpleDateFormat;
10 | import java.time.LocalDate;
11 | import java.time.LocalDateTime;
12 | import java.time.Month;
13 | import java.time.Period;
14 | import java.time.ZoneId;
15 | import java.time.ZonedDateTime;
16 | import java.time.chrono.ThaiBuddhistDate;
17 | import java.time.format.DateTimeFormatter;
18 | import java.time.temporal.ChronoField;
19 | import java.util.Calendar;
20 | import java.util.Date;
21 | import java.util.GregorianCalendar;
22 | import java.util.TimeZone;
23 |
24 | import org.joda.time.DateTime;
25 | import org.joda.time.DateTimeFieldType;
26 | import org.joda.time.DateTimeZone;
27 | import org.joda.time.Interval;
28 | import org.joda.time.chrono.BuddhistChronology;
29 | import org.joda.time.format.DateTimeFormat;
30 | import org.junit.Test;
31 |
32 | import sun.util.BuddhistCalendar;
33 |
34 | /**
35 | * Why JSR-310 isn't Joda-Time
36 | * nice presentation (JUG Ukraine)
37 | * project page
38 | * Java-Doc
39 | *
40 | *
41 | *
Joda
42 | *
43 | *
Instant - Milliseconds from 1970-01-01T00:00Z
44 | *
Partial - Only partially represent a date or time in the datetime continuum.
45 | *
Interval - Time between two instants (TimeZone aware)
46 | *
Duration - No TimeZone aware or Chronology, just millis
47 | *
Period - No TimeZone aware or Chronology, defined in terms of fields, for ex: 1 day 5 hrs. Differs from Duration in that it is inexact in terms of
48 | * millis.
49 | *
Chronology - Pluggable chronologies. A Chronology is obtained and used in Joda-Time as a singleton (Iso is default)
50 | *
TimeZone - Bazed on TZ(Olson). Frquently updatable. You can also update whenever required.
51 | *
52 | *
53 | *
LocalDate - just date w/o tz, e.g. 2013-02-22
54 | *
LocalTime - just time w/o tz, e.g. 10:15:30
55 | *
LocalDateTime - date and time w/o offset, e.g. 2013-02-22 T10:15:30
56 | *
DateTime - date with time and DateTimeZone
57 | *
58 | *
59 | *
JSR-310
60 | *
61 | *
Instant - An instant is a specific point on a discretized timeline. An example of an instant is "January 7, 2008, at time 23:00:00.0 UTC."
62 | *
63 | * Partial (for example MonthDay, YearMonth)- A partial is an indication of date or time that is not sufficient to specify a specific, unique point on the
64 | * timeline. For example, "June 7" is a partial, because it specifies a month and day, but it does not specify a year or time of day.
65 | *
Interval - Was planned, but removed later - NOT EXISTING
66 | *
Duration - A duration represents a length of elapsed time, defined to the nanosecond level; for example, "100,000 nanoseconds" is a duration.
67 | *
Period - Like durations, periods represent a length of elapsed time. Examples of periods are "4 years, 8 days," and "1 hour." As shown by these examples,
68 | * periods are defined using calendar fields (years, days, hours, etc.), rather than by an exact number of nanoseconds.
69 | *
Chronology - A calendar system, used to organize and identify dates. (Iso is default for LocalDate)
70 | *
71 | *
72 | *
LocalDate - just date w/o tz, e.g. 2013-02-22
73 | *
LocalTime - just time w/o tz, e.g. 10:15:30
74 | *
LocalDateTime - date and time w/o offset, e.g. 2013-02-22 T10:15:30
75 | *
ZoneOffset - offset against UTC (positive or negative), e.g. +05:00, +01:00, -02:00, +04:30, Z, CEST, UTC, GMT
76 | *
OffsetDate - date w/o time but with offset, e.g. 2013-12-03+02:00
77 | *
OffsetTime - time w/o date but with offset, e.g. 10:15:30+02:00