- 浏览: 66575 次
- 性别:
- 来自: 杭州
最新评论
-
westboy172887564:
好久之前的帖子了,不知道还会不会回复啊,有开发文档么?
迟到的开源 -
lieyan2024:
正在学习单例模式, 看了你的文章有收获,有不解.单例模式确实很 ...
架构、框架、模式之轻松掌握设计模式(单例模式) -
raoyutao:
DCS member.
关于Spring -
凤舞凰扬:
raoyutao 写道黄教授,今天在这上面突然发现了你,好欣喜 ...
关于Spring -
raoyutao:
黄教授,今天在这上面突然发现了你,好欣喜呢
关于Spring
前两天在网上无意看到一个关于使用java的正则表达式来进行通配符识别判断的实现。(http://blog.csdn.net/subchen/archive/2007/10/25/1843232.aspx)
看了一下,程序其实有蛮多问题的,甚至都无法通过编译以及测试。我将程序改了一下,并稍微优化了一下结构,如下:
private static final String PATTERN_LINE_START = "^" ; private static final String PATTERN_LINE_END = "$" ; private static final char[] META_CHARACTERS = { '$', '^', '[', ']', '(', ')', '{', '}', '|', '+', '.', '\\' }; /** * match function, support '*' and '?'. * The function is based on regex. * @param pattern * @param str * @return */ public static boolean wildcardMatch(String pattern, String str) { pattern = convertToRegexPattern(pattern); return Pattern.matches(pattern, str); } private static String convertToRegexPattern(String wildcardString) { String result = PATTERN_LINE_START ; char[] chars = wildcardString.toCharArray() ; for (char ch : chars) { if (Arrays.binarySearch(META_CHARACTERS, ch)>=0) { result += "\\" + ch ; continue ; } switch (ch) { case '*': result += ".*"; break; case '?': result += ".{0,1}"; break; default: result += ch; } } result += PATTERN_LINE_END ; return result; }
后来运行了一下,发现这样的效率并不高,原代码中不支持?,而实际中对于?的通配符匹配,尤其是在java类名,文件名的识别上应用并不多,于是,另外写了个快速的实现,不使用正则表达式。
public static boolean simpleWildcardMatch(String pattern, String str) { return wildcardMatch(pattern, str, "*"); } public static boolean wildcardMatch(String pattern, String str, String wildcard) { if (StringUtils.isEmpty(pattern) || StringUtils.isEmpty(str)) { return false; } final boolean startWith = pattern.startsWith(wildcard); final boolean endWith = pattern.endsWith(wildcard); String[] array = StringUtils.split(pattern, wildcard); int currentIndex = -1; int lastIndex = -1 ; switch (array.length) { case 0: return true ; case 1: currentIndex = str.indexOf(array[0]); if (startWith && endWith) { return currentIndex >= 0 ; } if (startWith) { return currentIndex + array[0].length() == str.length(); } if (endWith) { return currentIndex == 0 ; } return str.equals(pattern) ; default: for (String part : array) { currentIndex = str.indexOf(part); if (currentIndex > lastIndex) { lastIndex = currentIndex; continue; } return false; } return true; } }
为了验证这两个方法,测试类借用了一部分原文的测试例子:
public class RegexUtilsTest { /** * test '?' and '*' */ @Test public void testWildMatch2() { assertTrue(RegexUtils.wildcardMatch("1234?", "12345")); assertTrue(RegexUtils.wildcardMatch("1234?", "1234")); assertFalse(RegexUtils.wildcardMatch("1234?", "123456")); assertTrue(RegexUtils.wildcardMatch("abc*x?yz*", "abcxxxyz")); assertTrue(RegexUtils.wildcardMatch("abc*xxx?yz*", "abcxxxyz")); } @Test public void testWildMatch() { assertTrue(RegexUtils.wildcardMatch("*", "toto")); assertFalse(RegexUtils.wildcardMatch("toto.java", "tutu.java")); assertFalse(RegexUtils.wildcardMatch("12345", "1234")); assertFalse(RegexUtils.wildcardMatch("*f", "")); assertTrue(RegexUtils.wildcardMatch("***", "toto")); assertFalse(RegexUtils.wildcardMatch("*.java", "toto.")); assertFalse(RegexUtils.wildcardMatch("*.java", "toto.jav")); assertTrue(RegexUtils.wildcardMatch("*.java", "toto.java")); assertFalse(RegexUtils.wildcardMatch("abc*", "")); assertTrue(RegexUtils.wildcardMatch("a*c", "abbbbbccccc")); assertTrue(RegexUtils.wildcardMatch("abc*xyz", "abcxxxyz")); assertTrue(RegexUtils.wildcardMatch("*xyz", "abcxxxyz")); assertTrue(RegexUtils.wildcardMatch("abc**xyz", "abcxxxyz")); assertTrue(RegexUtils.wildcardMatch("abc**x", "abcxxx")); assertTrue(RegexUtils.wildcardMatch("*a*b*c**x", "aaabcxxx")); assertTrue(RegexUtils.wildcardMatch("abc*x*yz", "abcxxxyz")); assertTrue(RegexUtils.wildcardMatch("a*b*c*x*yf*z*", "aabbccxxxeeyffz")); assertFalse(RegexUtils.wildcardMatch("a*b*c*x*yf*zze", "aabbccxxxeeyffz")); assertTrue(RegexUtils.wildcardMatch("a*b*c*x*yf*z", "aabbccxxxeeyffz")); assertTrue(RegexUtils.wildcardMatch("a*b*c*x*yf*ze", "aabbccxxxeeyfze")); assertTrue(RegexUtils.wildcardMatch("*LogServerInterface*.java", "_LogServerInterfaceImpl.java")); assertTrue(RegexUtils.wildcardMatch("*Log*Impl.java", "_LogServerInterfaceImpl.java")); assertTrue(RegexUtils.wildcardMatch("abc*xyz", "abcxyxyz")); String str = this.getClass().getName() ; assertTrue(RegexUtils.wildcardMatch("com.oocllogistics.comp.*", str)); assertTrue(RegexUtils.wildcardMatch(RegexUtilsTest.class.getName(), str)); assertTrue(RegexUtils.wildcardMatch("*.RegexUtilsTest", str)); assertTrue(RegexUtils.wildcardMatch("*com.oocllogistics.comp.util.RegexUtilsTest", str)); assertTrue(RegexUtils.wildcardMatch("*.comp.*", str)); assertFalse(RegexUtils.wildcardMatch("comp.*", str)); assertFalse(RegexUtils.wildcardMatch("*.RegexUtils", str)); assertTrue(RegexUtils.wildcardMatch("com.*.comp.*", str)); assertTrue(RegexUtils.wildcardMatch("com.*.RegexUtilsTest", str)); assertTrue(RegexUtils.wildcardMatch("com.*.RegexUtilsTest*", str)); assertTrue(RegexUtils.wildcardMatch("*com.*.RegexUtilsTest", str)); assertTrue(RegexUtils.wildcardMatch("*com.*.*UtilsTest*", str)); assertTrue(RegexUtils.wildcardMatch("*com**UtilsTest*", str)); assertTrue(RegexUtils.wildcardMatch("**com**Utils**", str)); assertFalse(RegexUtils.wildcardMatch("com.", str)); } @Test public void tesstSimpleWildcardMatch() { assertTrue(RegexUtils.simpleWildcardMatch("*", "toto")); assertFalse(RegexUtils.simpleWildcardMatch("toto.java", "tutu.java")); assertFalse(RegexUtils.simpleWildcardMatch("12345", "1234")); assertFalse(RegexUtils.simpleWildcardMatch("*f", "")); assertTrue(RegexUtils.simpleWildcardMatch("***", "toto")); assertFalse(RegexUtils.simpleWildcardMatch("*.java", "toto.")); assertFalse(RegexUtils.simpleWildcardMatch("*.java", "toto.jav")); assertTrue(RegexUtils.simpleWildcardMatch("*.java", "toto.java")); assertFalse(RegexUtils.simpleWildcardMatch("abc*", "")); assertTrue(RegexUtils.simpleWildcardMatch("a*c", "abbbbbccccc")); assertTrue(RegexUtils.simpleWildcardMatch("abc*xyz", "abcxxxyz")); assertTrue(RegexUtils.simpleWildcardMatch("*xyz", "abcxxxyz")); assertTrue(RegexUtils.simpleWildcardMatch("abc**xyz", "abcxxxyz")); assertTrue(RegexUtils.simpleWildcardMatch("abc**x", "abcxxx")); assertTrue(RegexUtils.simpleWildcardMatch("*a*b*c**x", "aaabcxxx")); assertTrue(RegexUtils.simpleWildcardMatch("abc*x*yz", "abcxxxyz")); assertTrue(RegexUtils.simpleWildcardMatch("a*b*c*x*yf*z*", "aabbccxxxeeyffz")); assertFalse(RegexUtils.simpleWildcardMatch("a*b*c*x*yf*zze", "aabbccxxxeeyffz")); assertTrue(RegexUtils.simpleWildcardMatch("a*b*c*x*yf*z", "aabbccxxxeeyffz")); assertTrue(RegexUtils.simpleWildcardMatch("a*b*c*x*yf*ze", "aabbccxxxeeyfze")); assertTrue(RegexUtils.simpleWildcardMatch("*LogServerInterface*.java", "_LogServerInterfaceImpl.java")); assertTrue(RegexUtils.simpleWildcardMatch("*Log*Impl.java", "_LogServerInterfaceImpl.java")); assertTrue(RegexUtils.simpleWildcardMatch("abc*xyz", "abcxyxyz")); String str = this.getClass().getName() ; assertTrue(RegexUtils.simpleWildcardMatch("com.oocllogistics.comp.*", str)); assertTrue(RegexUtils.simpleWildcardMatch(RegexUtilsTest.class.getName(), str)); assertTrue(RegexUtils.simpleWildcardMatch("*.RegexUtilsTest", str)); assertTrue(RegexUtils.simpleWildcardMatch("*com.oocllogistics.comp.util.RegexUtilsTest", str)); assertTrue(RegexUtils.simpleWildcardMatch("*.comp.*", str)); assertFalse(RegexUtils.simpleWildcardMatch("comp.*", str)); assertFalse(RegexUtils.simpleWildcardMatch("*.RegexUtils", str)); assertTrue(RegexUtils.simpleWildcardMatch("com.*.comp.*", str)); assertTrue(RegexUtils.simpleWildcardMatch("com.*.RegexUtilsTest", str)); assertTrue(RegexUtils.simpleWildcardMatch("com.*.RegexUtilsTest*", str)); assertTrue(RegexUtils.simpleWildcardMatch("*com.*.RegexUtilsTest", str)); assertTrue(RegexUtils.simpleWildcardMatch("*com.*.*UtilsTest*", str)); assertTrue(RegexUtils.simpleWildcardMatch("*com**UtilsTest*", str)); assertTrue(RegexUtils.simpleWildcardMatch("**com**Utils**", str)); assertFalse(RegexUtils.simpleWildcardMatch("com.", str)); } public void performanceTestWildcardMatch() { int loop = 1000 ; long start = System.currentTimeMillis(); for (int i = 0; i < loop; i++) { testWildMatch(); } long end = System.currentTimeMillis(); System.out.println("Loop[1000] cost : " + (end - start) / 1000d + " seconds"); loop = 5000 ; start = System.currentTimeMillis(); for (int i = 0; i < loop; i++) { testWildMatch(); } end = System.currentTimeMillis(); System.out.println("Loop[5000] cost : " + (end - start) / 1000d + " seconds"); loop = 10000 ; start = System.currentTimeMillis(); for (int i = 0; i < loop; i++) { testWildMatch(); } end = System.currentTimeMillis(); System.out.println("Loop[10000] cost : " + (end - start) / 1000d + " seconds"); } public void performanceTestSimpleWildcardMatch() { int loop = 1000 ; long start = System.currentTimeMillis(); for (int i = 0; i < loop; i++) { tesstSimpleWildcardMatch(); } long end = System.currentTimeMillis(); // log.info("cost : "+(end - start)/1000d + " seconds"); System.out.println("Loop[1000] cost : " + (end - start) / 1000d + " seconds"); loop = 5000 ; start = System.currentTimeMillis(); for (int i = 0; i < loop; i++) { tesstSimpleWildcardMatch(); } end = System.currentTimeMillis(); System.out.println("Loop[5000] cost : " + (end - start) / 1000d + " seconds"); loop = 10000 ; start = System.currentTimeMillis(); for (int i = 0; i < loop; i++) { tesstSimpleWildcardMatch(); } end = System.currentTimeMillis(); System.out.println("Loop[10000] cost : " + (end - start) / 1000d + " seconds"); } @Test public void performanceTest() { System.out.println("------Test wildcardMatch---------"); performanceTestWildcardMatch(); System.out.println(); System.out.println("------Test simpleWildcardMatch---------"); performanceTestSimpleWildcardMatch(); } }
其中PerformanceTest方法分别对wildcardMatch喝simpleWildcardMatch进行了1000,5000,10000次重复运行Test Case比较,其中每个case包括38个匹配断言。下面是性能测试结果:
------Test wildcardMatch--------- Loop[1000] cost : 0.703 seconds Loop[5000] cost : 2.547 seconds Loop[10000] cost : 4.907 seconds ------Test simpleWildcardMatch--------- Loop[1000] cost : 0.094 seconds Loop[5000] cost : 0.25 seconds Loop[10000] cost : 0.484 seconds
我们可以看到,使用simpleWildCardMatch要比wildcardMatch方法快上一个数量级。 所以如果有朋友有兴趣,建议使用只支持*号的simpleWildcardMatch。(当然了,实际应用中,这种性能差别其实对application影响并不大)
如果有网友有兴趣,可以尝试优化,或者提供更多的测试。
相关推荐
signByIF.java 用if语句实现符号函数示例 triangleStar.java 输出一个由*组成的直角三角形 upperToLowCase.java 大写转换成小写 variableScopeExample.java 变量使用范围示例 第3章 示例描述:本章学习对象和类...
总的来说,这个Java实现的自然语言到cron表达式转换工具包,结合了NLP技术,旨在降低用户与系统交互的难度,提高用户体验,特别是在对话机器人和定时任务管理场景下。其背后涉及的理论和技术都是计算机科学和人工...
Java实现连接数据库及模糊查询功能示例 Java语言是当前最流行的程序设计语言之一,在数据处理和存储方面,Java提供了非常强大的支持。连接数据库是Java编程中非常重要的一步,通过连接数据库,Java程序可以对数据库...
在IT领域,字符串匹配是一项基础且重要的任务,广泛应用于文件搜索、文本处理、模式识别等多个场景。当涉及到“带通配符的字符串匹配”时,我们通常是指在字符串搜索过程中,使用特殊字符(如星号(*)或问号(?))来...
练习题可能要求你识别并实现这些模式。 解答这些练习题不仅有助于深化对Java的理解,还能提高编程技巧,为实际项目开发打下坚实的基础。通过深入研究和实践,你可以成为一名熟练的Java开发者。
path变量用于指定系统可以识别的命令所在的目录,比如Java编译器和运行时环境的路径。classpath变量用于指定Java类加载器在查找类时需要搜索的目录路径。具体来说,path变量需要在原有值的基础上添加JDK安装目录下的...
- **环境变量设置**: 设置JAVA_HOME、PATH等环境变量,确保系统能够识别Java命令行工具。 #### 2. Java基本语法 - **注释**: 单行注释(`//`)、多行注释(`/* */`)和文档注释(`/** */`)。 - **数据类型**: 基本...
C#到Java的转换工具通常会解析C#源代码,识别出语法规则,并按照Java的语法规则重构代码。这个过程中,工具需要处理的关键点包括但不限于: 1. 类和对象:C#中的类和接口转换为Java中的对应结构。 2. 方法:C#的...
习题可能要求识别和实现特定设计模式。 8. **反射机制**:Java的反射机制允许在运行时检查类的信息并动态调用方法。习题可能涉及获取类、字段和方法的信息,以及动态创建对象。 9. **泛型**:泛型提高了代码的类型...
Java SE Development Kit 8,简称JDK 8,是Oracle公司发布的Java开发工具包,用于构建和运行Java应用程序。...记得在安装后配置系统环境变量,确保PATH中包含JDK的bin目录,以便系统能够正确识别和执行Java命令。
1. **Java环境搭建**:首先,我们需要安装Java Development Kit (JDK),设置好环境变量,包括JAVA_HOME、PATH和CLASSPATH,确保系统能够正确识别和执行Java程序。 2. **Java语法基础**:Java是一种面向对象的语言,...
《Java编程思想》第四版详细阐述了泛型的概念、泛型类、泛型方法以及通配符的使用,使得读者能够编写更加安全、灵活的代码。 #### 集合框架 Java的集合框架是用于存储和操作数据的高效工具。本书深入讲解了集合...
集合框架是Java中处理数据的重要工具,包括List、Set、Map等接口及其实现类。题目可能会测试你对ArrayList、LinkedList、HashMap、HashSet等的区别和使用场景的理解,以及如何有效地操作和遍历集合。 多线程是Java...
- **ArrayList与LinkedList**:两种常用列表实现,理解它们的性能差异和使用场景。 - **HashMap与TreeMap**:哈希表和有序映射的区别,以及它们的遍历方式。 - **Set接口**:不包含重复元素的集合,如HashSet和...
- HashMap、HashSet、LinkedList等实现类:熟悉它们的内部实现和性能特点。 - 集合操作:如迭代、查找、排序、去重等。 - 泛型:理解泛型的用途和限制。 6. **多线程**: - 线程的创建与运行:掌握Thread类和...
2. **环境配置**:讲解如何安装Java Development Kit (JDK) 和设置环境变量,使计算机能够识别并运行Java程序。 3. **语法基础**:包括基本数据类型(如整型、浮点型、字符型、布尔型)、变量、常量的定义与使用,...
- 实现多个接口:理解Java中类如何通过接口实现多重继承。 7. **异常处理** - 异常分类:检查型异常和运行时异常的区别。 - try-catch-finally语句块:异常捕获和处理的基本结构。 8. **集合框架** - List、...
- **内存泄漏**:识别和避免可能导致内存浪费或程序崩溃的问题。 4. **多线程** - **线程创建**:通过Thread类和实现Runnable接口两种方式创建线程。 - **同步机制**:理解synchronized关键字,死锁、活锁、饥饿...
- **泛型**:使用泛型的好处,类型擦除的概念,以及通配符的运用。 5. **内存管理** - **JVM内存模型**:解释堆、栈、方法区、本地方法栈和程序计数器的作用。 - **垃圾回收**:理解垃圾回收的工作原理,GC ...