从java中的HashMap返回通配符匹配的列表

发布于 2024-12-07 19:46:41 字数 361 浏览 0 评论 0原文

我有一个 Hashmap,它的字符串中可能包含通配符 (*)。

例如,

HashMap<String, Student> students_;

可以将 John* 作为一把钥匙。我想知道 JohnSmith 是否与 Students_ 中的任何元素匹配。我的字符串可能有多个匹配项(John*、Jo*Smith 等)。有什么方法可以从我的 HashMap 中获取这些匹配项的列表吗?

是否有另一个我可以使用的对象不需要我迭代集合中的每个元素,或者我是否必须吸收它并使用 List 对象?

仅供参考,我的集合中的元素将少于 200 个,最终我希望找到与最少数量的通配符匹配的元素对。

I have a Hashmap which may contain wildcards (*) in the String.

For instance,

HashMap<String, Student> students_;

can have John* as one key. I want to know if JohnSmith matches any elements in students_. There could be several matches for my string (John*, Jo*Smith, etc). Is there any way I can get a list of these matches from my HashMap?

Is there another object I could be using that does not require me to iterate through every element in my collection, or do I have to suck it up and use a List object?

FYI, my collection will have less than 200 elements in it, and ultimately I will want to find the pair that matches with the least amount of wildcards.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

美羊羊 2024-12-14 19:46:41

由于哈希函数的原因,不可能使用 hasmap 来实现。它必须分配 "John*" 的哈希值和 "John Smith" 等人的哈希值。相同的值。

如果您编写自己的自定义类 WildcardString 包装 String,并以 "John*".compareTo 的方式实现 compareTo,则可以使用 TreeMap 来实现它("John Smith") 返回 0。您可以使用 其他答案已经指出。

看到您想要通配符匹配列表,您可以随时删除找到的条目,并迭代TreeMap.get()。输入完名字后,记得将钥匙放回原处。

这只是实现这一目标的一种可能方法。如果元素少于 200 个,您就可以进行迭代。

更新:要在 TreeSet 上正确施加顺序,您可以区分比较两个 WildcardString 的情况(意味着它是键之间的比较)和将 WildcardStringString 进行比较(将键与搜索值进行比较)。

It's not possible to achieve with a hasmap, because of the hashing function. It would have to assign the hash of "John*" and the hash of "John Smith" et al. the same value.

You could make it with a TreeMap, if you write your own custom class WildcardString wrapping String, and implement compareTo in such a way that "John*".compareTo("John Smith") returns 0. You could do this with regular expressions like other answers have already pointed out.

Seeing that you want the list of widlcard matchings you could always remove entries as you find them, and iterate TreeMap.get()'s. Remember to put the keys back once finished with a name.

This is just a possible way to achieve it. With less than 200 elements you'll be fine iterating.

UPDATE: To impose order correctly on the TreeSet, you could differentiate the case of comparing two WildcardStrings (meaning it's a comparation between keys) and comparing a WildcardString to a String (comparing a key with a search value).

李不 2024-12-14 19:46:41

您可以使用正则表达式进行匹配,但必须首先将 "John*" 转换为正则表达式等效的 "John.*",尽管您可以即时执行此操作。

这是一些可以工作的代码:

String name = "John Smith"; // For example
Map<String, Student> students_ = new HashMap<String, Sandbox.Student>();

for (Map.Entry<String, Student> entry : students_.entrySet()) {
    // If the entry key is "John*", this code will match if name = "John Smith"
    if (name.matches("^.*" + entry.getKey().replace("*", ".*") + ".*$")) {
        // do something with the matching map entry
        System.out.println("Student " + entry.getValue() + " matched " + entry.getKey());
    }
}

You can use regex to match, but you must first turn "John*" into the regex equivalent "John.*", although you can do that on-the-fly.

Here's some code that will work:

String name = "John Smith"; // For example
Map<String, Student> students_ = new HashMap<String, Sandbox.Student>();

for (Map.Entry<String, Student> entry : students_.entrySet()) {
    // If the entry key is "John*", this code will match if name = "John Smith"
    if (name.matches("^.*" + entry.getKey().replace("*", ".*") + ".*$")) {
        // do something with the matching map entry
        System.out.println("Student " + entry.getValue() + " matched " + entry.getKey());
    }
}
断爱 2024-12-14 19:46:41

您可以只迭代您的 Map,而不将其转换为列表,并使用字符串匹配函数,其中使用正则表达式。

如果你想避免循环,你可以像这样使用番石榴

@Test
public void hashsetContainsWithWildcards() throws Exception {
Set<String> students = new HashSet<String>();
students.add("John*");
students.add("Jo*Smith");
students.add("Bill");

Set<String> filteredStudents = Sets.filter(students, new Predicate<String>() {
  public boolean apply(String string) {
    return "JohnSmith".matches(string.replace("*", ".*"));
  }
});

assertEquals(2, filteredStudents.size());
assertTrue(filteredStudents.contains("John*"));
assertTrue(filteredStudents.contains("Jo*Smith"));

}

You can just iterate your Map without converting it into a list, and use the String matches function, wih uses a regexp.

If you want to avoid the loop, you can use guava like this

@Test
public void hashsetContainsWithWildcards() throws Exception {
Set<String> students = new HashSet<String>();
students.add("John*");
students.add("Jo*Smith");
students.add("Bill");

Set<String> filteredStudents = Sets.filter(students, new Predicate<String>() {
  public boolean apply(String string) {
    return "JohnSmith".matches(string.replace("*", ".*"));
  }
});

assertEquals(2, filteredStudents.size());
assertTrue(filteredStudents.contains("John*"));
assertTrue(filteredStudents.contains("Jo*Smith"));

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文