-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStringConcatenation.java
More file actions
156 lines (138 loc) · 6.24 KB
/
Copy pathStringConcatenation.java
File metadata and controls
156 lines (138 loc) · 6.24 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package Phase2_MethodsArraysStrings.Strings;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
/**
* String Concatenation
* --------------------
* "Concatenation" means joining two or more Strings end-to-end. Java offers
* several mechanisms:
* <p>
*
* 1. The '+' operator "Hello, " + name
* 2. String.concat(other) "Hello, ".concat(name)
* 3. StringBuilder / StringBuffer use when looping
* 4. String.join(delim, parts...) Java 8+
* 5. java.util.StringJoiner Java 8+, with prefix/suffix
* 6. Stream.collect(Collectors.joining(...)) Java 8+
* 7. String.format / String.formatted printf-style composition
* 8. Text blocks Java 15+, multi-line literals
* <p>
*
* Behind the scenes
* -----------------
* Each `+` between String operands is compiled (since Java 9) into a
* `makeConcatWithConstants` invoke-dynamic call that the JVM optimises at
* runtime. For most simple expressions like `"x=" + x` you do NOT need to
* reach for StringBuilder yourself - the compiler does the right thing.
* <p>
*
* The big EXCEPTION is concatenation INSIDE A LOOP:
* <p>
*
* String s = "";
* for (int i = 0; i < N; i++) s += part(i); // O(N^2) - BAD
* <p>
*
* StringBuilder sb = new StringBuilder();
* for (int i = 0; i < N; i++) sb.append(part(i)); // O(N) - GOOD
* String s = sb.toString();
* <p>
*
* Each `+=` allocates and copies the whole prefix again because Strings are
* immutable.
* <p>
*
* Type Coercion - the '+' Trap
* ----------------------------
* "Sum = " + 1 + 2 == "Sum = 12" (left-to-right concatenation)
* "Sum = " + (1 + 2) == "Sum = 3" (parens force int addition)
* <p>
*
* Performance Demo
* ----------------
* main() benchmarks loop-concat vs StringBuilder so you can see the
* difference in milliseconds.
*/
public class StringConcatenation {
public static void main(String[] args) {
// ============================================================
// 1. + operator - the everyday case
// ============================================================
String name = "Deepak";
int age = 25;
String greeting = "Hello " + name + ", you are " + age + " years old.";
System.out.println(greeting);
// ============================================================
// 2. concat() - same effect as +, but only for two Strings, never null
// ============================================================
String a = "Hello, ".concat("World");
System.out.println(a);
// ============================================================
// 3. The '+' trap: left-to-right evaluation
// ============================================================
System.out.println("Sum = " + 1 + 2); // "Sum = 12" (string + 1 -> string, + 2 -> string)
System.out.println("Sum = " + (1 + 2)); // "Sum = 3"
// ============================================================
// 4. String.join (Java 8+) - joins many parts with a delimiter
// ============================================================
String csv = String.join(",", "alpha", "beta", "gamma");
System.out.println("join("+","+",...) = " + csv);
List<String> parts = List.of("alpha", "beta", "gamma");
System.out.println("join(list) = " + String.join(",", parts));
// ============================================================
// 5. StringJoiner - delimiter + optional prefix and suffix
// ============================================================
StringJoiner sj = new StringJoiner(", ", "[", "]");
sj.add("apple");
sj.add("banana");
sj.add("cherry");
System.out.println("StringJoiner = " + sj); // [apple, banana, cherry]
// ============================================================
// 6. Collectors.joining - the streamy way
// ============================================================
String sj2 = parts.stream()
.map(String::toUpperCase)
.collect(Collectors.joining(" | ", "<", ">"));
System.out.println("Collectors.join = " + sj2);
// ============================================================
// 7. String.format / formatted (Java 15+) - printf-style
// ============================================================
String row = String.format("%-10s %5d %6.2f", name, age, 1.75);
System.out.println("format = " + row);
String row2 = "Name=%s, Age=%d".formatted(name, age); // Java 15+
System.out.println("formatted = " + row2);
// ============================================================
// 8. Performance - loop-+ vs StringBuilder
// ============================================================
final int N = 50_000;
long t1 = System.nanoTime();
String slow = "";
for (int i = 0; i < N; i++) slow += "x";
long slowMs = (System.nanoTime() - t1) / 1_000_000;
long t2 = System.nanoTime();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < N; i++) sb.append('x');
String fast = sb.toString();
long fastMs = (System.nanoTime() - t2) / 1_000_000;
System.out.println();
System.out.println("N=" + N);
System.out.println("loop with += : " + slowMs + " ms length=" + slow.length());
System.out.println("StringBuilder : " + fastMs + " ms length=" + fast.length());
// SAMPLE OUTPUT (timings vary)
// Hello Deepak, you are 25 years old.
// Hello, World
// Sum = 12
// Sum = 3
// join(,,...) = alpha,beta,gamma
// join(list) = alpha,beta,gamma
// StringJoiner = [apple, banana, cherry]
// Collectors.join = <ALPHA | BETA | GAMMA>
// format = Deepak 25 1.75
// formatted = Name=Deepak, Age=25
//
// N=50000
// loop with += : 450 ms length=50000
// StringBuilder : 2 ms length=50000
}
}