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); } } |