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 | package Torello.Java;
import Torello.Java.ParallelArrayException;
import java.util.stream.IntStream;
class StrArrToStrArr
{
static String replace(
final boolean ignoreCase,
final String s,
final String[] matchStrs,
final String[] replaceStrs
)
{
// Make sure these arrays are parallel, and if not throw ParallelArrayException
// If there are any 'null' values in these arrays, throw NullPointerException
ParallelArrayException.check
(matchStrs, "matchStrs", true, replaceStrs, "replaceStrs", true);
// Java Stream's shall keep records of where and which the matches occurred
IntStream.Builder whereB = IntStream.builder();
IntStream.Builder whichB = IntStream.builder();
int delta = 0;
// This part of the code finds the locations of all the matches in the input string.
// It does not build the new String, but rather, finds indexes first. This way a
// char[] array can be built, and then populated with the updated sub-strings.
TOP:
for (int i=0; i < s.length(); i++)
for (int j=0; j < matchStrs.length; j++)
if (s.regionMatches(ignoreCase, i, matchStrs[j], 0, matchStrs[j].length()))
{
// Save the "original String index" of WHERE the match occurred
whereB.accept(i);
// Save the "match index" of WHICH match has occurred
whichB.accept(j);
// Keep a record of the 'delta' - which is the change in size of the
// output/returned String
delta = delta - matchStrs[j].length() + replaceStrs[j].length();
// Make sure to advance the index-pointer, skip the most recent match
i += matchStrs[j].length() - 1;
continue TOP;
}
// List of indices into the input-String for WHERE matches occurred.
int[] whereArr = whereB.build().toArray();
// List of indices into the match-array for WHICH matches occurred.
int[] whichArr = whichB.build().toArray();
// The new "Char Array" which will be built into a String. The "change in size" was
// computed earlier
char[] cArr = new char[s.length() + delta];
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// If there were no matches, return the original string
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
if (whereArr.length == 0) return s;
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// "Pre-Loop Priming Update" or "Priming Read"
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
//
// This just copies the first non-matching sub-string portion to the cArr[]
s.getChars(0, whereArr[0], cArr, 0);
// These are the loop-control variables
int oldStrPos = whereArr[0];
int newStrPos = whereArr[0];
int i = 0;
while (i < whichArr.length)
{
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// Copy the next match from the "Replacement Strings Array"
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
String replaceStr = replaceStrs[whichArr[i]];
replaceStr.getChars(0, replaceStr.length(), cArr, newStrPos);
// Advance the pointers
newStrPos += replaceStr.length();
oldStrPos += matchStrs[whichArr[i]].length();
i++;
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
// Copy the next non-matching sub-string section from the "Old Input String"
// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
int end = (i < whichArr.length) ? whereArr[i] : s.length();
s.getChars(oldStrPos, end, cArr, newStrPos);
// Advance the pointers
newStrPos += (end - oldStrPos);
oldStrPos = end;
}
// Convert the character array into a String
return new String(cArr);
}
}
|