渴望像神话中巨型的黄色罗马蜡烛那样燃烧。——杰克·凯鲁亚克《在路上》
这里是基于hutool
的dfa
查找法得到的结果集进行封装,不一定非要依赖hutool
,可以自定义FoundWord
对象,里面就只用到了一个起始下标,以及对应需要高亮的词汇
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public static String highlight(String text, List<FoundWord> fondWords, UnaryOperator<String> highlightOperator) { if (Opp.ofColl(fondWords).isEmpty() || Opp.ofStr(text).isEmpty()) { return text; } fondWords = Steam.of(fondWords) .sorted(Comparator.comparing(FoundWord::getIndex) .thenComparingInt(w -> w.getWord().length())) .toList(); LinkedList<FoundWord> linkedList = new LinkedList<>(); int lastIdx = 0; for (int i = 0; i < fondWords.size(); i++) { FoundWord fondWord = fondWords.get(i); String word = null; if (i > 0 && lastIdx > fondWord.getIndex()) { FoundWord last = Objects.requireNonNull(linkedList.pollLast()); lastIdx -= last.getWord().length(); int index = fondWord.getWord().indexOf(last.getWord().charAt(last.getWord().length() - 1)); String suffix = fondWord.getWord().substring(index+1); word = last.getWord() + suffix; } else { String partOne = text.substring(lastIdx, fondWord.getIndex()); lastIdx += partOne.length(); linkedList.add(new FoundWord(partOne, lastIdx)); } word = Opp.ofStr(word).orElseGet(fondWord::getWord); lastIdx += word.length(); linkedList.add(new FoundWord(word, highlightOperator.apply(word), lastIdx)); } linkedList.add(new FoundWord(text.substring(lastIdx), text.substring(lastIdx), lastIdx)); return Steam.of(linkedList).map(FoundWord::getWordAfterHighlight).join(); }
|
使用:
1 2 3 4 5 6 7 8 9 10
| WordTree tree = new WordTree(); tree.addWord("大"); tree.addWord("大土豆"); tree.addWord("土豆"); tree.addWord("刚出锅"); tree.addWord("出锅"); String text = "我有一颗大土豆,刚出锅的"; List<FoundWord> foundWords = tree.matchAllWords(text, -1, true, true); String result = CommonUtils.highlight(text, foundWords, s -> "<span style='color:red'>" + s + "</span>"); System.out.println(result);
|
效果:
这里重载了一个needSort
,如果是自定义的FoundWord
,需要指定为true
,手动进行排序