Java:基于正则表达式在HashMap密钥中搜索?

时间:2009-05-18 20:57:48

标签: java regex hashmap

我正在使用HashMap构建同义词库来存储同义词。

我正在尝试基于正则表达式搜索单词:该方法必须将字符串作为参数并返回结果数组。这是我的第一次尝试:

public ArrayList<String> searchDefinition(String regex) {
    ArrayList<String> results = new ArrayList<String>();

    Pattern p = Pattern.compile(regex);

    Set<String> keys = thesaurus.keySet();
    Iterator<String> ite = keys.iterator();

    while (ite.hasNext()) {
        String candidate = ite.next();
        Matcher m = p.matcher(candidate);
        System.out.println("Attempting to match: " + candidate + " to "  + regex);
        if (m.matches()) {
            System.out.println("it matches");
            results.add(candidate);
        }
    }   

    if (results.isEmpty()) {
        return null;
    }
    else {
        return results;
    }
}

现在,这不会像我期望的那样工作(或者我可能错误地使用正则表达式)。如果我在hashmap中有以下键:

cat, car, chopper

然后通过致电searchDefinition("c")searchDefinition("c*")我获得null

  1. 如何按预期方式开展此工作?
  2. 是否有比HashMap更好的数据结构来保持同义词所需的graph? (仅限好奇心,对于此作业,我们被要求使用Java Collection Map)。
  3. 我在上面的代码中没有做任何其他事情吗?
  4. 谢谢, 丹

    编辑:我已经纠正了这个例子。即使我使用了正确的案例,它也不起作用。

6 个答案:

答案 0 :(得分:10)

您需要指定不区分大小写Pattern.compile ( "c", Pattern.CASE_INSENSITIVE )。要查找包含c的字词,您需要使用matcher.find()Matcher.matches()尝试匹配整个字符串。

答案 1 :(得分:10)

但是,嗯:

(a)如果您打算始终按顺序搜索HashMap,为什么还要使用HashMap?处理哈希键时会浪费很多浪费,而且当你从不使用哈希键时。当然,一个简单的ArrayList或LinkedList会更好。

(b)这与词库有什么关系?为什么要使用正则表达式搜索同义词库?如果我想知道“cat”的同义词,我会认为我会搜索“cat”,而不是“c。*”。

我对如何构建词库的第一个想法是......好吧,我想我要问的第一个问题是,“同义词是一个等同关系吗?”,即如果A是B的同义词,那么它请注意B是A的同义词?如果A是B的同义词而B是C的同义词,那么A是C的同义词吗?假设这些问题的答案是“是”,那么我们想要构建的是将语言中的所有单词划分为同义词集合的东西,因此我们可以将每个集合中的任何单词映射到该集合中的所有其他单词。所以你需要的是一种方法来接受任何单词,将其映射到某种连接点,然后从那个连接点转到映射到它的所有单词。

这对数据库来说很简单:只需创建一个包含两列的表,比如说“word”和“token”,每个列都有自己的索引。所有同义词都映射到同一个令牌。令牌可以是任何东西,只要它对于任何给定的同义词集合是唯一的,例如序列号。然后搜索给定的单词,找到关联的标记,然后获取具有该标记的所有单词。例如,我们可以使用(大,1),(大,1),(巨大,1),(猫,2),(猫,2)等创建记录。搜索“大”并获得1,然后搜索1,你会得到“大”,“大”和“巨人”。

我不知道内置Java集合中的任何类都可以执行此操作。我能想到的最简单的方法是构建两个协调的哈希表:一个用于将单词映射到标记,另一个用于将标记映射到一个单词数组。因此,表1可能具有big-> 1,large-> 1,gigantic-> 1,cat-> 2,feline-> 2等。然后表2映射1-> [big,large,您可以在第一个表中查找将一个单词映射到一个标记,然后在第二个表中将该标记映射回一个单词列表。巨型],2-> [猫,猫]等。它是笨拙的,因为所有的数据都是冗余存储的,也许有更好的解决方案,但我并没有把它从头脑中解脱出来。 (好吧,如果我们假设我们每次都会按顺序搜索整个单词列表会很容易,但随着列表变大,性能会很糟糕。)

答案 2 :(得分:3)

这是你正在使用的正则表达式吗?

仅当整个输入序列与表达式(来自Javadoc)匹配时,Matcher.matches()方法才返回true,因此在这种情况下需要使用"c.*",而不是"c*"以及不敏感的匹配案例。

答案 3 :(得分:2)

正则表达式区分大小写。你想要:

Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);

答案 4 :(得分:2)

看起来你正在使用你的正则表达式。 “c”只匹配小写字母c,而不是大写字母。

那就是说,我建议您考虑使用具有全文搜索功能的嵌入式数据库。

答案 5 :(得分:0)

回应杰伊的“但是嗯”,

(我会添加评论,但没有代表。)

按顺序搜索它是一种缓慢的方式。用正则表达式做这件事就是陷入疯狂。使用数据库进行编程是一个编程警察。当然,如果你的数据集可能是必需的,但请记住“为了这个任务我们被要求使用Java Collection Map”我们应该找出使用这个java集合的正确方法。

它不明显的原因是因为它不是一个集合。这是两个。但它不是两张地图。它不是ArrayList。缺少的是一套。它是一组同义词的映射。

组&LT;字符串&GT;将让你建立你的同义词列表。你可以随意制作多少。两组同义词就是一个很好的例子。这是一个Set not a ArrayList,因为你不想要重复的单词。

Map&lt; String,Set&lt; String&gt;&gt;将让您快速找到从任何单词到其同义词集的方式。

构建你的套装。然后构建地图。编写辅助方法来构建带有地图和集合的地图。

addSet(Map&lt; String,Set&lt; String&gt;&gt; map,Set&lt; String&gt; newSet)

此方法只是循环newSet并将字符串作为键添加到地图中,并将newSet的引用添加为值。你可以为每一组调用addSet一次。

现在你构建了数据结构,我们应该能够找到东西。为了使其更加健壮,请记住在搜索之前清理搜索关键字。使用trim()来消除无意义的空白。使用toLowerCase()来摆脱无意义的大写。您应该在构建集合之前(或同时)在同义词数据上完成这两项操作。这样做,谁需要正则表达式?这种方式更快,更重要的是更安全。正则表达式非常强大,但在出错时可能是调试的噩梦。不要仅仅因为你认为它们很酷而使用它们。