Возврат списка подстановочных совпадений из HashMap в Java - PullRequest
10 голосов
/ 30 сентября 2011

У меня есть Hashmap, который может содержать символы подстановки (*) в строке.

Например,

HashMap<String, Student> students_;

может иметь Джона * в качестве одного ключа. Я хочу знать, соответствует ли JohnSmith какие-либо элементы в student_. Для моей строки может быть несколько совпадений (Джон *, Джо * Смит и т. Д.). Есть ли способ получить список этих совпадений из моего HashMap?

Есть ли другой объект, который я мог бы использовать, который не требует, чтобы я перебирал все элементы в моей коллекции, или мне нужно его подхватить и использовать объект List?

К вашему сведению, в моей коллекции будет менее 200 элементов, и в итоге я захочу найти пару, которая соответствует наименьшему количеству подстановочных знаков.

Ответы [ 3 ]

3 голосов
/ 30 сентября 2011

Вы можете использовать регулярное выражение для соответствия, но сначала вы должны превратить "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());
    }
}
2 голосов
/ 30 сентября 2011

Невозможно достичь с помощью hasmap из-за функции хеширования.Это должно было бы присвоить хэш "John*" и хэш "John Smith" и др.то же самое значение.

Вы можете сделать это с TreeMap, если вы напишите свой собственный класс WildcardString, упаковывающий String, и реализуете compareTo таким образом, что "John*".compareTo("John Smith") возвращает 0. Вы можете сделатьэто с помощью регулярных выражений, таких как другие ответы уже указали.

Видя, что вы хотите список совпадений карточек виджетов , вы всегда можете удалить записи, как только найдетеитерация TreeMap.get().Не забудьте поставить ключи обратно после того, как закончите с именем.

Это просто возможный способ добиться этого.Имея менее 200 элементов, вы будете хорошо выполнять итерации.

ОБНОВЛЕНИЕ: Чтобы правильно навести порядок на TreeSet, вы можете различить случай сравнения двух WildcardString s (то естьэто сравнение между ключами) и сравнение WildcardString с String (сравнение ключа со значением поиска).

0 голосов
/ 30 сентября 2011

Вы можете просто перебрать свою Карту, не конвертируя ее в список, и использовать функцию соответствия строк, которая использует регулярное выражение.

Если вы хотите избежать цикла, вы можете использовать guava следующим образом

@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"));

}

...