diff --git a/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java b/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java index b52133be7..c1c69af51 100755 --- a/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java +++ b/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java @@ -102,23 +102,22 @@ public class WordTree extends HashMap { WordTree parent = null; WordTree current = this; WordTree child; - char currentChar = 0; + Character lastAcceptedChar = null; + final int length = word.length(); for (int i = 0; i < length; i++) { - currentChar = word.charAt(i); + char currentChar = word.charAt(i); if (charFilter.accept(currentChar)) {//只处理合法字符 - child = current.get(currentChar); - if (child == null) { - //无子类,新建一个子节点后存放下一个字符 - child = new WordTree(); - current.put(currentChar, child); - } + child = current.computeIfAbsent(currentChar, c -> new WordTree()); parent = current; current = child; + lastAcceptedChar = currentChar; } } + // 仅当存在父节点且存在非停顿词时,才设置词尾标记 + // 当 null != parent 条件成立时,lastAcceptedChar != null 必然成立,故也可以省去 if (null != parent) { - parent.setEnd(currentChar); + parent.setEnd(lastAcceptedChar); } return this; } diff --git a/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java b/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java index 97b068be5..7ae160a75 100755 --- a/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java +++ b/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java @@ -116,6 +116,34 @@ public class DfaTest { assertEquals(all, CollUtil.newArrayList("t-io")); } + /** + * Github Issue #4091 + * 测试当关键词以停顿词(如括号)结尾时,其合法前缀是否能被正确匹配 + */ + @Test + public void addWordWithTrailingFilteredCharTest() { + WordTree tree = new WordTree(); + tree.addWord("hello "); // 以被过滤字符结尾 + + List matches = tree.matchAll("hello", -1); + assertEquals(1, matches.size()); + assertEquals("hello", matches.get(0)); + } + + /** + * Github Issue #4091 + * 测试关键词中间包含停顿词的情况 + */ + @Test + public void addWordWithMiddleFilteredCharTest() { + WordTree tree = new WordTree(); + tree.addWord("he llo"); // 中间 '(' 被过滤 + + List matches = tree.matchAll("hello", -1); + assertEquals(1, matches.size()); + assertEquals("hello", matches.get(0)); + } + @Test public void aTest(){ WordTree tree = new WordTree();