Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java比较两个模式对象_Java_Regex - Fatal编程技术网

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());
    }