More excellent articles.

“Microservices are not all, just a subset of a specific domain”

Selection and process should be careful, otherwise it will be out of control.

Out of all the monitoring components, there’s always one for you

What are we Developing with Netty?

This is probably the most pertinent Redis specification

Portrait of a Programmer: A Decade of Ups and Downs

Most useful series:

The Most Common Set of “Vim” Techniques for Linux Production

The most Common set of “Sed” Techniques for Linux Production

The Most Common Set of “AWK” Tips for Linux Production

If you agree with this knowledge, welcome to follow the wechat public account Xiaojie Taste

ID: xjjdog


I usually don’t care much about the implementation of the code, because my development language is very messy and tends to be the simplest and most generic way to solve the problem. Today I accidentally saw a friend in the group posted the following Java code, I feel very limited and ignorant:

String str1 = "createTime";
String str2 = "createTimeAt";
String regex = "([A-Z])+";

System.out.println(str1.replaceAll(regex, "_The $1").toLowerCase());
System.out.println(str2.replaceAll(regex, "_The $1").toLowerCase());

//result
//create_time
//create_time_at
Copy the code

As you can see from the output, the function of this code is to replace the camel named string with the underlined split. This function is relatively simple, but it is his code that attracts me.

"createTime".replaceAll("([A-Z]+)"."_The $1")
Copy the code

This line of code is as simple as calling the replaceAll method of the String class. The method takes the regular expression as its first argument and the new value to be replaced with as its second argument.

To my surprise, the second argument to replaceAll in his code, which was called replacement in the JDK documentation, was _$1. What the hell is this? And support for things like placeholders? I never knew.

To explore problems

Since I studied regular expressions earlier, by looking at the first argument ([a-z]+) to replaceAll, I assumed that this was A grouping of regular expressions, corresponding to the java.util.regex.matcher class’s group() method in JDK.

In Linux Sed, some replacements are made with &, which should be the same.

Take a look at how the String.replaceAll method is implemented. JDK:

public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
Copy the code

It uses Matcher at the bottom, but with Matcher’s own replaceAll method. If you look at its documentation, the argument to this method is a ghost, see the implementation code below.

public String replaceAll(String replacement) {
        reset();
        boolean result = find();
        if (result) {
            StringBuilder sb = new StringBuilder();
            do {
                appendReplacement(sb, replacement);
                result = find();
            } while (result);
            appendTail(sb);
            return sb.toString();
        }
        return text.toString();
    }
Copy the code

The key part of the documentation is the appendReplacement method, and then you can see the detailed description of the documentation.

It is clear that the replacement parameter of this method can be used to refer to the grouping obtained by Matcher through the regular matching through $character, which supports name and number. The corresponding methods here are group(name) and group(int) of the Matcher class.

conclusion

1. The replaceAll method of String is actually implemented through the replaceAll() method of the java.util.regex.matcher class. 2. The replaceAll method of the java.util.regex.Matcher class again implements the replacement logic by calling the appendReplacement method 3. The replacement parameter to the appendReplacement method of the Matcher class supports a $sign to refer to the Matcher matched grouping

The following line of code is a best practice for grouping using Matcher classes.

String data = "Ha ha ha, xjjdog's mobile number is :12345678901, will you call me?"; Matcher Matcher = pattern.compile (".*(my mobile number is :([0-9]{11}))").matcher(data);
while (matcher.find()) {
    System.out.println("G0:" + matcher.group(0));
    System.out.println("G1:" + matcher.group(1));
    System.out.println("G2:"+ matcher.group(2)); } //result //G0: hahaha, xjjdog's mobile phone number is :12345678901 //G1: Xjjdog's mobile phone number is :12345678901 //G2:12345678901Copy the code

Group (0) represents the entire string group(1) represents the first match, as in the above example (my cell phone number is :([0-9]{11})) part group(2) represents the second match, as in the above example ([0-9]{11}) part

Use groups can be used to extract the target string value in the string, very easy to use!

A few examples

Here are a few examples that you can relate to by analogy.

Name the hump by underlining

public static String camelToUnderline(String camelName) {
return camelName.replaceAll("([A-Z]+)"."_The $1").toLowerCase();
}
Copy the code

Underline to hump

This one is a little trickier, written by the copycat matcher. replaceAll method.

public static String underlineToCamel(String underlineName) {
        Matcher matcher = Pattern.compile("(_[a-z]{1})").matcher(underlineName);
        StringBuffer result = new StringBuffer();
        while (matcher.find()) {
            String replacement = matcher.group(1);
            matcher.appendReplacement(result, replacement.replace("_"."").toUpperCase());
        }
        matcher.appendTail(result);
        return result.toString();
}
Copy the code

In addition, Mybatis Generator plug-in also provides the similar method in the source of (JavaBeansUtil. GetCamelCaseString), here to do the simple changes

 public static String getCamelCaseString(String inputString) {
        StringBuilder sb = new StringBuilder();
        boolean nextUpperCase = false;
        for (int i = 0; i < inputString.length(); i++) {
            char c = inputString.charAt(i);
            switch (c) {
                case '_':
                case The '-':
                case The '@':
                case '$':
                case The '#':
                case ' ':
                case '/':
                case '&':
                    if (sb.length() > 0) {
                        nextUpperCase = true;
                    }
                    break;
                default:
                    if (nextUpperCase) {
                        sb.append(Character.toUpperCase(c));
                        nextUpperCase = false;
                    } else {
                        sb.append(Character.toLowerCase(c));
                    }
                    break; }}return sb.toString();
    }
Copy the code

The speed is significantly faster without the involvement of complex regex.

End

Looking at some good open source code, you can actually learn some useful tips. It’s much more efficient than having to reinvent the wheel yourself. Time should be spent on knives, but not cutting tofu.