Java 正则表达式:比你想象的更强大

Java 正则表达式:比你想象的更强大
Java 正则表达式比你想象的更强大正则表达式是每一位开发者都应该掌握的技能但你知道吗在 Java 中正则表达式的处理能力远超过你的想象。今天我们不单纯讲解正则表达式的语法而是通过具体的编码实验对比不同正则表达式方案的性能和功能差异帮助你深刻理解 Java 正则表达式的强大之处。实验 1简单匹配假设你需要验证一个字符串是否包含特定的子字符串比如检查一个 URL 是否包含 .com。你会选择什么样的方法呢让我们看看两种方案的对比。方案 1使用String.contains()方法public class TestContains { public static void main(String[] args) { String url https://www.example.com; boolean contains url.contains(.com); // 简单的子字符串匹配 System.out.println(Contains .com? contains); } }方案 2使用正则表达式Pattern和Matcherimport java.util.regex.Pattern; import java.util.regex.Matcher; public class TestRegex { public static void main(String[] args) { String url https://www.example.com; Pattern pattern Pattern.compile(\\.com); // 使用正则表达式 Matcher matcher pattern.matcher(url); // 创建匹配器 boolean matches matcher.find(); // 查找匹配 System.out.println(Matches .com? matches); } }性能对比我们可以通过测量两种方法的执行时间来评估性能。使用System.currentTimeMillis()进行简单的时间测量public class PerformanceTest { public static void testContains() { String url https://www.example.com; long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { url.contains(.com); } long endTime System.currentTimeMillis(); System.out.println(Contains took (endTime - startTime) ms); } public static void testRegex() { String url https://www.example.com; Pattern pattern Pattern.compile(\\.com); long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { Matcher matcher pattern.matcher(url); matcher.find(); } long endTime System.currentTimeMillis(); System.out.println(Regex took (endTime - startTime) ms); } public static void main(String[] args) { testContains(); testRegex(); } }运行结果可能会显示String.contains()方法快于正则表达式。但在某些情况下正则表达式可以提供更灵活的匹配方案例如匹配多个模式。实验 2复杂的模式匹配假设你需要验证一个字符串是否符合某种复杂的模式比如一个有效的电子邮件地址。你会如何处理方案 1使用多个条件判断public class TestEmail1 { public static boolean isValidEmail(String email) { if (email null || email.isEmpty()) { return false; } if (!email.contains()) { return false; } if (email.indexOf() 0 || email.lastIndexOf() email.length() - 1) { return false; } if (!email.contains(.)) { return false; } if (email.indexOf(.) 0 || email.lastIndexOf(.) email.length() - 1) { return false; } if (email.lastIndexOf(.) email.lastIndexOf()) { return false; } return true; } public static void main(String[] args) { String email testexample.com; System.out.println(Is valid email? isValidEmail(email)); } }方案 2使用正则表达式import java.util.regex.Pattern; import java.util.regex.Matcher; public class TestEmail2 { private static final Pattern EMAIL_PATTERN Pattern.compile( ^[A-Za-z0-9_.-][A-Za-z0-9.-]\\.[A-Za-z]{2,}$ // 复杂的正则表达式 ); public static boolean isValidEmail(String email) { if (email null) { return false; } Matcher matcher EMAIL_PATTERN.matcher(email); return matcher.matches(); // 正则表达式匹配 } public static void main(String[] args) { String email testexample.com; System.out.println(Is valid email? isValidEmail(email)); } }性能对比同样是通过测量执行时间来评估性能public class EmailValidationPerformanceTest { public static void testEmail1() { String email testexample.com; long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { TestEmail1.isValidEmail(email); } long endTime System.currentTimeMillis(); System.out.println(Multiple conditions took (endTime - startTime) ms); } public static void testEmail2() { String email testexample.com; long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { TestEmail2.isValidEmail(email); } long endTime System.currentTimeMillis(); System.out.println(Regex took (endTime - startTime) ms); } public static void main(String[] args) { testEmail1(); testEmail2(); } }运行结果可能会显示正则表达式的性能略逊一筹但它的代码简洁性和可维护性远超多个条件判断的方法。实验 3替换操作假设你需要将一个字符串中的所有空格替换为下划线。你会如何实现方案 1使用String.replaceAll()方法public class TestReplaceAll { public static void main(String[] args) { String input Hello World This Is Java; String output input.replaceAll( , _); // 使用正则表达式替换空格 System.out.println(Output: output); } }方案 2使用StringBuilder手动替换public class TestStringBuilder { public static String replaceSpaces(String input) { StringBuilder sb new StringBuilder(); for (char c : input.toCharArray()) { if (c ) { sb.append(_); // 手动替换空格 } else { sb.append(c); } } return sb.toString(); } public static void main(String[] args) { String input Hello World This Is Java; String output replaceSpaces(input); System.out.println(Output: output); } }性能对比再次通过测量执行时间来评估性能public class ReplacePerformanceTest { public static void testReplaceAll() { String input Hello World This Is Java; long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { input.replaceAll( , _); } long endTime System.currentTimeMillis(); System.out.println(ReplaceAll took (endTime - startTime) ms); } public static void testStringBuilder() { String input Hello World This Is Java; long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { TestStringBuilder.replaceSpaces(input); } long endTime System.currentTimeMillis(); System.out.println(StringBuilder took (endTime - startTime) ms); } public static void main(String[] args) { testReplaceAll(); testStringBuilder(); } }结果可能会显示StringBuilder方法更快但在简单的替换操作中使用正则表达式可以大大简化代码。实验 4分组捕获假设你需要从一个字符串中提取特定的部分比如从一个 URL 中提取主机名和路径。你会如何处理方案 1手动解析public class TestManualParsing { public static String[] extractParts(String url) { int start url.indexOf(://) 3; int end url.indexOf(/, start); String host url.substring(start, end); // 提取主机名 String path url.substring(end); // 提取路径 return new String[]{host, path}; } public static void main(String[] args) { String url https://www.example.com/path/to/resource; String[] parts extractParts(url); System.out.println(Host: parts[0]); System.out.println(Path: parts[1]); } }方案 2使用正则表达式分组捕获import java.util.regex.Pattern; import java.util.regex.Matcher; public class TestRegexGroup { private static final Pattern URL_PATTERN Pattern.compile( https?://(.*?)/(.*) // 使用分组捕获 ); public static String[] extractParts(String url) { Matcher matcher URL_PATTERN.matcher(url); if (matcher.matches()) { String host matcher.group(1); // 提取主机名 String path matcher.group(2); // 提取路径 return new String[]{host, path}; } return null; } public static void main(String[] args) { String url https://www.example.com/path/to/resource; String[] parts extractParts(url); System.out.println(Host: parts[0]); System.out.println(Path: parts[1]); } }性能对比同样的通过测量执行时间来评估性能public class GroupCapturePerformanceTest { public static void testManualParsing() { String url https://www.example.com/path/to/resource; long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { TestManualParsing.extractParts(url); } long endTime System.currentTimeMillis(); System.out.println(Manual parsing took (endTime - startTime) ms); } public static void testRegexGroup() { String url https://www.example.com/path/to/resource; long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { TestRegexGroup.extractParts(url); } long endTime System.currentTimeMillis(); System.out.println(Regex group took (endTime - startTime) ms); } public static void main(String[] args) { testManualParsing(); testRegexGroup(); } }结果可能会显示手动解析更快但在处理复杂的字符串时正则表达式的分组捕获功能可以显著减少代码量和复杂性。实验 5编译优化Java 正则表达式的一个重要特性是可以编译正则表达式以提高性能。让我们看看编译前后的性能差异。方案 1未编译的正则表达式public class TestUncompiledRegex { public static void main(String[] args) { String input Hello World This Is Java; boolean matches input.matches(.*\\s.*); // 未编译的正则表达式 System.out.println(Matches? matches); } }方案 2编译后的正则表达式import java.util.regex.Pattern; public class TestCompiledRegex { private static final Pattern SPACE_PATTERN Pattern.compile(.*\\s.*); // 编译后的正则表达式 public static void main(String[] args) { String input Hello World This Is Java; boolean matches SPACE_PATTERN.matcher(input).matches(); // 使用编译后的正则表达式 System.out.println(Matches? matches); } }性能对比通过测量执行时间来评估编译优化的效果public class CompilationPerformanceTest { public static void testUncompiled() { String input Hello World This Is Java; long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { input.matches(.*\\s.*); } long endTime System.currentTimeMillis(); System.out.println(Uncompiled regex took (endTime - startTime) ms); } public static void testCompiled() { String input Hello World This Is Java; long startTime System.currentTimeMillis(); for (int i 0; i 1000000; i) { TestCompiledRegex.SPACE_PATTERN.matcher(input).matches(); } long endTime System.currentTimeMillis(); System.out.println(Compiled regex took (endTime - startTime) ms); } public static void main(String[] args) { testUncompiled(); testCompiled(); } }结果可能会显示编译后的正则表达式性能明显提升特别是在多次使用同一正则表达式时。写在最后通过上述实验我们可以看到 Java 正则表达式在不同场景下的表现和优势。虽然在某些简单的情况下传统的字符串方法可能会更快但在处理复杂的字符串匹配和替换时正则表达式的简洁性和灵活性使其成为不可或缺的工具。如果你对正则表达式的构建和测试有更多需求不妨试试 Hey Cron。这个网站提供了多种实用的工具包括正则表达式生成器可以帮助你快速构建和测试正则表达式提高开发效率。同时Hey Cron 还支持 Cron 表达式生成器、中英互译、JSON 格式化、Base64 编码解码、时间戳转换和 JWT 解析等功能是开发者日常工作中的一大助力。