11. @JosePaumard
#50new8
Date : Instant
Un Instant est un point sur une timeline
Instant start = Instant.now() ;
Instant end = Instant.now() ;
12. @JosePaumard
#50new8
Date : Duration
Une « duration » est le temps entre deux Instant
Instant start = Instant.now() ;
Instant end = Instant.now() ;
Duration elapsed = Duration.between(start, end) ;
long millis = elapsed.toMillis() ;
13. @JosePaumard
#50new8
Date : Duration
On a une arithmétique sur les « Duration »
Instant start = Instant.now() ;
Instant end = Instant.now() ;
Duration elapsed = Duration.between(start, end) ;
long millis = elapsed.toMillis() ;
elapsed.plus(2L, TemporalUnit.SECONDS) ;
15. @JosePaumard
#50new8
Date : Duration
La précision de la time line est de 10-9 s (nanosecond)
Bonne précision ?
16. @JosePaumard
#50new8
Date : Duration
La précision de la time line est de 10-9 s (nanosecond)
Bonne précision ?
La demie-vie du
boson de Higgs est de 10-23 s
17. @JosePaumard
#50new8
Date : LocalDate
Une « LocalDate » est une date de tous les jours
LocalDate now = LocalDate.now() ;
LocalDate shakespeareDoB =
LocaleDate.of(1564, Month.APRIL, 23) ;
18. @JosePaumard
#50new8
Date : Period
Une « Period » est le temps entre deux LocalDate
LocalDate now = LocalDate.now() ;
LocalDate shakespeareDoB =
LocaleDate.of(1564, Month.APRIL, 23) ;
Period p = shakespeareDoB.until(now) ;
System.out.println("# years = " + p.getYears()) ;
19. @JosePaumard
#50new8
Date : Period
Une « Period » est le temps entre deux LocalDate
LocalDate now = LocalDate.now() ;
LocalDate shakespeareDoB =
LocaleDate.of(1564, Month.APRIL, 23) ;
Period p = shakespeareDoB.until(now) ;
System.out.println("# years = " + p.getYears()) ;
long days = shakespeareDoB.until(now, ChronoUnit.DAYS) ;
System.out.println("# days = " + days) ;
20. @JosePaumard
#50new8
Date : TemporalAdjuster
On a une arithmétique sur les « local date »
LocalDate now = LocalDate.now() ;
LocalDate nextSunday =
now.with(TemporalAdjuster.next(DayOfWeek.SUNDAY)) ;
21. @JosePaumard
#50new8
Date : TemporalAdjuster
On a une arithmétique sur les « local date »
Une boîte à outils de 14 méthodes statiques
firstDayOfMonth(), lastDayOfYear()
firstDayOfNextMonth()
LocalDate now = LocalDate.now() ;
LocalDate nextSunday =
now.with(TemporalAdjuster.next(DayOfWeek.SUNDAY)) ;
22. @JosePaumard
#50new8
Date : TemporalAdjuster
On a une arithmétique sur les « local date »
Une boîte à outils de 14 méthodes statiques
firstInMonth(DayOfWeek.MONDAY)
next(DayOfWeek.FRIDAY)
LocalDate now = LocalDate.now() ;
LocalDate nextSunday =
now.with(TemporalAdjuster.next(DayOfWeek.SUNDAY)) ;
23. @JosePaumard
#50new8
Date : LocalTime
Un « LocalTime » est un heure de tous les jours : ex. 10:20
LocalTime now = LocalTime.now() ;
LocalTime time = LocalTime.of(10, 20) ; // 10:20
24. @JosePaumard
#50new8
Date : LocalTime
Un « LocalTime » est un heure de tous les jours : ex. 10:20
LocalTime now = LocalTime.now() ;
LocalTime time = LocalTime.of(10, 20) ; // 10:20
LocalTime lunchTime = LocalTime.of(12, 30) ;
LocalTime coffeeTime = lunchTime.plusHours(2) ; // 14:20
25. @JosePaumard
#50new8
Date : ZonedTime
Utiles pour les dates localisées
Set<String> allZonesIds = ZoneId.getAvailableZoneIds() ;
String ukTZ = ZoneId.of("Europe/London") ;
26. @JosePaumard
#50new8
Date : ZonedTime
Utiles pour les dates localisées
System.out.println(
ZonedDateTime.of(
1564, Month.APRIL.getValue(), 23, // year / month / day
10, 0, 0, 0, // h / mn / s / nanos
ZoneId.of("Europe/London"))
); // prints 1564-04-23T10:00-00:01:15[Europe/London]
27. @JosePaumard
#50new8
Date : ZonedTime
On a aussi une arithmétique dessus
ZonedDateTime currentMeeting =
ZonedDateTime.of(
LocalDate.of(2014, Month.APRIL, 18), // LocalDate
LocalTime.of(9, 30), // LocalTime
ZoneId.of("Europe/London")
);
ZonedDateTime nextMeeting =
currentMeeting.plus(Period.ofMonth(1));
28. @JosePaumard
#50new8
Date : ZonedTime
On a aussi une arithmétique dessus
ZonedDateTime currentMeeting =
ZonedDateTime.of(
LocalDate.of(2014, Month.APRIL, 18), // LocalDate
LocalTime.of(9, 30), // LocalTime
ZoneId.of("Europe/London")
);
ZonedDateTime nextMeeting =
currentMeeting.plus(Period.ofMonth(1)) ;
ZonedDateTime nextMeetingUS =
nextMeeting.withZoneSameInstant(ZoneId.of("US/Central")) ;
29. @JosePaumard
#50new8
Date : Formatter
Classe factory : DateTimeFormatter
ZonedDateTime nextMeetingUS =
nextMeeting.withZoneSameInstant(ZoneId.of("US/Central"));
System.out.println(
DateTimeFormatter.ISO_DATE_TIME.format(nextMeetingUS)
);
// prints 2014-04-12T03:30:00-05:00[US/Central]
System.out.println(
DateTimeFormatter.RFC_1123_DATE_TIME.format(nextMeetingUS)
);
// prints Sat, 12 Apr 2014 03:30:00 -0500
30. @JosePaumard
#50new8
Date : liens avec java.util.Date
Date & Time API vs java.util.Date
Date date = Date.from(instant); // API -> legacy
Instant instant = date.toInstant(); // legacy -> new API
31. @JosePaumard
#50new8
Date : liens avec java.util.Date
Date & Time API vs java.util.Date
TimeStamp time = TimeStamp.from(instant); // API -> legacy
Instant instant = time.toInstant(); // legacy -> new API
Date date = Date.from(instant); // API -> legacy
Instant instant = date.toInstant(); // legacy -> new API
32. @JosePaumard
#50new8
Date : liens avec java.util.Date
Date & Time API vs java.util.Date
Date date = Date.from(localDate); // API -> legacy
LocalDate localDate = date.toLocalDate(); // legacy -> new API
TimeStamp time = TimeStamp.from(instant); // API -> legacy
Instant instant = time.toInstant(); // legacy -> new API
Date date = Date.from(instant); // API -> legacy
Instant instant = date.toInstant(); // legacy -> new API
33. @JosePaumard
#50new8
Date : liens avec java.util.Date
Date & Time API vs java.util.Date
Time time = Time.from(localTime); // API -> legacy
LocalTime localTime = time.toLocalTime(); // legacy -> new API
Date date = Date.from(localDate); // API -> legacy
LocalDate localDate = date.toLocalDate(); // legacy -> new API
TimeStamp time = TimeStamp.from(instant); // API -> legacy
Instant instant = time.toInstant(); // legacy -> new API
Date date = Date.from(instant); // API -> legacy
Instant instant = date.toInstant(); // legacy -> new API
35. @JosePaumard
#50new8
String : Stream
Un Stream sur les lettres qui composent une String
String s = "hello";
IntStream stream = s.chars(); // stream on the letters of s
36. @JosePaumard
#50new8
String : Stream
Un Stream sur les lettres qui composent une String
String s = "hello";
IntStream stream = s.chars(); // stream on the letters of s
s.chars()
.map(Character::toUpperCase)
.forEach(System.out::println);
37. @JosePaumard
#50new8
String : Stream
Un Stream sur les lettres qui composent une String
String s = "hello";
IntStream stream = s.chars(); // stream on the letters of s
s.chars()
.map(Character::toUpperCase)
.forEach(System.out::println);
>
HELLO
7269767679
38. @JosePaumard
#50new8
String : Stream
Un Stream sur les lettres qui composent une String
String s = "hello";
IntStream stream = s.chars(); // stream on the letters of s
s.chars() // IntStream
.map(Character::toUpperCase)
.forEach(System.out::println); // Prints an int!
>
7269767679
39. @JosePaumard
#50new8
String : Stream
Un Stream sur les lettres qui composent une String
String s = "hello";
IntStream stream = s.chars(); // stream on the letters of s
s.chars() // IntStream
.mapToObj(letter -> (char)letter) // Stream<Character>
.map(Character::toUpperCase)
.forEach(System.out::println); // Prints a Character
>
HELLO
40. @JosePaumard
#50new8
String : expressions régulières
Un Stream sur une expression régulière
// book is a looooooooong String
Stream<String> words =
Pattern
.compile("[^p{javaLetter}]")
.splitAsStream(book) ;
42. @JosePaumard
#50new8
String : concaténation
L’ignorant lui dit d’écrire :
StringBuffer sb1 = new StringBuffer("hello") ;
sb1.append(" world") ;
String s3 = sb1.toString() ;
(et il a tord)
43. @JosePaumard
#50new8
String : concaténation
Le développeur expérimenté lui dit d’écrire :
StringBuilder sb1 = new StringBuilder("hello") ;
sb1.append(" world") ;
String s3 = sb1.toString() ;
(et il se trompe aussi…)
44. @JosePaumard
#50new8
String : concaténation
Parce que le débutant a raison (même s’il ne le sait pas)
String s1 = "hello" ;
String s2 = " world!" ;
String s3 = s1 + " " + s2 ;
LINENUMBER 10 L2
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
LDC " "
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 3
45. @JosePaumard
#50new8
String : concaténation
L’expert Java 8 écrit :
// The JDK 8 way
StringJoiner sj = new StringJoiner(", ") ;
sj.add("one").add("two").add("three") ;
String s = sj.toString() ;
System.out.println(s) ;
46. @JosePaumard
#50new8
String : concaténation
L’expert Java 8 écrit :
Ce qui écrit :
// The JDK 8 way
StringJoiner sj = new StringJoiner(", ") ;
sj.add("one").add("two").add("three") ;
String s = sj.toString() ;
System.out.println(s) ;
> one, two, three
47. @JosePaumard
#50new8
String : concaténation
L’expert Java 8 écrit :
Ce qui écrit :
// The JDK 8 way
StringJoiner sj = new StringJoiner(", ") ;
sj.add("one") ;
String s = sj.toString() ;
System.out.println(s) ;
> one
48. @JosePaumard
#50new8
String : concaténation
L’expert Java 8 écrit :
Ce qui écrit :
// The JDK 8 way
StringJoiner sj = new StringJoiner(", ", "{", "}") ;
sj.add("one").add("two").add("three") ;
String s = sj.toString() ;
System.out.println(s) ;
> {one, two, three}
49. @JosePaumard
#50new8
String : concaténation
L’expert Java 8 écrit :
Ce qui écrit :
// The JDK 8 way
StringJoiner sj = new StringJoiner(", ", "{", "}") ;
sj.add("one") ;
String s = sj.toString() ;
System.out.println(s) ;
> {one}
50. @JosePaumard
#50new8
String : concaténation
L’expert Java 8 écrit :
Ce qui écrit :
// The JDK 8 way
StringJoiner sj = new StringJoiner(", ", "{", "}") ;
// we dont put anything in it
String s = sj.toString() ;
System.out.println(s) ;
> {}
51. @JosePaumard
#50new8
String : concaténation
Et on peut presque le faire de la classe String :
Ce qui écrit :
// From the String class, with a vararg
String s = String.join(", ", "one", "two", "three");
System.out.println(s);
> one, two, three
52. @JosePaumard
#50new8
String : concaténation
Et on peut presque le faire de la classe String :
Ce qui écrit :
// From the String class, with an Iterable
String [] tab = {"one", "two", "three"} ;
String s = String.join(", ", tab) ;
System.out.println(s) ;
> one, two, three
54. @JosePaumard
#50new8
Nombres : nouvelles méthodes
Méthodes max, min, sum
// max method available on number wrapper classes
long max = Long.max(1L, 2L);
long sum = Long.sum(1L, 2L);
55. @JosePaumard
#50new8
Nombres : nouvelles méthodes
Méthodes max, min, sum
Si utile que ça ?
// max method available on number wrapper classes
long max = Long.max(1L, 2L);
long sum = Long.sum(1L, 2L);
56. @JosePaumard
#50new8
Nombres : nouvelles méthodes
Méthodes max, min, sum
Si utile que ça ?
// max method available on number wrapper classes
long max = Long.max(1L, 2L);
long sum = Long.sum(1L, 2L);
persons.stream()
.map(Person::getAge)
.reduce(0, (a1, a2) -> Integer.max(a1, a2));
57. @JosePaumard
#50new8
Nombres : nouvelles méthodes
Méthodes max, min, sum
Si utile que ça ? Utile pour écrire des method references
// max method available on number wrapper classes
long max = Long.max(1L, 2L);
long sum = Long.sum(1L, 2L);
persons.stream()
.map(Person::getAge)
.reduce(0, Integer::max);
58. @JosePaumard
#50new8
Nombres : nouvelles méthodes
Méthodes max, min, sum
// max method available on number wrapper classes
long max = Long.max(1L, 2L);
long sum = Long.sum(1L, 2L);
persons.stream()
.mapToInt(Person::getAge)
.max();
59. @JosePaumard
#50new8
Nombres : nouvelles méthodes
Méthodes max, min, sum
// max method available on number wrapper classes
long max = Long.max(1L, 2L);
long sum = Long.sum(1L, 2L);
persons.stream()
.max(Comparator.comparingBy(Person::getAge));
60. @JosePaumard
#50new8
Nombres : nouvelles méthodes
Calcul de code du hachage
// JDK 7
long l = 3141592653589793238L;
int hash = new Long(l).hashCode(); // -1985256439
61. @JosePaumard
#50new8
Nombres : nouvelles méthodes
Calcul de code du hachage
// JDK 7
long l = 3141592653589793238L;
int hash = new Long(l).hashCode(); // -1985256439
// JDK 8
long l = 3141592653589793238L;
int hash = Long.hashCode(l); // -1985256439
68. @JosePaumard
#50new8
Iterable : forEach
ForEach : permet de consommer les éléments
Dommage : pas sur les tableaux
// method forEach defined on Iterable
List<String> strings =
Arrays.asList("one", "two", "three") ;
strings.forEach(System.out::println) ;
> one, two, three
69. @JosePaumard
#50new8
Collection : removeIf
Retire un objet à partir d’un prédicat
Collection<String> strings =
Arrays.asList("one", "two", "three", "four");
// works « in place », no Collections.unmodifiable...
Collection<String> list = new ArrayList<>(strings);
// returns true if the list has been modified
boolean b = list.removeIf(s -> s.length() > 4);
> one, two, four
70. @JosePaumard
#50new8
List : replaceAll
Remplace un objet par sa transformation
List<String> strings =
Arrays.asList("one", "two", "three", "four");
// works « in place », no Collections.unmodifiable...
List<String> list = new ArrayList<>(strings);
// returns nothing
list.replaceAll(String::toUpperCase);
> ONE, TWO, THREE, FOUR
71. @JosePaumard
#50new8
List : sort
Trie une liste « en place », à l’aide d’un Comparator
List<String> strings =
Arrays.asList("one", "two", "three", "four");
// works « in place », no Collections.unmodifiable...
List<String> list = new ArrayList<>(strings);
// returns nothing
list.sort(Comparator.naturalOrder()) ;
> four, one, three, two
74. @JosePaumard
#50new8
Comparator !
Que dire de mieux ?
Comparator.naturalOrder()
public static
<T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>)
Comparators.NaturalOrderComparator.INSTANCE;
}
75. @JosePaumard
#50new8
Comparator !
enum NaturalOrderComparator
implements Comparator<Comparable<Object>> {
INSTANCE; // What is this???
}
76. @JosePaumard
#50new8
Comparator !
enum NaturalOrderComparator
implements Comparator<Comparable<Object>> {
INSTANCE; // OMG: a SINGLETON!!!
}
public class MySingleton {
INSTANCE;
private MySingleton() {}
public static MySingleton getInstance() {
// some buggy double-checked locking code
return INSTANCE;
}
}
78. @JosePaumard
#50new8
Comparator !
enum NaturalOrderComparator
implements Comparator<Comparable<Object>> {
INSTANCE;
public int compare(Comparable<Object> c1, Comparable<Object> c2) {
return c1.compareTo(c2);
}
public Comparator<Comparable<Object>> reversed() {
return Comparator.reverseOrder();
}
}
79. @JosePaumard
#50new8
À l’ancienne !
Comparator !
// comparison using the last name
Comparator<Person> compareLastName =
new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.getLastName().compareTo(p2.getLastName());
}
};
80. @JosePaumard
#50new8
Comparator !
// comparison using the last name then the first name
Comparator<Person> compareLastNameThenFirstName =
new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
int lastNameComparison =
p1.getLastName().compareTo(p2.getLastName());
return lastNameComparison == 0 ?
p2.getFirstName().compareTo(p2.getFirstName());
lastNameComparison;
}
};
86. @JosePaumard
#50new8
Comparator !
Et que fait-on pour les valeurs nulles ?
Comparator<Person> comp =
Comparator.naturalOrder();
87. @JosePaumard
#50new8
Comparator !
Et que fait-on pour les valeurs nulles ?
Comparator<Person> comp =
Comparator.nullsFirst(Comparator.naturalOrder());
88. @JosePaumard
#50new8
Comparator !
Et que fait-on pour les valeurs nulles ?
Comparator<Person> comp =
Comparator.nullsFirst(Comparator.naturalOrder());
Comparator<Person> comp =
Comparator.nullsLast(Comparator.naturalOrder());
90. @JosePaumard
#50new8
Optional
Optional a été créé pour indiquer qu’une méthode peut ne retourner « aucune valeur »
Ex : max(), min()
91. @JosePaumard
#50new8
Optional
Optional a été créé pour indiquer qu’une méthode peut ne retourner « aucune valeur »
Ex : max(), min(), average()
92. @JosePaumard
#50new8
Optional
Un Optional est un type enveloppe, qui peut être vide
Comment peut-on en créer un ?
Optional<String> opt = Optional.<String>empty() ;
Optional<String> opt = Optional.of("one") ; // not null
Optional<String> opt = Optional.ofNullable(s) ; // may be null
93. @JosePaumard
#50new8
Optional
Un Optional est un type enveloppe, qui peut être vide
Comment peut-on en créer un ?
Optional<String> opt = ... ;
if (opt.isPresent()) {
String s = opt.get() ;
} else {
...
}
94. @JosePaumard
#50new8
Optional
Un Optional est un type enveloppe, qui peut être vide
Comment peut-on en créer un ?
String s = opt.orElse("") ; // this is a default value that
// is valid for our application
Optional<String> opt = ... ;
if (opt.isPresent()) {
String s = opt.get() ;
} else {
...
}
95. @JosePaumard
#50new8
Optional
Un Optional est un type enveloppe, qui peut être vide
Comment peut-on en créer un ?
String s = opt.orElseThrow(MyException::new) ; // lazy initialization
96. @JosePaumard
#50new8
Optional : patterns
Un Optional peut aussi être vu comme un Stream
comportant 0 ou 1 élément
void ifPresent(Consumer<T> consumer) ;
97. @JosePaumard
#50new8
Optional : patterns
Un Optional peut aussi être vu comme un Stream
comportant 0 ou 1 élément
void ifPresent(Consumer<T> consumer) ;
Optional<T> filter(Predicate<T> mapper) ;
98. @JosePaumard
#50new8
Optional : patterns
Un Optional peut aussi être vu comme un Stream
comportant 0 ou 1 élément
void ifPresent(Consumer<T> consumer) ;
Optional<T> filter(Predicate<T> mapper) ;
Optional<U> map(Function<T, U> mapper) ;
99. @JosePaumard
#50new8
Optional : patterns
Un Optional peut aussi être vu comme un Stream
comportant 0 ou 1 élément
void ifPresent(Consumer<T> consumer) ;
Optional<T> filter(Predicate<T> mapper) ;
Optional<U> map(Function<T, U> mapper) ;
Optional<U> flatMap(Function<T, Optional<U>> mapper) ;
100. @JosePaumard
#50new8
Optional : nouveaux patterns en vue !
public class NewMath {
public static Optional<Double> inv(Double d) {
return d == 0.0d ? Optional.empty() :
Optional.of(1/d) ;
}
public static Optional<Double> sqrt(Double d) {
return d < 0.0d ? Optional.empty() :
Optional.of(Math.sqrt(d)) ;
}
}
113. @JosePaumard
#50new8
Map : get
Que se passe-t-il si la clé n’est pas dans la map ?
// the existing map
Map<String, Person> map = ... ;
Person p = map.get(key);
114. @JosePaumard
#50new8
Map : get
On peut retourner une valeur par défaut
// the existing map
Map<String, Person> map = ... ;
Person p = map.getOrDefault(key, Person.DEFAULT_PERSON);
115. @JosePaumard
#50new8
Map : put
Même idée pour le put
// the existing map
Map<String, Person> map = ... ;
map.put(key, person);
116. @JosePaumard
#50new8
Map : putIfAbsent
Même idée pour le put
// the existing map
Map<String, Person> map = ... ;
map.put(key, person);
map.putIfAbsent(key, person);
117. @JosePaumard
#50new8
Map : replace
Même idée pour le replace
// the existing map
Map<String, Person> map = ... ;
// key, newValue
map.replace("six", john) ;
// key, oldValue, newValue
map.replace("six", peter, john) ;
118. @JosePaumard
#50new8
Map : replaceAll
Permet de « remapper » une map avec une l
// the existing map
Map<String, Person> map = ... ;
// key, oldValue
map.replaceAll(
(key, value) -> key + " -> " + value ;
) ;
119. @JosePaumard
#50new8
Map : remove
Efface une paire clé / valeur si elle est la
// the existing map
Map<String, Person> map = ... ;
// key, oldValue
map.remove("six", john) ;
120. @JosePaumard
#50new8
Map : compute
Calcule une valeur à partir d’une paire clé / valeur existante, et d’une l
// the existing map
Map<String, Person> map = ... ;
// key, oldValue
map.compute(
key,
(key, person) -> key + "::" + person // person can be null
) ;
121. @JosePaumard
#50new8
Map : computeIfAbsent
Calcule une valeur à partir d’une clé si elle n’est pas dans la map
// the existing map
Map<String, Person> map = ... ;
// key, no existing value
map.computeIfAbsent(
key,
key -> person
) ;
122. @JosePaumard
#50new8
Map : computeIfPresent
Calcule une valeur à partir d’une paire clé / valeur présente, et d’une l
// the existing map
Map<String, Person> map = ... ;
// key, the existing value
map.computeIfPresent(
key, person,
(key, person) -> newPerson // person cannot be null
) ;
123. @JosePaumard
#50new8
Map : compute*
Le truc, c’est que ces méthodes retournent la valeur, qu’elle ait été juste créée ou pas
124. @JosePaumard
#50new8
Construire des maps de maps
Construire des maps de maps devient un jeu d’enfant !
// the existing map
Map<String, Map<String, Person>> map = ... ;
// key, newValue
map.computeIfAbsent(
"one",
(key) -> HashMap::new
).put("two", john);
125. @JosePaumard
#50new8
Map : merge
Calcule une nouvelle valeur à partir de la paire clé / valeur existante, d’une valeur à ajouter, et d’une l
// the existing map
Map<Long, String> map = ... ;
// key, otherValue
map.merge(
key,
otherValue,
(value, otherValue) -> String.join(", ", value, otherValue)
) ;
127. @JosePaumard
#50new8
Annotations en Java 7
Une annotation ne peut être posée qu’une fois
Donc on crée des annotations enveloppe…
@TestCases({
@TestCase(param=1, expected=false),
@TestCase(param=2, expected=true)
})
public boolean even(int param) {
return param % 2 == 0;
}
128. @JosePaumard
#50new8
Annotations en Java 8
Avec Java 8, on peut !
@TestCase(param=1, expected=false),
@TestCase(param=2, expected=true)
public boolean even(int param) {
return param % 2 == 0;
}
130. @JosePaumard
#50new8
Comment ça marche ?
D’abord, on crée nos annotations comme avant
@interface TestCase {
int param();
boolean expected();
}
@interface TestCases {
TestCase[] value();
}
131. @JosePaumard
#50new8
Comment ça marche ?
Et on ajoute @Repeatable
@Repeatable(TestCases.class)
@interface TestCase {
int param();
boolean expected();
}
@interface TestCases {
TestCase[] value();
}
132. @JosePaumard
#50new8
Type annotations
Les annotations peuvent être posées sur les types
Exemple 1 : nous dit que persons ne peut pas être nul
private @NonNull List<Person> persons = ... ;
133. @JosePaumard
#50new8
Type annotations
Les annotations peuvent être posées sur les types
Exemple 1 : nous dit que persons ne peut pas être nul
Exemple 2 : la liste ne peut contenir des valeurs nulles
private @NonNull List<Person> persons = ... ;
private @NonNull List<@NonNull Person> persons = ... ;
135. @JosePaumard
#50new8
Parallel Arrays
Arrays.parallelSetAll
long [] array = new long [...] ;
Arrays.parallelSetAll(array, index -> index % 3) ;
System.out.println(Arrays.toString(array)) ;
136. @JosePaumard
#50new8
Parallel Arrays
Arrays.parallelPrefix : fold right
long [] array = new long [...] ;
Arrays.parallelPrefix(array, (l1, l2) -> l1 + l2) ;
System.out.println(Arrays.toString(array)) ;
long [] array = {1L, 1L, 1L, 1L} ;
> [1, 2, 3, 4]
137. @JosePaumard
#50new8
Parallel Arrays
Arrays.parallelSort : tri « en place »
long [] array = new long [...] ;
Arrays.parallelSort(array) ;
System.out.println(Arrays.toString(array)) ;
141. @JosePaumard
#50new8
CompletableFuture
On peut alors créer des pipelines
CompletableFuture.supplyAsync(
() ->
readWebPage(url)
)
.thenApply(
content -> getImages(content) // returns a List<Image>
) ; // returns a CompletableFuture<List<Image>>
142. @JosePaumard
#50new8
CompletableFuture
On peut alors créer des pipelines
CompletableFuture.supplyAsync(
() ->
readWebPage(url)
)
.thenApply(
content -> getImages(content) // returns a List<Image>
)
.thenAccept(
images -> images.forEach(System.out::println)
);
143. @JosePaumard
#50new8
CompletableFuture
thenCompose() : permet de composer les choses
CompletableFuture.supplyAsync(
() ->
readWebPage(url)
)
.thenCompose(
content -> getImages(content) // returns List<Image>
)
144. @JosePaumard
#50new8
CompletableFuture
allOf : termine quand tout les calculs sont faits (anyOf)
CompletableFuture.allOf(
CompletableFuture.supplyAsync(
() ->
readWebPage(url)
)
.thenCompose(content -> getImages(content))
.thenApply(image -> writeToDisk(image))
)
.join() ;
145. @JosePaumard
#50new8
CompletableFuture
thenCombine : combine plusieurs CF avec une l
La l est appliquée au résultat des deux CF
CompletableFuture cf1 = ... ;
CompletableFuture cf2 = ... ;
cf1.thenCombine(cf2, (b1, b2) -> b1 & b2) ; // can combine
// the results of CFs
146. @JosePaumard
#50new8
CompletableFuture
thenCombine : combine plusieurs CF avec une l
La l est appliquée au résultat des deux CF
On a aussi : thenAcceptBoth, runAfterBoth
CompletableFuture cf1 = ... ;
CompletableFuture cf2 = ... ;
cf1.thenCombine(cf2, (b1, b2) -> b1 & b2) ; // can combine
// the results of CFs
147. @JosePaumard
#50new8
CompletableFuture
applyToEither : prend le premier résultat disponible
CompletableFuture cf1 = ... ;
CompletableFuture cf2 = ... ;
cf1.applyToEither(cf2, (b) -> ...) ; // applies to the first
// CF that returns
148. @JosePaumard
#50new8
CompletableFuture
applyToEither : prend le premier résultat disponible
acceptEither, runAfterEither
CompletableFuture cf1 = ... ;
CompletableFuture cf2 = ... ;
cf1.applyToEither(cf2, (b) -> ...) ; // applies to the first
// CF that returns
150. @JosePaumard
#50new8
Variables atomiques
Java 5 :
AtomicLong atomic = new AtomicLong() ;
long l1 = atomic.incrementAndGet() ;
151. @JosePaumard
#50new8
Variables atomiques
Java 8 nous amène :
AtomicLong atomic = new AtomicLong() ;
long l1 = atomic.incrementAndGet() ;
long l2 = atomic.updateAndGet(l -> l*2 + 1) ;
152. @JosePaumard
#50new8
Variables atomiques
Java 8 nous amène :
AtomicLong atomic = new AtomicLong() ;
long l1 = atomic.incrementAndGet() ;
long l2 = atomic.updateAndGet(l -> l*2 + 1) ;
long l3 = atomic.accumulateAndGet(12L, (l1, l2) -> l1 % l2) ;
153. @JosePaumard
#50new8
LongAdder
Java 8 nous amène :
LongAdder adder = new LongAdder() ;
adder.increment() ; // in a thread
adder.increment() ; // in a 2nd thread
adder.increment() ; // in a 3rd thread
long sum = adder.sum() ;
154. @JosePaumard
#50new8
LongAccumulator
Idem, avec une l :
LongAccumulator accu =
new LongAccumulator((l1, l2) -> Long.max(l1, l2), 0L) ;
accu.accumulate(value1) ; // in a thread
accu.accumulate(value2) ; // in a 2nd thread
accu.accumulate(value2) ; // in a 3rd thread
long sum = accu.longValue() ;
155. @JosePaumard
#50new8
StampedLock
Un lock normal, avec lecture optimiste
long stamp = sl.writeLock() ;
try {
...
} finally {
sl.unlockWrite(stamp) ;
}
long stamp = sl.readLock() ;
try {
...
} finally {
sl.unlockRead(stamp) ;
}
StampedLock sl= new StampedLock() ;
156. @JosePaumard
#50new8
StampedLock
Un lock normal, avec lecture optimiste
Lecture / écriture exclusives, mais…
long stamp = sl.writeLock() ;
try {
...
} finally {
sl.unlockWrite(stamp) ;
}
long stamp = sl.readLock() ;
try {
...
} finally {
sl.unlockRead(stamp) ;
}
StampedLock sl= new StampedLock() ;
157. @JosePaumard
#50new8
StampedLock
Un lock normal, avec lecture optimiste
StampedLock sl= new StampedLock() ;
long stamp = sl.tryOptimisticRead() ;
// here we read a variable that can be changed in another thread
if (lock.validate(stamp)) {
// the read was not concurrent
} else {
// another thread acquired a write lock
}
159. @JosePaumard
#50new8
ConcurrentHashMap
La vieille ConcurrentHashMap V7 a été retirée
Thread safe
Pas de lock ≠ ConcurrentHashMap V7
Des nouvelles méthodes (un paquet…)
164. @JosePaumard
#50new8
ConcurrentHashMap
Ne jamais utiliser size()
int count = map.size() ; // should not be used
count = map.mappingCount() ; // new method
165. @JosePaumard
#50new8
ConcurrentHashMap
Ne jamais utiliser size()
int count = map.size() ; // should not be used
long count = map.mappingCount() ; // new method
168. @JosePaumard
#50new8
ConcurrentHashMap
Méthode search()
Si la map contient plus de 10 éléments, la recherche aura lieu en parallèle !
ConcurrentHashMap<Integer, String> map = ... ;
map.search(10L, (key, value) -> value.length() < key) ;
169. @JosePaumard
#50new8
ConcurrentHashMap
Méthode search()
Si la map contient plus de 10 éléments, la recherche aura lieu en parallèle !
On peut passer 0 ou Long.MAX_VALUE
ConcurrentHashMap<Integer, String> map = ... ;
map.search(10L, (key, value) -> value.length() < key) ;
172. @JosePaumard
#50new8
Pas de ConcurrentHashSet
Mais…
Set<String> set = ConcurrentHashMap.newKeySet() ;
173. @JosePaumard
#50new8
Pas de ConcurrentHashSet
Mais…
Crée une concurrent hashmap dans laquelle les valeurs sont Boolean.TRUE
Se comporte donc comme un ConcurrentSet
Set<String> set = ConcurrentHashMap.newKeySet() ;