【问题标题】:Comparing collections of Reg Ex Patterns比较 Reg Ex 模式的集合
【发布时间】:2011-11-16 03:57:17
【问题描述】:

简而言之,我如何最好地检查两个 Reg Ex 模式集合是否相等(忽略顺序)?

关于我实际尝试使用它的更多信息,我有一个用于过滤日志消息的对象,此过滤器对象包含可用于过滤的每件事的集合,其中之一是 Reg Ex 模式。我为我的过滤对象创建了一个 equals 方法,因此我可以查看两个过滤器是否基本相同,对于其他集合我可以使用集合 .equals 方法,但我对 Pattern 对象有问题。

我可以将模式的字符串输入列表保留在不同的列表中,并将字符串列表与 .equals 进行比较,或者我可以运行所有对象并逐个检查它们,如果 .toString 与另一个匹配每个列表的列表如下:

        boolean equals = true;
        for (Pattern p1: patternList1) {
            boolean found = false;
            for (Pattern p2: patternList2) {
                if(p1.toString().equals(p2.toString())) {
                    found = true;
                    break;
                }
            }
            if(!found) {
                equals = false;
                break;
            }
        }
        if(equals) {
            for (Pattern p1: patternList2) {
                boolean found = false;
                for (Pattern p2: patternList1) {
                    if(p1.toString().equals(p2.toString())) {
                        found = true;
                        break;
                    }
                }
                if(!found) {
                    equals = false;
                    break;
                }
            }
        }
        return equals;

这看起来不是很有效但会起作用,但如果两个正则表达式模式匹配相同但写法不同,它就不会捕获。上面的代码如何以不同的方式优化/完成?是否有任何“简单”的方法来捕获写得不同但匹配相同的 reg ex?

【问题讨论】:

    标签: java regex collections compare equals


    【解决方案1】:

    这里的问题是Pattern 类没有实现equals(),所以你不能轻易比较集合。要解决这个问题,请创建您自己的 Pattern 包装类,该类包含 Pattern 并实现 equals()。例如:

    public class PatternWrapper{
        private final Pattern pattern;
    
        public PatternWrapper(Pattern p) {
            this.pattern = p;
        }
    
        /**
         * @return the pattern
         */
        public Pattern getPattern() {
            return pattern;
        }
    
        /* (non-Javadoc)
         * @see java.lang.Object#hashCode()
         */
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((pattern == null) ? 0 : pattern.hashCode());
            return result;
        }
    
        /* (non-Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals(Object obj) {
            if (obj == this)
                return true;
            if (!(obj instanceof PatternWrapper))
                return false;
            PatternWrapper other = (PatternWrapper) obj;
            if (pattern == null) {
                if (other.pattern != null)
                    return false;
            } else if (!pattern.toString().equals(other.pattern.toString()))
                return false;
            return true;
        }
    }
    

    现在您可以将 PatternWrapper 对象存储在您的集合中。

    由于您希望在比较集合时忽略排序,因此不能简单地在两个集合之间调用equals,因为这会比较对应的元素。但是,您可以使用另一个库(例如 Apache commons-collections CollectionUtils#isEqualCollection)来独立于顺序比较它们。查看这个 SO 问题以获取更多信息:Is there a way to check if two Collections contain the same elements, independent of order?

    我认为没有一种简单的方法可以匹配两个具有不同模式但匹配相同文本的正则表达式。一种方法可能是创建一个测试字符串列表,您可以针对每个正则表达式运行这些测试字符串以查看它们是否匹配。

    【讨论】:

    • 除非您有重复的模式并且不一直比较它们,否则您可以在比较之前将模式放入集合中。
    • 认识到两个正则表达式匹配完全相同的字符串集并非易事。您必须将每个模式减少为所谓的最小确定性有限状态机,然后进行比较。
    • 非常感谢,我感觉这是我的问题,但不确定是 Patterns 中的 .equals 问题。另外,我得到的其他过滤选项的排序没有问题的原因是,模式是我唯一进入列表的一次,其余的都在集合中,所以谢谢你指出这一点。
    【解决方案2】:

    我只是answered 一个关于比较一个Pattern 的相当相似的问题,因为这是有问题的,因为在比较它们时它的flag 被忽略了。因为这些列表或数组与遇到此问题的任何人都可能会在那里查看几乎相同的东西。

    关于未排序的检查,请参阅dogbane's answer

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-08
      相关资源
      最近更新 更多