forked from forax/java-guide
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chapter10-string_formatting.jsh
104 lines (81 loc) · 3.61 KB
/
chapter10-string_formatting.jsh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// To starts, run jshell --enable-preview which is a program able to interpret Java syntax
// then cut and paste the following lines to see how it works
// To exit jshell type /exit
// # String formatting
// There are several ways to concatenate/format objects to strings in Java,
// mostly depending if there are a fixed number of values or
// if the values are in a list or any other data structures.
// Let say we have some friends
record Friend(String name) {}
var bob = new Friend("bob");
var ana = new Friend("ana");
var jul = new Friend("jul");
// ## With a fixed number of values
// If there is a fixed number of value, the concatenation using '+' is the
// most readable (ok, when your are used to) and the fastest
// ### Concatenation with +
// Just do a '+' between the different values,
// this code is heavily optimized and will allocate only one String
System.out.println(bob.name() + ", " + ana.name() + ", " + jul.name());
// ### Concatenation with String.format()
// If you want more control on the formatting, you can use `String.format`
// that reuse the C formatting style
// But the method `format()` is quite slow.
System.out.println(String.format("%s, %s, %s", bob, ana, jul));
System.out.printf("%s, %s, %s\n", bob, ana, jul);
// ## with a variable number of values
// If there is a variable numbers of values, you have two cases,
// depending if it's a collection of String or not
var strings = List.of("bob", "ana", "jul");
var friends = List.of(bob, ana, jul);
// ### Concatenation with a +
// Never use '+' in this case, because the compiler is not smart enough
// to reuse the same buffer of characters for the whole loop, so it will
// create a new String for each loop trip.
String concatenate(List<?> list) {
var string = "";
var separator = "";
for(var item: list) {
string = string + separator + item; // creates two many strings, ahhhh
separator = ", ";
}
return string;
}
System.out.println(concatenate(strings));
System.out.println(concatenate(friends));
// ### Concatenation with a StringBuilder
// A StringBuilder is a modifiable version of String with an expandable buffer
// of characters. There is no notion of separators
String concatenate(List<?> list) {
var builder = new StringBuilder();
var separator = "";
for(var item: list) {
builder.append(separator).append(item);
separator = ", ";
}
return builder.toString();
}
System.out.println(concatenate(strings));
System.out.println(concatenate(friends));
// > Don't use '+' inside a call to `append()`, you already have a StringBuilder,
// so use append() instead
// ### Concatenation with String.join()
// If you have an array of strings or a collection of strings, `String.join`
// is the simplest way to concatenate the items with a separator
System.out.println(String.join(", ", strings));
// ### Concatenation with a StringJoiner
// If you don't have a list of strings by a list of objects, you can use the
// `StringJoiner` which let you specify a separator and is implemented
// using expandable buffer of strings (`StringJoiner.add` only accepts strings).
String concatenate(List<?> list) {
var joiner = new StringJoiner(", ");
list.forEach(item -> joiner.add(item.toString()));
return joiner.toString();
}
System.out.println(concatenate(strings));
System.out.println(concatenate(friends));
// ### Concatenation with a Stream
// If you use a `Stream` and the collector `joining`, it will use a `StringJoiner` internally.
import java.util.stream.Collectors;
System.out.println(strings.stream().collect(Collectors.joining(", ")));
System.out.println(friends.stream().map(Friend::toString).collect(Collectors.joining(", ")));