java比较两个模式对象
有没有比较两个java比较两个模式对象,java,regex,Java,Regex,有没有比较两个模式对象的简单方法 我有一个模式,它使用regex“/”编译以检查代码中的注释 因为有几个正则表达式可以描述注释,所以我想找到一种方法来区分它们 怎样才能做到呢?模式类不实现等于方法。模式不实现,但字符串实现。为什么不比较编译模式的正则表达式呢?也许我不完全理解这个问题。但正如您在下面的示例中所看到的,每个java对象都有一个默认的java.lang.Object.equals(Object)方法。此方法比较对对象的引用,即使用=运算符 package test; import
模式对象的简单方法
我有一个模式
,它使用regex“/”
编译以检查代码中的注释
因为有几个正则表达式可以描述注释,所以我想找到一种方法来区分它们
怎样才能做到呢?模式
类不实现等于
方法。模式
不实现,但字符串
实现。为什么不比较编译模式的正则表达式呢?也许我不完全理解这个问题。但正如您在下面的示例中所看到的,每个java对象都有一个默认的java.lang.Object.equals(Object)
方法。此方法比较对对象的引用,即使用=
运算符
package test;
import java.util.regex.Pattern;
public class Main {
private static final Pattern P1 = Pattern.compile("//.*");
private static final Pattern P2 = Pattern.compile("//.*");
public static void main(String[] args) {
System.out.println(P1.equals(P1));
System.out.println(P1.equals(P2));
System.out.println(P1.pattern().equals(P1.pattern()));
System.out.println(P1.pattern().equals(P2.pattern()));
}
}
产出:
true
false
true
true
您可以比较已生成模式的字符串表示形式:
Pattern p1 = getPattern1();
Pattern p2 = getPattern2();
if (p1.pattern().equals(p2.pattern())){
// your code here
}
您可以通过比较调用Pattern()
或toString
的结果来比较Pattern
对象,但这并不是您想要的(如果我正确理解了您的问题)。具体来说,这将比较传递给模式.compile(…)
工厂方法的字符串。但是,这不考虑单独传递给模式字符串的标志
没有简单的方法来测试两个不相同的正则表达式是否相等。例如,“+”
和“.*”
表示等价的正则表达式,但使用模式
API无法直接确定这一点
我不知道这个问题在理论上是否可以解决。。。在一般情况下。评论:
正则表达式等价性没有有限的公理化,因此简单的回答是“正则表达式本身的树变换无法实现这一点”。但是,可以比较两个自动机的语言(测试它们的相等性),这样就可以计算两个正则表达式是否相等。请注意,我指的是“真正的”正则表达式,没有诸如对捕获组的反向引用之类的扩展,它们脱离了rational语言的领域,即自动机的领域
我还想对接受的答案发表评论。作者提供了一些代码,他声称这些代码表明模式的equals
方法继承自对象。事实上,他看到的结果与。。。但它并没有表现出来
了解情况是否属实的正确方法是查看javadoc。。。其中,等于
方法列在继承方法列表中。这是确定的
那么,为什么这个示例没有显示作者所说的内容呢
两种方法的行为方式可能相同,但实现方式可能不同。如果我们将模式
类视为一个黑匣子,那么我们无法证明这没有发生。(或者至少……在不使用反射的情况下。)
作者只在一个平台上运行过这个。其他平台的行为可能会有所不同
关于第二点,我记得在模式
(在Java 1.4中)的早期实现中,模式.compile(…)
方法保留了最近编译的模式对象1的缓存。如果编译了两次特定的模式字符串,第二次可能会得到与第一次返回的相同的对象。这将导致测试代码输出:
true
true
true
true
但这说明了什么?它是否显示模式
覆盖对象。等于
?不
这里的教训是,您应该主要通过查看javadocs了解Java库方法的行为:
- 如果你写了一个“黑盒子”测试,你很容易得出错误的结论。。。或者至少,并非所有平台的结论都是正确的
- 如果您的结论基于“阅读代码”,那么您就有可能得出对其他平台无效的结论
1-即使我的记忆不正确,这样的实现也会与Pattern.compile(…)
方法的javadocs保持一致。他们并没有说每个compile
调用都会返回一个新的Pattern
对象。由于神秘的原因,Pattern对象没有实现equals()。例如,此简单单元测试将失败:
@Test
public void testPatternEquals() {
Pattern p1 = Pattern.compile("test");
Pattern p2 = Pattern.compile("test");
assertEquals(p1, p2); // fails!
}
最常见的解决方法似乎是比较模式对象的字符串表示形式(返回用于创建模式的字符串):
我想我明白了这个问题的意思,因为我寻找了比较模式的方法,所以我在这里结束了(可能晚了两年,很抱歉…)
我正在编写测试,我需要知道我的方法是否返回预期的模式。虽然通过toString()
或pattern()
的文本可能相同,但标志可能不同,并且使用该模式时的结果可能是意外的
不久前,我编写了自己的toString()
的一般实现。它收集所有字段,包括private
字段,并构造一个字符串,用于日志记录和测试。结果表明,当编译两个相等的模式时,root
和matchRoot
字段是不同的。假设这两个变量与等式无关,并且因为有一个字段标志
,我的解决方案即使不完美也很好
/**
* Don't call this method from a <code>toString()</code> method with
* <code>useExistingToString</code> set to <code>true</code>!!!
*/
public static String toString(Object object, boolean useExistingToString, String... ignoreFieldNames) {
if (object == null) {
return null;
}
Class<? extends Object> clazz = object.getClass();
if (useExistingToString) {
try {
// avoid the default implementation Object.toString()
Method methodToString = clazz.getMethod("toString");
if (!methodToString.getDeclaringClass().isAssignableFrom(Object.class)) {
return object.toString();
}
} catch (Exception e) {
}
}
List<String> ignoreFieldNameList = Arrays.asList(ignoreFieldNames);
Map<String, Object> fields = new HashMap<String, Object>();
while (clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
String fieldName = field.getName();
if (ignoreFieldNameList.contains(fieldName) || fields.containsKey(fieldName)) {
continue;
}
boolean accessible = field.isAccessible();
if (!accessible) {
field.setAccessible(true);
}
try {
Object fieldValue = field.get(object);
if (fieldValue instanceof String) {
fieldValue = stringifyValue(fieldValue);
}
fields.put(fieldName, fieldValue);
} catch (Exception e) {
fields.put(fieldName, "-inaccessible- " + e.getMessage());
}
if (!accessible) {
field.setAccessible(false);
}
}
// travel upwards in the class hierarchy
clazz = clazz.getSuperclass();
}
return object.getClass().getName() + ": " + fields;
}
public static String stringifyValue(Object value) {
if (value == null) {
return "null";
}
return "'" + value.toString() + "'";
}
测试为绿色:
String toString1 = Utility.toString(Pattern.compile("test", Pattern.CASE_INSENSITIVE), false, "root", "matchRoot");
String toString2 = Utility.toString(Pattern.compile("test", Pattern.CASE_INSENSITIVE), false, "root", "matchRoot");
assertEquals(toString1, toString2);
要确定两个模式
对象是否等效,最简单的方法是比较实际的字符串模式和用于创建该模式的标志:
boolean isPatternEqualToPattern(final Pattern p1, final Pattern p2) {
return p1.flags() == p2.flags() &&
p1.pattern().equals(p2.pattern());
}
我知道自动机可以解决你的问题。但这可能很复杂。
大致来说,您至少应该比较pattern.pattern()
和pattern.flags()
,尽管这还不足以决定两个正则表达式是否相同
boolean isPatternEqualToPattern(final Pattern p1, final Pattern p2) {
return p1.flags() == p2.flags() &&
p1.pattern().equals(p2.pattern());
}