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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | package Torello.Java; import Torello.Java.ParallelArrayException; import java.util.stream.IntStream; class CharArrToStrArr { static String replace( final boolean ignoreCase, final String s, final char[] matchCharsInput, final String[] replaceStrs ) { // Make sure these arrays are Parallel, and throw ParallelArrayException if not // If 'replaceStrs' contains null-values, throw NullPointerException ParallelArrayException.check (replaceStrs, "replaceStrs", true, matchCharsInput, "matchChars"); // If the case of the characters is being ignored, it is easier to just set them all // to lower-case right now. final char[] matchChars; if (ignoreCase) { matchChars = new char[matchCharsInput.length]; // matchCharsInput.clone(); for (int i=0; i < matchChars.length; i++) matchChars[i] = Character.toLowerCase(matchCharsInput[i]); } else matchChars = matchCharsInput; // Java Stream's shall keep records of *WHERE* and *WHICH* the matches occurs IntStream.Builder whereB = IntStream.builder(); IntStream.Builder whichB = IntStream.builder(); int delta = 0; // string length change // 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++) { char c = ignoreCase ? Character.toLowerCase(s.charAt(i)) : s.charAt(i); for (int j=0; j < matchChars.length; j++) if (c == matchChars[j]) { // Save the "original String index" of WHERE the match occurred whereB.accept(i); // Save the "match index" of WHICH char-match has occurred whichB.accept(j); // Keep a record of the 'delta' - and this is the size of the string to insert. delta += replaceStrs[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(); // IMPORTANT: If no matches in input char[] array 'matchChars' were found or identified // inside the input-string, return the original String immediately, with no // changes! if (whereArr.length == 0) return s; // 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]; // These are some loop-control variables int oldStrPos = 0; int newStrPos = 0; int matchNum = 0; // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // "Pre-Loop Priming Update" or "PRIMING READ" - populates char array with replace-strings // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // copies the first non-matching sub-string portion to the cArr[] if (whereArr[0] > 0) { s.getChars(0, whereArr[0], cArr, 0); // Advance the pointers newStrPos = oldStrPos = whereArr[0]; } // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // Iterate through each of the matches // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** while (matchNum < whichArr.length) { // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // Copy the next MATCHING char-substitute String from the "Replacement Strings Array" // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** String replaceStr = replaceStrs[whichArr[matchNum]]; /* FROM: Java's JDK Documentation for java.lang.String public void getChars( int srcBegin, int srcEnd, char[] dst, int dstBegin ) Copies characters from this string into the destination character array. Parameters: srcBegin - index of the first character in the string to copy. srcEnd - index after the last character in the string to copy. dst - the destination array. dstBegin - the start offset in the destination array. // OLD CODE: int len = replaceStr.length(); for (int i=0; i < len; i++) cArr[newStrPos++] = replaceStr.charAt(i); */ replaceStr.getChars(0, replaceStr.length(), cArr, newStrPos); // In the new (output) string (currently a char[]), we have added "len" characters newStrPos += replaceStr.length(); // Since we are replacing a *SINGLE* character with a new (replacement) String, // the pointer to the source / old string is advanced by *ONLY* one. oldStrPos++; // This "index" is pointing to an array that is holding the match information. // Essentially, here, we are just moving on to the next match. Therefore // increment by only 1. matchNum++; // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // Copy the next NON-MATCHING PORTION sub-string from the "Old Input String" // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // Have We copied the entire string yet? if (oldStrPos < s.length()) { int endCopyPos = (matchNum < whichArr.length) ? whereArr[matchNum] : s.length(); s.getChars(oldStrPos, endCopyPos, cArr, newStrPos); // We have just copied (end - oldStrPos) characters to the new array, from the // old array. Advance the newStrPos by this many characters. newStrPos += (endCopyPos - oldStrPos); // Advance the oldStr by the same number of character. The line of code below // will be identical to this line of code: oldStrpos += (endCopyPos - oldStrPos); // Same as oldStrPos += (endCopyPos - oldStrPos) (Obviously!) oldStrPos = endCopyPos; } } // Convert the char[] array (cArr) into a String, and return it. return new String(cArr); } } |