Ответ 1
Почему бы не отсортировать список правил для начала. Затем вы можете выполнить двоичный поиск соответствующего правила.
У меня есть список правил в форме
L1 → (A, B, C)
L2 → (D, E),
L3 → (F, G, A),
L4 → (C, A)
.....
Этот список содержит ~ 30k таких правил.
У меня есть вход в форме (X, Y, Z)
Это создает метод
List <Rule> matchRules(input)
Что принадлежит классу RuleMatcher
Я начал с очень простого ясного наивного решения, чтобы получить структуру, получить что-то работающее.
public RuleMatcher(Collection<Rule> rules) {
this.rules = rules;
}
public Collection<Rule> matchRules(List<Token> input) {
List<Rule> matchingRules = new ArrayList<>();
for(Rule r: this.rules) {
if(r.matches(input)) {
matchingRules.add(r);
}
}
return matchingRules;
}
Где matches
- очень простая функция, которая проверяет, совпадают ли длины, а затем проверяет каждый токен как цикл for.
Эта функция matchRules вызывается в величине миллиардов раз.
Очевидно, что это очень плохая реализация. Согласно моему профилировщику, в этой функции совпадений используется не менее половины времени выполнения.
Я думал о двух возможных решениях:
а. Некоторая структура данных Trie, содержащая цепочки правил, которые могут быть сопоставлены.
В. некоторая хэш-функция. Каждому символу присваивается уникальный идентификатор. К сожалению, существует около 8 тысяч уникальных символов, поэтому это может быть затруднено.
С. Сделайте условие хешмапа по размеру правой стороны, количество жетонов в правиле. К сожалению, большинство правил примерно одинакового размера, поэтому это может даже не стоить.
Д. Удивительное решение, из которого один из вас придумал.
Я надеюсь, что кто-то может пролить свет на эту проблему.
Изменить: токен - это просто объект с уникальным номером. Например, "NN" является токеном. Каждый экземпляр "NN" точно такой же.
Код соответствия:
public boolean rhsMatches(List<Token> tokens) {
if(tokens.size()!=rhsSize()) return false;
for(int i = 0;i<rhsSize();i++) {
if(!rightSide.get(i).equals(tokens.get(i)) {
return false;
}
}
return true;
}
Это не очень красиво, но просто.
Почему бы не отсортировать список правил для начала. Затем вы можете выполнить двоичный поиск соответствующего правила.
Для меня это выглядит как идеальный сценарий для привлечения некоторых рабочих потоков. Задачи сопоставления кажутся независимыми друг от друга, разделяют список правил и делегируют соответствие рабочим, если это возможно в вашей ситуации.