Package Torello.Java

Class StrReplace


  • public class StrReplace
    extends java.lang.Object
    StrReplace - Documentation.

    This class allows for a bulk-replace of all instances of a particular list of String's (as sub-strings) to be quickly, and efficiently, replaced using either a parallel array, or a java.util.function.Function to retrieve the replacement characters or String's.

    NOTE: This class is in now way intended to replace the simplicity of using Regular-Expressions. Usually, when repacing text inside of String's, code that utilizes the java.util.regex.Pattern, and java.util.regex.Matcher is usally just fine. There are circumstances, which will be encountered where large numbers of substrings map directly to another set of substrings. In such cases, using RegEx can actually be a "prohibitor" to finding the solution - primarily because thinking through the logic of Reg-Ex does not lend itself to "maps." When all one has are hammers, everything looks like a nail. Reg-Ex does work for String-replacement operations in many cases, but not all.

    Static (Functional) API: The methods in this class are all (100%) defined with the Java Key-Word / Key-Concept 'static'. Furthermore, there is no way to obtain an instance of this class, because there are no public (nor private) constructors. Java's Spring-Boot, MVC feature is *not* utilized because it flies directly in the face of the light-weight data-classes philosophy. This has many advantages over the rather ornate Component Annotations (@Component, @Service, @AutoWired, etc... 'Java Beans') syntax:

    • The methods here use the key-word 'static' which means (by implication) that there is no internal-state. Without any 'internal state' there is no need for constructors in the first place! (This is often the complaint by MVC Programmers).
    • A 'Static' (Functional-Programming) API expects to use fewer data-classes, and light-weight data-classes, making it easier to understand and to program.
    • The Vectorized HTML data-model allows more user-control over HTML parse, search, update & scrape. Also, memory management, memory leakage, and the Java Garbage Collector ought to be intelligible through the 'reuse' of the standard JDK class Vector for storing HTML Web-Page data.

    The power that object-oriented programming extends to a user is (mostly) limited to data-representation. Thinking of "Services" as "Objects" (Spring-MVC, 'Java Beans') is somewhat 'over-applying' the Object Oriented Programming Model. Like most classes in the Java-HTML JAR Library, this class backtracks to a more C-Styled Functional Programming Model (no Objects) - by re-using (quite profusely) the key-word static with all of its methods, and by sticking to Java's well-understood class Vector

    Internal-State: A user may click on this class' source code (see link below) to view any and all internally defined fields class. A cursory inspection of the code would prove that this class has precisely zero internally defined global fields (Spaghetti). All variables used by the methods in this class are local fields only, and therefore this class ought to be though of as 'state-less'.



    • Method Summary

      All Methods Static Methods Concrete Methods 
      Modifier and Type Method
      static String r​(boolean ignoreCase, String s, char[] matchChars, String[] replaceStrs)
      static String r​(boolean ignoreCase, String s, char[] matchChars, IntCharFunction<String> replaceFunction)
      static String r​(boolean ignoreCase, String s, String[] matchStrs, char[] replaceChars)
      static String r​(boolean ignoreCase, String s, String[] matchStrs, String[] replaceStrs)
      static String r​(boolean ignoreCase, String s, String[] matchStrs, IntTFunction<String,​String> replaceFunction)
      static String r​(String s, boolean ignoreCase, String[] matchStrs, IntTFunction<String,​Character> replaceFunction)
      static String r​(String s, char[] matchChars, char prependChar)
      static String r​(String s, char[] matchChars, char[] replaceChars)
      static String r​(String s, char[] matchChars, String[] replaceStrs)
      static String r​(String s, char[] matchChars, IntCharFunction<String> replaceFunction)
      static String r​(String s, String[] matchStrs, char[] replaceChars)
      static String r​(String s, String[] matchStrs, String[] replaceStrs)
      static String r​(String s, String[] matchStrs, IntTFunction<String,​String> replaceFunction)
      static String r​(String s, IntTFunction<String,​Character> replaceFunction, String[] matchStrs)
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • r

        public static java.lang.String r​(java.lang.String s,
                                         java.lang.String[] matchStrs,
                                         java.lang.String[] replaceStrs)
        Convenience Method. Case-Sensitive. Invokes r(boolean, String, String[], String[])
        Code:
        Exact Method Body:
        1
         return r(false, s, matchStrs, replaceStrs);
        
      • r

        public static java.lang.String r​(boolean ignoreCase,
                                         java.lang.String s,
                                         java.lang.String[] matchStrs,
                                         java.lang.String[] replaceStrs)
        This shall replace each instance of the elements of parameter 'matchStrs' in input String 's' with the elements of parallel array 'replaceStrs'
        Parameters:
        ignoreCase - When this parameter is set to TRUE, then the comparisons that determine whether a match has occurred shall ignore the case of the characters involved.
        s - This may be any Java String.
        matchStrs - This is a String[] array that should hold some sub-strings of input parameter 's'. This method shall search 's' - left to right - for any instances of the list of 'matchStrs' and replace those sub-strings with whatever String is in the same array-index location (parallel-array) from input parameter 'replaceStrs'

        MULTIPLE-MATCH SCENARIOS: If there are substring's within parameter 'matchStrs' such that the loop-iterations of this method could select multiple, different String's as a substring match with the input parameter 's', then the loops will always replace the first match found with input String[] array parameter 'matchStrs'.

        Example:
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
         String[] matches         = { "Bell", "Belle", "Belleview" };
         String[] replacements    = { "Ring", "Flower", "Microsoft Corporate HQ" };
         String   theString       = "Microsoft Corporate Apartments are in Belleview, Washington";
        
         System.out.println(StrReplace.r(false, theString, matches, replacements));
        
         // Would print to terminal:
         // Microsoft Corporate Apartments are in Ringeview, Washington
         
         // This is because the point when the "Replace Loop" cursor reaches character 'B' in
         // 'Bellview', the first match it finds with parameter 'matches' is the String "Bell"
         // ... And because the 'replacements' parameter maps the word "Bell" to "Ring"
         
        
        replaceStrs - This is also an String[] array that should hold sub-strings. Every time a copy of any 'matchStr' is found within 's', the index of the sub-string match from 'matchStrs' shall be used to lookup the parallel 'replaceStr', and used to over-write or replace that sub-string inside 's'.

        PARALLEL ARRAY: This array should be considered parallel to input String[] array 'matchStrs'. It provides a replacement mapping. It is required to be the exact same length as array 'matchStrs', or an exception shall throw.
        Returns:
        This shall return a new-String where the replacements that were requested have been substituted.
        Throws:
        java.lang.NullPointerException - If any of the String's inside the String[] arrays contain null pointers.
        ParallelArrayException - If the length of array matchStrs does not equal the length of array replaceStrs, then this exception shall throw. This is because these arrays are intended to be parallel arrays, where the references in the second array are supposed to be used to replace sub-strings (in 's') from the first array.
        Code:
        Exact Method Body:
         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
         // 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 the matches occurred
         IntStream.Builder   originalStrPosB     = IntStream.builder();
         IntStream.Builder   arrayParamsIndexB   = 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
                     originalStrPosB.accept(i);
        
                     // Save the "match index" of WHICH match has occurred
                     arrayParamsIndexB.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 the right number of characters.
                     i += matchStrs[j].length() - 1;
                            
                     continue TOP;
                 }
        
         // List of indices into the input-String for WHERE matches occurred.
         int[]   posArr      = originalStrPosB.build().toArray();
        
         // List of indices into the match-array for WHICH matches occurred.
         int[]   indices     = arrayParamsIndexB.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];
        
         // These are some loop-control variables
         int     oldStrPos   = 0;
         int     newStrPos   = 0;
         int     index       = 0;
        
         /* DEBUG PRINTLN'S
             System.out.println(
                 "posArr.length: " + posArr.length +
                 "indices.length: " + indices.length
             );
             System.out.println("Old s.length(): " +  s.length() + ", cArr.length: " + cArr.length);
             System.out.print("posArr: ");
             for (int pos : posArr) System.out.print(pos + ", ");
             System.out.print("\nindices: ");
             for (int indexx : indices) System.out.print(indexx + ", ");
             System.out.println("\nsubstrings: ");
             for (int pos : posArr) System.out.print(s.substring(pos, pos + 8) + ", ");
             System.out.println();
         */
        
         // ***************************************************************
         // This will populate a new char array with the updated substrings
         // This is a "Pre-Loop Priming Update" or "Priming Read".  It just
         // copies the first non-matching sub-string portion to the cArr[]
         // ***************************************************************
         int end = (index < indices.length) ? posArr[index] : s.length();
        
         while (oldStrPos != end) cArr[newStrPos++] = s.charAt(oldStrPos++);
        
         while (index < indices.length)
         {
             // ********************************************************
             // Copy the next match from the "Replacement Strings Array"
             // ********************************************************
             String  replaceStr  = replaceStrs[indices[index]];
             int     len         = replaceStr.length();
        
             for (int i=0; i < len; i++) cArr[newStrPos++] = replaceStr.charAt(i);
        
             oldStrPos += matchStrs[indices[index]].length();
             index++;
        
             // *************************************************************************
             // Copy the next non-matching sub-string section from the "Old Input String"
             // *************************************************************************
             end = (index < indices.length) ? posArr[index] : s.length();
        
             while (oldStrPos < end) cArr[newStrPos++] = s.charAt(oldStrPos++);
         }
        
         // Convert the character array into a String
         return new String(cArr);
        
      • r

        public static java.lang.String r​
                    (java.lang.String s,
                     java.lang.String[] matchStrs,
                     IntTFunction<java.lang.String,​java.lang.String> replaceFunction)
        
        Convenience Method. Case-Sensitive. Invokes r(boolean, String, String[], IntTFunction)
        Code:
        Exact Method Body:
        1
         return r(false, s, matchStrs, replaceFunction);
        
      • r

        public static java.lang.String r​
                    (boolean ignoreCase,
                     java.lang.String s,
                     java.lang.String[] matchStrs,
                     IntTFunction<java.lang.String,​java.lang.String> replaceFunction)
        
        This shall replace each instance of the elements of parameter 'matchStrs' in input String 's' with the String-value returned by the 'replaceFunction' lambda-method / functional-interface.
        Parameters:
        ignoreCase - When this parameter is set to TRUE, then the comparisons that determine whether a match has occurred shall ignore the case of the characters involved.
        s - This may be any Java String.
        matchStrs - This is an String[] array that should hold some sub-strings of input parameter 's'. This method shall search 's' - left to right - for any instances of the list of 'matchStrs' and replace those sub-strings with whatever String is returned by the 'replaceFunction'.

        MULTIPLE-MATCH SCENARIOS: If there are substring's within parameter 'matchStrs' such that the loop-iterations of this method could select multiple, different String's as a substring match with the input parameter 's', then the loops will always replace the first match found with input String[] array parameter 'matchStrs'.

        Example:
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
         String[] matches         = { "Bell", "Belle", "Belleview" };
         String   theString       = "Microsoft Corporate Apartments are in Belleview, Washington";
        
         System.out.println
             (StrReplace.r(false, theString, matches, (int i, String s) -> s.toUpperCase()));
        
         // Would print to terminal:
         // Microsoft Corporate Apartments are in BELLeview, Washington
         
         // This is because the point when the "Replace Loop" cursor reaches character 'B' in
         // 'Bellview', the first match it finds with parameter 'matches' is the String "Bell"
         // ... And because the 'replaceFunction' parameter merely asks the match-String be
         //     converted to upper-case.
         
        
        replaceFunction - This shall receive any Java String and reply with a replace-String. This shall be used to replace any instances of that character found inside the input String.

        LOOK-AROUND: The replaceFunction parameter here include both the matched String, and the index to the first character-position of that match. This means that the function-pointer or lambda you provide here has the ability to 'look ahead' (or behind) into the input-String before returning a String-replacement.
        Returns:
        This shall return a new-String where the replacements that were requested have been substituted.
        Throws:
        java.lang.NullPointerException - If any of the String's inside the String[] arrays contain null pointers.
        Code:
        Exact Method Body:
         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
         // Loop simply checks for null pointers.
         for (int i=0; i < matchStrs.length; i++) 
             if (matchStrs[i] == null) throw new NullPointerException(
                 "The " + i + StringParse.ordinalIndicator(i) + " of array parameter " +
                 "'matchStrs' is null."
             );
        
         // Use a StringBuilder to build the return String.  It is precisely what it was
         // it was designed for.
         StringBuilder sb = new StringBuilder();
        
         int last = 0;
        
         // Main Loop: Builds a replacement StringBuilder.  Looks for matches between the input
         // String 's', and the matchStrs in array String[] matchStrs.
         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()))
                 {
                     // A match was founnd, so begin
                     String nonMatchStr  = s.substring(last, i);
                     String oldStr       = s.substring(i, i + matchStrs[j].length());
                     String newStr       = replaceFunction.apply(i, oldStr);
        
                     // Append them to the StringBuilder.
                     if (nonMatchStr.length() > 0) sb.append(nonMatchStr);
                     sb.append(newStr);
        
                     // Update the pointers
                     last    = i + oldStr.length();
                     i       = last - 1; // use -1 because of the loop-incrementer at top
        
                     continue TOP;
                 }
        
         if (last == 0) return s; // There were no matches, return original String.
        
         // This happens when there are remaining characters after the last match that occurred.
         // Same as the HTML Parser - trailing READ/PARSE.
         if (last < s.length()) sb.append(s.substring(last));
        
         return sb.toString();
        
      • r

        public static java.lang.String r​
                    (java.lang.String s,
                     IntTFunction<java.lang.String,​java.lang.Character> replaceFunction,
                     java.lang.String[] matchStrs)
        
        Convenience Method. Case-Sensitive. Invokes r(String, boolean, String[], IntTFunction)
        Code:
        Exact Method Body:
        1
         return r(s, false, matchStrs, replaceFunction);
        
      • r

        public static java.lang.String r​
                    (java.lang.String s,
                     boolean ignoreCase,
                     java.lang.String[] matchStrs,
                     IntTFunction<java.lang.String,​java.lang.Character> replaceFunction)
        
        This shall replace each instance of the elements of parameter 'matchStrs' in input String 's' with the char-value returned by the 'replaceFunction' lambda-method / functional-interface.

        Example:
        1
        2
        3
        4
        5
        6
        7
        8
        9
         String[] matches    = { "&Pi;", "&Rho;", "&Sigma;", "&Tau;", "&Upsilon;", "&Phi;" };
         String   theString  = "Greek: &Pi;, &Rho;, &Sigma;, &Tau;, &Upsilon;, &Phi;";
         
         System.out.println
             (StrReplace.r(theString, false, matches, (int i, String s) -> Escape.escHTMLToChar(s)));
        
         // Would print to terminal:
         // Greek: Π, Ρ, Σ, Τ, Υ, Φ 
         
        
        Parameters:
        s - This may be any Java String.
        ignoreCase - When this parameter is set to TRUE, then the comparisons that determine whether a match has occurred shall ignore the case of the characters involved.
        matchStrs - This is an String[] array that should hold some sub-strings of input parameter 's'. This method shall search 's' - left to right - for any instances of the list of 'matchStrs' and replace those sub-strings with whatever char is returned by the 'replaceFunction' for that given match-String;

        MULTIPLE-MATCH SCENARIOS: If there are multiple copies (either ignoring case, or not ignoring case), of an identical String put into String[] array parameter 'matchStrs', this method will not generate an exception (or anything like that) in such scenarios.

        It is important to note that when invoking the replaceFunction's method apply(String), the String that is provided to apply will be the exact substring found in the original-String.
        replaceFunction - This shall receive any Java String and reply with a replace-char. This shall be used to replace any instances of that character found inside the input String.

        LOOK-AROUND: The replaceFunction parameter here include both the matched String, and the index to the first character-position of that match. This means that the function-pointer or lambda you provide here has the ability to 'look ahead' (or behind) into the input-String before returning a char-replacement.
        Returns:
        This shall return a new-String where the replacements that were requested have been substituted.
        Throws:
        java.lang.NullPointerException - If any of the String's inside the String[] arrays contain null pointers.
        Code:
        Exact Method Body:
          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
         // Loop simply checks for null pointers.
         for (int i=0; i < matchStrs.length; i++) 
             if (matchStrs[i] == null) throw new NullPointerException(
                 "The " + i + StringParse.ordinalIndicator(i) + " of array parameter " +
                 "'matchStrs' is null."
             );
        
         // NOTE: This builder used to save the indices where matches are found.
         //
         // The IntStream that we are building will be "interleaved" in the sense that each integer
         // in an *EVEN* location in the output array shall represent the starting-index of a 
         // sub-string match, and the *ODD* integer (the one that immediately follows it) represents
         // the ending-index of a sub-string match.
         IntStream.Builder b = IntStream.builder();
        
         // This is used to keep track of the size-change of the output string
         int delta = 0;
        
         // Main Loop: Builds a replacement StringBuilder.  Looks for matches between the input
         // String 's', and the matchStrs in array String[] matchStrs.
         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()))
                 {
                     // SEE NOTE ABOVE: When a match is found, the starting-index of the 
                     // substring match is appended to the IntStream, then IMMEDIATELY AFTERWARDS
                     // the ending-index of the substring match is appended.
                     int len = matchStrs[j].length();
                     b.accept(i);
                     b.accept(i + len);
        
                     // The change in size of the output String is precisely the length of the
                     // match minus 1.  A substring is being replaced by a character.
                     delta += (len - 1);
        
                     // A Match was found, so skip to the next location.  Move past the match
                     // that was just identified.
                     i += (len -1);
        
                     continue TOP;
                 }
                
         // Keeps track of all the locations in the original string where matches occurred.
         int[] posArr = b.build().toArray();
        
         // If there were no matches, return the original String
         if (posArr.length == 0) return s;
        
         // The output string will be stored here.
         char[] cArr = new char[s.length() - delta];
        
         // These are the array indices of both arrays, and the original string
         int i           = 0;    // Match-String Location Pointer Array
         int originalPos = 0;    // Pointer to Input-String index
         int newPos      = 0;    // Pointer to Output Char-Array index
        
         // Iterate and replace the substrings.
         while (i < posArr.length)
         {
             if (originalPos == posArr[i])
             {
                 // Ask the "Replace Function" for the replacement character for the matched
                 // substring
                 //
                 // NOTE: Each *EVEN* location in the posArr contains a start-index, and the
                 //       *ODD* location immediately following contains an end-index.  These
                 //       start-end pair identify the substring matches that were found.
                 //
                 // NOW:  Grab that substring, and pass it to the parameter-provided (user
                 //       provided)  "replaceFunction" which informs this method what character
                 //       to use when replacing a substring
                 cArr[newPos++] = replaceFunction.apply(i, s.substring(posArr[i], posArr[i+1]));
        
                 // Advance the "pointers" (advance the array indices)
                 //
                 // The pointer to the "source array" (a.k.a. the "original array") should be
                 // advanced to the location of the end of the match we just found.  That end
                 // was pointed at by the start-end *PAIR* posArr[i] ... posArr[i+1].
                 //
                 // NOTE: the substring match is "exclusive of" the actual character
                 //       located at posArr[i+1].  Specifically, in the original string, there
                 //       was a sub-string match to replace with a single character that began
                 //       at original-string index/location posArr[i] and continuing to 
                 //       index/location (posArr[i+1]-1)
                 //
                 //       Java's java.lang.String.subtring(star, end) is *ALWAYS* exclusive of
                 //       the character located at 'end'
                
                 originalPos = posArr[i+1];
        
                 // Skip the "pair" (starting-index and ending-index).   Note that at the end
                 // of the loop, variable 'i' shall *ALWAYS* be an even-number.
                 i += 2;
             }
             else cArr[newPos++] = s.charAt(originalPos++);
         }
        
         // Just like in HTMLNode Parse, the trailing ("tail") of characters after the final
         // match in the String need to be appended to the output char[] array.  These are
         // "missed" or "skipped" by the above replacement loop.  (Similar to a "trailing read")
         while (newPos < cArr.length) cArr[newPos++] = s.charAt(originalPos++);
        
         // AGAIN: All of the replacements where done on a "char[] array".  Convert that array
         //        to an actual String, and return it to the user.
         return new String(cArr);
        
      • r

        public static java.lang.String r​(java.lang.String s,
                                         java.lang.String[] matchStrs,
                                         char[] replaceChars)
        Convenience Method. Case-Sensitive. Invokes r(boolean, String, String[], char[])
        Code:
        Exact Method Body:
        1
         return r(false, s, matchStrs, replaceChars);
        
      • r

        public static java.lang.String r​(boolean ignoreCase,
                                         java.lang.String s,
                                         java.lang.String[] matchStrs,
                                         char[] replaceChars)
        This shall replace each instance of the elements of parameter 'matchStrs' in input String 's' with the provided characters in parallel array 'replaceChars'.

        Example:
        1
        2
        3
        4
        5
        6
        7
        8
        9
         String[]  matches       = { "&Pi;", "&Rho;", "&Sigma;", "&Tau;", "&Upsilon;", "&Phi;" };
         char[]    replacements  = { 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ'  };
         String    theString     = "Greek Letters: &Pi;, &Rho;, &Sigma;, &Tau;, &Upsilon;, &Phi;";
         
         System.out.println(StrReplace.r(false, theString, matches, replacements);
        
         // Would print to terminal the following String:
         // Greek Letters: Π, Ρ, Σ, Τ, Υ, Φ 
         
        
        Parameters:
        s - This may be any Java String.
        ignoreCase - When this parameter is set to TRUE, then the comparisons that determine whether a match has occurred shall ignore the case of the characters involved.
        matchStrs - This is a String[] array that should hold some sub-strings of input parameter 's'. This method shall search 's' - left to right - for any instances of the list of 'matchStrs' and replace those sub-strings with whatever char is in the same array-index location (parallel-array) from input parameter 'replaceChars'.

        MULTIPLE-MATCH SCENARIOS: If there are substring's within parameter 'matchStrs' such that the loop-iterations of this method could select multiple, different String's as a substring match with the input parameter 's', then the loops will always replace the first match found with input String[] array parameter 'matchStrs'.
        replaceChars - This is also a char[] array. Every time a copy of any of the 'matchStrs' is found within 's', the index of the String match from 'matchStrs' shall be used to lookup the parallel 'replaceChar', and used to over-write or replace that character inside 's'.

        PARALLEL ARRAY: This array should be considered parallel to input char[] array 'matchStrs'. It provides a replacement mapping. It is required to be the exact same length as array 'matchChars', or an exception shall throw.
        Returns:
        This shall return a new-String where the replacements that were requested have been substituted.
        Throws:
        java.lang.NullPointerException - If any of the String's inside the String[] matchStrs are null pointers.
        ParallelArrayException - If the arrays matchStrs and replaceChars are not identical lengths. These arrays must be parallel
        Code:
        Exact Method Body:
          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
         // Check that these arrays are parallel, and if not, throw ParallelArrayException
         // If 'matchStr' has a null, throw NullPointerException
         ParallelArrayException.check
             (matchStrs, "matchStrs", true, replaceChars, "replaceChars");
        
         // The first stream is used to save the indices where matches are found.
         // The second stream is used to save WHICH MATCH has occurred, in order to retrieve the
         // replacement character.
         //
         // NOTE: This builder used to save the indices where matches are found.
         //
         // The IntStream that we are building will be "interleaved" in the sense that each integer
         // in an *EVEN* location in the output array shall represent the starting-index of a 
         // sub-string match, and the *ODD* integer (the one that immediately follows it) represents
         // the ending-index of a sub-string match.
         IntStream.Builder matchLocationsB   = IntStream.builder();
        
         // This is saving which match occurred
         IntStream.Builder matchPosB         = IntStream.builder();
        
         // This is used to keep track of the size-change of the output string
         int delta = 0;
        
         // Main Loop: Builds a replacement StringBuilder.  Looks for matches between the input
         // String 's', and the matchStrs in array String[] matchStrs.
         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()))
                 {
                     // SEE NOTE ABOVE: When a match is found, the starting-index of the 
                     // substring match is appended to the IntStream, then IMMEDIATELY AFTERWARDS
                     // the ending-index of the substring match is appended.
                     int len = matchStrs[j].length();
                     matchLocationsB.accept(i);
                     matchLocationsB.accept(i + len);
        
                     // The second IntStream shall store WHICH MATCH has occurred.  The match that
                     // occurred is identified by an array-index into the "replaceChars" char[] array
                     // that was provided by the user to this method through the parameter list at
                     // the top of this.
                     matchPosB.accept(j);
        
                     // The change in size of the output String is precisely the length of the
                     // match minus 1.  A substring is being replaced by a character.
                     delta += (len - 1);
        
                     // A Match was found, so skip to the next location.  Move past the match
                     // that was just identified.
                     i += (len -1);
                     continue TOP;
                 }
                
         // Keeps track of all the locations in the original string where matches occurred.
         int[] originalStrPosArr = matchLocationsB.build().toArray();
         int[] matchNumberPosArr = matchPosB.build().toArray();
        
         // If there were no matches, return the original String
         if (matchNumberPosArr.length == 0) return s;
        
         // The output string will be stored here.
         char[] cArr = new char[s.length() - delta];
        
         // These are the array indices of both arrays, and the original string
         int i           = 0;    // Index into Match-String Location Pointer Array 
         int originalPos = 0;    // Pointer / index into Input-String
         int newPos      = 0;    // Pointer / index into Output Char-Array
         int rArrPos     = 0;    // Pointer / index into Replace Characters Char-Array
        
         // Iterate and replace the substrings.
         while (i < originalStrPosArr.length)
         {
             if (originalPos == originalStrPosArr[i])
             {
                 // Retrieve the replacement character from the 'replaceChars' array.
                 // The *CORRECT INDEX* from the replacement-char array is the next location
                 // in the matchNumberPosArr... And *THIS INDEX* is called 'rArrPos'
                 // NOTE: Good Variable Names became uncompromisingly difficult here. 
                 cArr[newPos++] = replaceChars[matchNumberPosArr[rArrPos++]];
        
                 // Advance the "pointers" (advance the array indices)
                 //
                 // The pointer to the "source array" (a.k.a. the "original array") should be
                 // advanced to the location of the end of the match we just found.  That end
                 // was pointed at by the start-end *PAIR* posArr[i] ... posArr[i+1].
                 //
                 // NOTE: the substring match is "exclusive of" the actual character
                 //       located at posArr[i+1].  Specifically, in the original string, there
                 //       was a sub-string match to replace with a single character that began
                 //       at original-string index/location posArr[i] and continuing to 
                 //       index/location (posArr[i+1]-1)
                 //
                 //       Java's java.lang.String.subtring(star, end) is *ALWAYs* exclusive of
                 //       the character located at 'end'
                
                 originalPos = originalStrPosArr[i+1];
        
                 // Skip the "pair" (starting-index and ending-index).   Note that at the end
                 // of the loop, variable 'i' shall *ALWAYS* be an even-number.
                 i += 2;
             }
             else cArr[newPos++] = s.charAt(originalPos++);
         }
        
         // Just like in HTMLNode Parse, the trailing ("tail") of characters after the final
         // match in the String need to be append to the output char[] array.  These are "missed"
         // or "skipped" by the above replacement loop.  (Similar to a "trailing read")
         while (newPos < cArr.length) cArr[newPos++] = s.charAt(originalPos++);
        
         // Convert the character array into a String
         return new String(cArr);
        
      • r

        public static java.lang.String r​(java.lang.String s,
                                         char[] matchChars,
                                         java.lang.String[] replaceStrs)
        Convenience Method. Case-Sensitive. Invokes r(boolean, String, char[], String[])
        Code:
        Exact Method Body:
        1
         return r(false, s, matchChars, replaceStrs);
        
      • r

        public static java.lang.String r​(boolean ignoreCase,
                                         java.lang.String s,
                                         char[] matchChars,
                                         java.lang.String[] replaceStrs)
        This shall replace each instance of the characters of parameter 'matchStrs' in input String 's' with the String's of parallel array 'replaceStrs'.
        Parameters:
        ignoreCase - When this parameter is set to TRUE, then the comparisons that determine whether a match has occurred shall ignore the case of the characters involved.
        s - This may be any Java String.
        matchChars - This is a char[] array that should hold some set of characters which are expected to be contained within the input parameter 's'. This method shall search 's' - left to right - for any instances of the list of 'matchChars' and replace those characters with whatever String is in the same array-index location (parallel-array) from input parameter 'replaceStrs'

        MULTIPLE-MATCH SCENARIOS: If there are multiple copies of an the exact same character in input parameter 'matchChars', this should be considered an error-case. The code in this method does not actually go into that level of error checking, and as such, if parameter 'matchChars' attempts to map the same char to more than one replacement-String, the loop will simply use the first-mapping found in 'replaceStrs' that is found. No exceptions will throw when presented with this type of input.

        ALSO: If an upper-case and lower-case version of the exact same character is provided in char[] array parameter 'matchChars', and the boolean flag parameter 'ignoreCase' were set to TRUE, whichever of the two characters (upper-case or lower-case) that occurs first in array parameter 'matchChars' would be used to provide a replacement-String from array parameter 'replaceStrs'
        replaceStrs - This is a String[] array that should hold sub-strings. Every time a copy of any of the 'matchChars' is found within 's', the index of the character match from 'matchChars' shall be used to lookup the parallel 'replaceStr', and used to over-write or replace that character inside 's'.

        PARALLEL ARRAY: This array should be considered parallel to input char[] array 'matchChars'. It provides a replacement mapping. It is required to be the exact same length as array 'matchChars', or an exception shall throw.
        Returns:
        This shall return a new-String where the replacements that were requested have been substituted.
        Throws:
        java.lang.NullPointerException - If any of the String's inside String[] replaceStrs are null.
        ParallelArrayException - If the length of array matchChars does not equal the length of array replaceStrs, then this exception shall throw. This is because these arrays are intended to be parallel arrays, where the references in the second array are supposed to be used to replace sub-strings (in 's') from the first array.
        Code:
        Exact Method Body:
          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
         // Make sure these arrays are Parallel, and throw ParallelArrayException if not
         // If 'replaceStrs' contains null-values, throw NullPointerException
        
         ParallelArrayException.check
             (replaceStrs, "replaceStrs", true, matchChars, "matchChars");
        
         // If the case of the characters is being ignored, it is easier to just set them all
         // to lower-case right now.
         if (ignoreCase)
         {
             matchChars = matchChars.clone();
             for (int i=0; i < matchChars.length; i++)
                 matchChars[i] = Character.toLowerCase(matchChars[i]);
         }
            
         // Java Stream's shall keep records of *WHERE* and *WHICH* the matches occurs
         IntStream.Builder   originalStrPosB     = IntStream.builder();  // where
         IntStream.Builder   arrayParamsIndexB   = IntStream.builder();  // which
         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
                     originalStrPosB.accept(i);
        
                     // Save the "match index" of WHICH char-match has occurred
                     arrayParamsIndexB.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[]   posArr      = originalStrPosB.build().toArray();
        
         // List of indices into the match-array for WHICH matches occurred.
         int[]   indices     = arrayParamsIndexB.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 (posArr.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     index       = 0;
        
         // ***************************************************************
         // This will populate a new char array with the updated substrings
         // This is a "Pre-Loop Priming Update" or "PRIMING READ".  It just
         // copies the first non-matching sub-string portion to the cArr[]
         // ***************************************************************
                
         // OLD CODE: 
         // int end = (index < indices.length) ? posArr[index] : s.length();
         // while (oldStrPos != end) cArr[newStrPos++] = s.charAt(oldStrPos++);
         //
         // REPLACED WITH:
         if (posArr[0] > 0)
         {
             s.getChars(0, posArr[0], cArr, 0);
             newStrPos = posArr[0];
         }
        
        
         // *************************************
         // Iterate through each of the matches
         // *************************************
        
         while (index < indices.length)
         {
             /*
                 // VERY USEFUL DEBUGGING.  DO NOT DELETE.  THIS JUST PRINTS OUT THE OUTPUT-ARRAY
                 System.out.print("STAGE-1:\t");
                 for (char c : cArr) System.out.print((c == 0) ? "0, " : (c + ", "));
                 System.out.println();
             */
        
             // **********************************************************************************
             // Copy the next MATCHING char-substitute String from the "Replacement Strings Array"
             // **********************************************************************************
             String  replaceStr  = replaceStrs[indices[index]];
        
             /*
                 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);
        
                 // REPLACED WITH:
             */
             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.
             index++;
        
             // *************************************************************************
             // Copy the next NON-MATCHING PORTION sub-string from the "Old Input String"
             // *************************************************************************
        
             // OLD CODE: 
             // end = (index < indices.length) ? posArr[index] : s.length();
             // while (oldStrPos < end) cArr[newStrPos++] = s.charAt(oldStrPos++);
             //
             // REPLACED WITH:
        
             /*
                 // VERY USEFUL DEBUGGING.  DO NOT DELETE.  THIS JUST PRINTS OUT THE OUTPUT-ARRAY
                 System.out.print("STAGE-1:\t");
                 for (char c : cArr) System.out.print((c == 0) ? "0, " : (c + ", "));
                 System.out.println();
             */
        
             // Have We copied the entire string yet?
             if (oldStrPos < s.length())
             {
                 int endCopyPos = (index < indices.length) ? posArr[index] : s.length();
        
                 // System.out.println("THE-FACTS:\t" + oldStrPos + ", " + endCopyPos + ", " + newStrPos);
                 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);
                 oldStrPos = endCopyPos;  // Same as oldStrPos += (endCopyPos - oldStrPos) (Obviously!)
             }
         }
        
         // Convert the char[] array (cArr) into a String, and return it.
         return new String(cArr);
        
      • r

        public static java.lang.String r​
                    (java.lang.String s,
                     char[] matchChars,
                     IntCharFunction<java.lang.String> replaceFunction)
        
        Convenience Method. Case-Sensitive. Invokes r(boolean, String, char[], IntCharFunction)
        Code:
        Exact Method Body:
        1
         return r(false, s, matchChars, replaceFunction);
        
      • r

        public static java.lang.String r​
                    (boolean ignoreCase,
                     java.lang.String s,
                     char[] matchChars,
                     IntCharFunction<java.lang.String> replaceFunction)
        
        This shall replace each instance of the characters of parameter 'matchStrs' in input String 's' with the String-value returned by the 'replaceFunction' lambda-method / functional-interface.

        Example:
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
         // THIS EXAMPLE SHOWS HOW THIS METHOD CAN BE USED WITH REGULAR-EXPRESSION PROCESSING.
        
         // These are (some / most) of the characters that would need to be 'escaped' to use
         // them for the actual characters they represent inside of a Regular-Expression Pattern.
         final char[] CHARS_TO_ESCAPE = { '*', '.', '[', ']', '(', ')', '+', '|', '?', ':' };
        
         // This method invocation uses a lambda-expression that simply "prepends" a forward
         // slash to whatever character is being replaced with a String.  This will "escape" any
         // punctuation in the text that needs to "bypass" the Regular-Expression Engine - meaning
         // that these symbols, when found inside the text, should not be interpreted as commands
         // to RegEx, but rather as plain old brackets, parenthesis, periods, etc...
         text = StrReplace.r(text, CHARS_TO_ESCAPE, (int i, char c) -> "\\" + c);
         
        
        Parameters:
        ignoreCase - When this parameter is set to TRUE, then the comparisons that determine whether a match has occurred shall ignore the case of the characters involved.
        s - This may be any Java String.
        matchChars - This is a char[] array that should hold some set of characters which are expected to be contained within the input parameter 's'. This method shall search 's' - left to right - for any instances of the list of 'matchChars' and replace those characters with the results from input functional-interface parameter 'replaceFunction'.
        replaceFunction - This shall receive any Java char (or java.lang.Character), and reply with a replace-String. This shall be used to replace any instances of that character found inside the input String.

        LOOK-AROUND: The replaceFunction parameter here include both the matched char, and the index to the first character-position of that match. This means that the function-pointer or lambda you provide here has the ability to 'look ahead' (or behind) into the input-String before returning a String-replacement.
        Returns:
        This shall return a new-String where the replacements that were requested have been substituted.
        Code:
        Exact Method Body:
         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
         // Use a StringBuilder.  It is easier since the 'Replace Function' is going to be
         // *GENERATING* a new String each and every time there is a match.  This is essentially
         // what class StringBuilder was deigned for.
        
         StringBuilder sb = new StringBuilder();
        
         // If the case of the characters is being ignored, it is easier to just set them all
         // to lower-case right now.
         if (ignoreCase)
         {
             matchChars = matchChars.clone();
             for (int i=0; i < matchChars.length; i++)
                 matchChars[i] = Character.toLowerCase(matchChars[i]);
         }
        
         // IMPORTANT: This entire method is "The Easy Way"  Here, we are just reusing Java's
         //            StringBuilder class to build the String, piece-by-piece.  It is
         //            unknown whether this is less efficient than working with a char[] array
        
         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])
                 { 
                     sb.append(replaceFunction.apply(i, c));
                     continue TOP;
                 }
        
             sb.append(s.charAt(i));
         }
        
         return sb.toString();
        
      • r

        public static java.lang.String r​(java.lang.String s,
                                         char[] matchChars,
                                         char[] replaceChars)
        This shall replace any instance of any of the characters in array-parameter 'matchChars' with the character's provided in array-parameter 'replaceChars'.

        Example:
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
         // In this example, some of the Higher-Order UNICODE Punctuation Characters are replaced
         // With simple ASCII-Versions of similar punctuation symbols.  Occasionally, foreign
         // language news-sources will utilize these "Alternate Punctuation Symbols" in Asian
         // Language Texts.  Translating these documents necessitates converting these to simple
         // ASCII versions of the punctuation, for readability purposes.  (Since translated text
         // in English wouldn't need to use these symbols).
        
         char[] unicodeChars = { '〔', '〕', '〈', '〉', '《', '》', '「', '」', '〖', '〗', '【', '】' };
         char[] replacements = { '[',  ']',  '<', '>',  '\"', '\"', '[',  ']',  '{',  '}',  '<',  '>' };
         String theString    = "会议强调,制定出台《中国共产党中央委员会工作条例》";
         
         // Use this method to replace all instance of the mentioned UNICODE characters with 
         // standard punctuation.  Note, after replacing the punctuation, translation would occur
         // in the next step...
         System.out.println(StrReplace.r(theString, unicodeChars, replacements));
         
         // Prints:
         // 会议强调,制定出台"中国共产党中央委员会工作条例"
         // Which translates to:
         // The meeting emphasized the formulation and promulgation of the "Regulations on the Work
         // of the Central Committee of the Communist Party of China"
         
        
        Parameters:
        s - This may be any valid Java String. It is expected to contain at least some of the characters that are listed in parameter 'matchChars'.
        matchChars - This is a char[] array that should hold some set of characters which are expected to be contained within the input parameter 's'. This method shall search 's' - left to right - for any instances of the list of 'matchChars' and replace those characters with whatever char is in the same array-index location (parallel-array) from input parameter 'replaceChars'

        MULTIPLE-MATCH SCENARIOS: If there are multiple copies of an the exact same character in input parameter 'matchChars', this should be considered an error-case. The code in this method does not actually go into that level of error checking, and as such, if parameter 'matchChars' attempts to map the same char to more than one replacement-char, the loop will simply use the first-mapping found in 'replaceStrs' that is found. No exceptions will throw when presented with this type of input.
        replaceChars - This is also a char[] array. Every time a copy of any of the 'matchChars' is found within 's', the index of the character match from 'matchChars' shall be used to lookup the parallel 'replaceChar', and used to over-write or replace that character inside 's'.

        PARALLEL ARRAY: This array should be considered parallel to input char[] array 'matchChars'. It provides a replacement mapping. It is required to be the exact same length as array 'matchChars', or an exception shall throw.
        Returns:
        This shall return a copy of the input String, with all characters that matched the characters in 'matchChars', replaced by the characters in 'replaceChars'.
        Throws:
        ParallelArrayException - If the length of the 'matchChars' array is not equal to the length of the 'replaceChars' array.
        Code:
        Exact Method Body:
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
         // Make sure these arrays are of equal length
         ParallelArrayException.check(matchChars, "matchChars", replaceChars, "replaceChars");
        
         // The methods in this class all perform the replacements by first creating an
         // appropriately-sized output char[] array.  The last step of each of the methods is to
         // invoke the String constructor: new String(char[]) where a character array is converted
         // into a String.
         char[] cArr = s.toCharArray();
        
         TOP:
         for (int i=0; i < cArr.length; i++)
             for (int j=0; j < matchChars.length; j++)
                 if (cArr[i] == matchChars[j])
                 {
                     cArr[i] = replaceChars[j];  // If a match was found, just replace it
                     continue TOP;               // This method, really is THAT EASY.
                 }
        
         // Convert the character array into a String
         return new String(cArr);
        
      • r

        public static java.lang.String r​(java.lang.String s,
                                         char[] matchChars,
                                         char prependChar)
        This shall "prepend" a specified / chosen character before each instance of a list of characters in an input-String. LAY-SPEAK: If, for example, the 'prependChar' provided were the back-slash character '\', then this method would insert a back-slash before each and every one of the 'matchChars' that it found inside 's'.

        This method is used to escape certain characters for things like regular expressions and javascript. Note the examples below. These two methods are provided in class StringParse. These methods are StringParse.escStrForRegEx(String), StringParse.escStrForJavaScript(String).

        Example:
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
         protected static final char[] JS_ESCAPE_CHARS = { '\\', '/', '\n', '\"' };
         
         // When using Java to build Java-Script "Strings", escape these characters
         public static String escStrForJavaScript(String str)
         { return StrReplace.r(str, JS_ESCAPE_CHARS, '\\'); }
         
         // This is a list of "control characters" for regular-expressions.  These characters
         // need to be escaped if they are expected to be taken literally, rather than as a control
         // character in regex.
         protected static final char[] REGEX_ESCAPE_CHARS =
         { '\\', '/', '(', ')', '[', ']', '{', '}', '$', '^', '+', '*', '?', '-', '.' };
         
         public static String escStrForRegEx(String str)
         { return StrReplace.r(str, REGEX_ESCAPE_CHARS, '\\'); }
         
        
        Parameters:
        s - This may be any valid Java String. It is expected to contain at least some of the characters that are listed in parameter 'matchChars'.
        matchChars - This is a char[] array that should hold some set of characters which are expected to be contained within the input parameter 's'. This method shall search 's' - left to right - for any instances of the list of 'matchChars' and insert the character 'prependChar' directly before each match-character identified in String-parameter 's'.
        prependChar - This character will be inserted directly before each instance of matcChars-characters that are found within input String-parameter 's'
        Returns:
        This shall return a new String with the 'prependChar' before each instance of one of the 'matchChars' identified in the original String 's'.
        Code:
        Exact Method Body:
         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
         // Need a temporary 'count' variable
         int count   = 0;
        
         // Improve the loop counter efficiency, use a 'len' instead of s.length()
         int len     = s.length();
        
         // Use a Java Stream to save the locations of the matches
         IntStream.Builder b = IntStream.builder();
        
         // Count how many escape-characters are in the input-string
         TOP:
         for (int i=0; i < len; i++)
         {
             char c = s.charAt(i);
        
             // This checks if the character is a match with any of the match-characters in
             // the input array.
             for (char matchChar : matchChars)
                 if (matchChar == c)
                 {
                     b.accept(i);
                     continue TOP;
                 }
         }
        
         // Build the java stream, and turn it into an index-pointer array (int array of
         // array indices)
         int[] posArr = b.build().toArray();
            
         // No matches, return original string.
         if (posArr.length == 0) return s;
        
         // The 'escaped string' will be longer than the original String by
         // 'posArr.length' characters.  Use a character array to build this string
         char[] retArr = new char[len + posArr.length];
        
         // There are now three different indices to keep up with - when doing this replace.
         // The input-string index.  The index of the "Match Locations Array" (posArr), and the
         // index into the returned String - which, for now, is represented as a char[] array.
         int     inputPos  = 0;
         int     outputPos = 0;
         int     posArrPos = 0;
        
         while (inputPos < len)
         {
             // The next character in the input string
             char c = s.charAt(inputPos);
        
             // Was this one of the matches - as computed in the earlier loop?
             if (inputPos == posArr[posArrPos])
             {
                 // if "YES", then insert the prependChar, AND the original-string-char
                 retArr[outputPos++] = prependChar;
                 retArr[outputPos++] = c;
        
                 // Here, increment the "Match Locations Array" index-location too.
                 // (We have just "used up" one of the match-locations.
                 posArrPos++;
             }
             else
                 // if "NO", then just insert the original-string-char
                 retArr[outputPos++] = c;
        
             // Only at the end should we increment the input-string index-location.
             inputPos++;
         }
        
         // Convert the char array that was built into a String, and return it.
         return String.valueOf(retArr);