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

Java:基于正则表达式在HashMap键中搜索?,java,regex,hashmap,Java,Regex,Hashmap,我正在用HashMap建立一个同义词词典来存储同义词 我试图根据正则表达式搜索单词:该方法必须将字符串作为参数并返回结果数组。这是我的第一次尝试: public ArrayList<String> searchDefinition(String regex) { ArrayList<String> results = new ArrayList<String>(); Pattern p = Pattern.compile(regex);

我正在用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;
    }
}
然后通过调用
searchDefinition(“c”)
searchDefinition(“c*”)
我得到
null

  • 我怎样才能使这项工作达到预期效果
  • 是否有比HashMap更好的数据结构来保存同义词表所需的
    图形?(仅出于好奇,本作业要求我们使用Java集合图)
  • 在上面的代码中,我还做了其他不恰当的事情吗
  • 谢谢, 丹


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

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

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

    看起来你不恰当地使用了正则表达式。“c”只匹配小写字母c,而不匹配大写字母


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

    您需要指定不区分大小写
    (“c”,“code>)
    )。要查找包含
    c
    的单词,您需要使用。尝试匹配整个字符串。

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

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

    但是,嗯:

    (a) 如果要始终按顺序搜索,为什么要使用HashMap?如果您从未使用过散列键,那么处理散列键以及所有这些都会浪费大量开销。当然,一个简单的ArrayList或LinkedList会是一个更好的主意

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

    我对如何建立同义词库的第一个想法是。。。我想我要问的第一个问题是,“同义词是等价关系吗?”,也就是说,如果A是B的同义词,那么B是A的同义词吗?如果A是B的同义词,B是C的同义词,那么A是C的同义词吗?假设这些问题的答案是“是”,那么我们想要构建的是将语言中的所有单词划分为同义词集,这样我们就可以将每个集中的任何单词映射到该集中的所有其他单词。所以你需要的是一种方法,把任何单词,映射到某种连接点,然后从这个连接点到所有映射到它的单词

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

    我不知道内置Java集合中有任何类可以这样做。我能想到的最简单的方法是构建两个协调的哈希表:一个将单词映射到标记,另一个将标记映射到单词数组。所以表1可能有大->1,大->1,巨人->1,猫->2,猫->2,等等。然后表2映射1->[大,大,巨人],2->[猫,猫],等等。您在第一个表中查找将单词映射到标记,在第二个表中将该标记映射回单词列表。这很笨拙,因为所有的数据都是冗余存储的,也许有更好的解决方案,但我并没有忘记。(好吧,如果我们假设每次都要按顺序搜索整个单词列表,那就很容易了,但随着列表越来越大,性能会越来越差。)

    回应上面“但是嗯”的Jay

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

    按顺序搜索是一种缓慢的方式。用正则表达式做这件事简直是疯了。用数据库做这件事是一种编程上的逃避。当然,如果您的数据集非常庞大,那么这可能是必需的,但请记住“对于此任务,我们被要求使用Java集合映射”,我们应该找到使用此Java集合的正确方法

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

    Set将允许您建立同义词列表。你想做多少就做多少。两组同义词就是一个很好的例子。这是一个集合而不是数组列表,因为你不想重复单词

    Map将让您快速找到从任何单词到其同义词集的方法

    建立你的集合。然后构建地图。编写一个helper方法来构建包含一个map和一个set的map

    addSet(映射映射,设置新闻集)

    这个方法只是循环newSet,将字符串作为键添加到映射中,并将对newSet的引用作为值。你会为每个集合调用addSet一次

    既然您的数据结构已经建立,我们应该能够找到东西。为了使它更加健壮,请记住在搜索之前清理搜索键。使用trim()删除无意义的空白。使用toLowerCase()可以消除无意义的大写。您应该在构建集合之前(或在构建集合时)对同义词数据执行这两项操作。那么谁需要正则表达式呢?这种方式更快,更重要的是更安全。正则表达式非常强大,但当它们出错时,可能会成为调试的噩梦。不要仅仅因为你认为它们很有用就使用它们
    Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);