add HighMultiReplacerTest

This commit is contained in:
Looly 2023-08-31 10:30:01 +08:00
parent 308588c80d
commit cf9cee0b6c
2 changed files with 19 additions and 17 deletions

View File

@ -28,15 +28,16 @@ import java.util.Map;
* @author kyao * @author kyao
*/ */
public class HighMultiReplacer extends StrReplacer { public class HighMultiReplacer extends StrReplacer {
private static final long serialVersionUID = 1L;
private final AhoCorasickAutomaton ahoCorasickAutomaton; private final AhoCorasickAutomaton ahoCorasickAutomaton;
/** /**
* 构造 * 构造
* *
* @param map key为需要被查找的字符串value为对应的替换的值 * @param map key为需要被查找的字符串value为对应的替换的值
*/ */
public HighMultiReplacer(Map<String, String> map) { public HighMultiReplacer(final Map<String, String> map) {
ahoCorasickAutomaton = new AhoCorasickAutomaton(map); ahoCorasickAutomaton = new AhoCorasickAutomaton(map);
} }
@ -46,19 +47,19 @@ public class HighMultiReplacer extends StrReplacer {
* @param map key为需要被查找的字符串value为对应的替换的值 * @param map key为需要被查找的字符串value为对应的替换的值
* @return org.dromara.hutool.core.text.replacer.HighMultiReplacer * @return org.dromara.hutool.core.text.replacer.HighMultiReplacer
*/ */
public static HighMultiReplacer of(Map<String, String> map) { public static HighMultiReplacer of(final Map<String, String> map) {
return new HighMultiReplacer(map); return new HighMultiReplacer(map);
} }
@Override @Override
protected int replace(CharSequence str, int pos, StringBuilder out) { protected int replace(final CharSequence str, final int pos, final StringBuilder out) {
ahoCorasickAutomaton.replace(str, out); ahoCorasickAutomaton.replace(str, out);
return str.length(); return str.length();
} }
@Override @Override
public CharSequence apply(final CharSequence str) { public CharSequence apply(final CharSequence str) {
StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
replace(str, 0, builder); replace(str, 0, builder);
return builder; return builder;
} }
@ -77,7 +78,7 @@ public class HighMultiReplacer extends StrReplacer {
/** /**
* @param target 待查找的目标字符串集合 * @param target 待查找的目标字符串集合
*/ */
public AhoCorasickAutomaton(Map<String, String> target) { public AhoCorasickAutomaton(final Map<String, String> target) {
root = new Node(); root = new Node();
this.target = target; this.target = target;
buildTrieTree(); buildTrieTree();
@ -108,13 +109,13 @@ public class HighMultiReplacer extends StrReplacer {
* 由目标字符串构建Trie树 * 由目标字符串构建Trie树
*/ */
private void buildTrieTree() { private void buildTrieTree() {
for (String targetStr : target.keySet()) { for (final String targetStr : target.keySet()) {
Node curr = root; Node curr = root;
if (targetStr == null) { if (targetStr == null) {
continue; continue;
} }
for (int i = 0; i < targetStr.length(); i++) { for (int i = 0; i < targetStr.length(); i++) {
char ch = targetStr.charAt(i); final char ch = targetStr.charAt(i);
Node node = curr.children.get(ch); Node node = curr.children.get(ch);
if (node == null) { if (node == null) {
node = new Node(); node = new Node();
@ -132,10 +133,10 @@ public class HighMultiReplacer extends StrReplacer {
*/ */
private void buildAcFromTrie() { private void buildAcFromTrie() {
/*广度优先遍历所使用的队列*/ /*广度优先遍历所使用的队列*/
LinkedList<Node> queue = new LinkedList<>(); final LinkedList<Node> queue = new LinkedList<>();
/*单独处理根结点的所有孩子结点*/ /*单独处理根结点的所有孩子结点*/
for (Node x : root.children.values()) { for (final Node x : root.children.values()) {
/*根结点的所有孩子结点的fail都指向根结点*/ /*根结点的所有孩子结点的fail都指向根结点*/
x.fail = root; x.fail = root;
queue.addLast(x);/*所有根结点的孩子结点入列*/ queue.addLast(x);/*所有根结点的孩子结点入列*/
@ -143,8 +144,8 @@ public class HighMultiReplacer extends StrReplacer {
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
/*确定出列结点的所有孩子结点的fail的指向*/ /*确定出列结点的所有孩子结点的fail的指向*/
Node p = queue.removeFirst(); final Node p = queue.removeFirst();
for (Map.Entry<Character, Node> entry : p.children.entrySet()) { for (final Map.Entry<Character, Node> entry : p.children.entrySet()) {
/*孩子结点入列*/ /*孩子结点入列*/
queue.addLast(entry.getValue()); queue.addLast(entry.getValue());
@ -176,14 +177,14 @@ public class HighMultiReplacer extends StrReplacer {
* @param text 被替换的目标字符串 * @param text 被替换的目标字符串
* @param stringBuilder 替换后的结果 * @param stringBuilder 替换后的结果
*/ */
public void replace(CharSequence text, StringBuilder stringBuilder) { public void replace(final CharSequence text, final StringBuilder stringBuilder) {
Node curr = root; Node curr = root;
int i = 0; int i = 0;
while (i < text.length()) { while (i < text.length()) {
/*文本串中的字符*/ /*文本串中的字符*/
char ch = text.charAt(i); final char ch = text.charAt(i);
/*文本串中的字符和AC自动机中的字符进行比较*/ /*文本串中的字符和AC自动机中的字符进行比较*/
Node node = curr.children.get(ch); final Node node = curr.children.get(ch);
if (node != null) { if (node != null) {
stringBuilder.append(ch); stringBuilder.append(ch);
/*若相等,自动机进入下一状态*/ /*若相等,自动机进入下一状态*/

View File

@ -10,7 +10,7 @@ public class HighMultiReplacerTest {
@Test @Test
public void replaceTest() { public void replaceTest() {
Map<String, String> map = new HashMap<>(); final Map<String, String> map = new HashMap<>();
map.put("abc", "bar"); map.put("abc", "bar");
map.put("123", "1234"); map.put("123", "1234");
map.put("12", "哈哈哈"); map.put("12", "哈哈哈");
@ -18,7 +18,8 @@ public class HighMultiReplacerTest {
map.put("你好", "hello world"); map.put("你好", "hello world");
map.put("AAACC", "%^$%$"); map.put("AAACC", "%^$%$");
map.put("_啊", "qqqq"); map.put("_啊", "qqqq");
HighMultiReplacer replacer = HighMultiReplacer.of(map);
final HighMultiReplacer replacer = HighMultiReplacer.of(map);
Assertions.assertEquals("bar哈哈哈hello world4", replacer.apply("abc12你好4").toString()); Assertions.assertEquals("bar哈哈哈hello world4", replacer.apply("abc12你好4").toString());
Assertions.assertEquals("qqqq啊qqqq-啊", replacer.apply("_啊啊_啊-啊").toString()); Assertions.assertEquals("qqqq啊qqqq-啊", replacer.apply("_啊啊_啊-啊").toString());
Assertions.assertEquals("哈哈哈3456789", replacer.apply("123456789").toString()); Assertions.assertEquals("哈哈哈3456789", replacer.apply("123456789").toString());