我有一個基于主題的發布訂閱服務,我正在研究主題匹配。我擁有的當前測驗樹如下(每行代表一個主題):
t1.t2
t1.t3
t1.t4
t1.t3.t5
t1.t4.t6
結果應該是(使用通配符時):
t1.# -> t1.t2, t1.t3, t1.t4, t1.t3.t5, t1.t4.t6
t1.* -> t1.t2, t1.t3, t1.t4
我當前的代碼:
public List<Topic> getMatchingTopics(Topic topic, List<Topic> currentTopics) {
List<Topic> matchingTopics = new ArrayList<>();
String topicString = topic.getName();
for (Topic t : currentTopics) {
String currentTopicString = t.getName();
if (topicString.equals(currentTopicString)) {
matchingTopics.add(t);
} else {
String[] topicStringSplit = topicString.split("\\.");
String[] currentTopicStringSplit = currentTopicString.split("\\.");
if (topicStringSplit.length == currentTopicStringSplit.length) {
boolean match = true;
for (int i = 0; i < topicStringSplit.length; i ) {
if (topicStringSplit[i].equals("*")) {
continue;
}
else if (topicStringSplit[i].equals("#")) {
continue;
} else if (!topicStringSplit[i].equals(currentTopicStringSplit[i])) {
// not a match
match = false;
break;
}
}
if (match) {
matchingTopics.add(t);
}
}
}
}
return matchingTopics;
}
星號通配符 (*) 有效,但是,我遇到了主題標簽 (#) 的問題,因此為了清楚起見,兩者的邏輯相同。
測驗方法
@Test
public void testTopicMatch() {
// t1.t2
// t1.t3
// t1.t4
// t1.t3.t5
// t1.t4.t6
// t1.# -> t1.t2, t1.t3, t1.t4, t1.t3.t5, t1.t4.t6
// t1.* -> t1.t2, t1.t3, t1.t4
List<Topic> topics = new ArrayList<>();
Topic t1t2 = new Topic();
t1t2.setName("t1.t2");
topics.add(t1t2);
Topic t1t3 = new Topic();
t1t3.setName("t1.t3");
topics.add(t1t3);
Topic t1t4 = new Topic();
t1t4.setName("t1.t4");
topics.add(t1t4);
Topic t1t3t5 = new Topic();
t1t3t5.setName("t1.t3.t5");
topics.add(t1t3t5);
Topic t1t4t6 = new Topic();
t1t4t6.setName("t1.t4.t6");
topics.add(t1t4t6);
Topic topicHashtag = new Topic();
topicHashtag.setName("t1.#");
List<Topic> res = getMatchingTopics(topicHashtag, topics);
for (Topic topic : res) {
System.out.println(topic.getName());
}
}
uj5u.com熱心網友回復:
一種看待這種情況的方法是使用正則運算式。您的規范可能會翻譯如下:
t1.* -> t1.t2, t1.t3, t1.t4
Regex: (t1\.)(t[0-9])
Explanation: Any string (topic name) starting with t1. followed by exactly t and number
t1.# -> t1.t2, t1.t3, t1.t4, t1.t3.t5, t1.t4.t6
Regex: (t1\.)(t[0-9])(\.(t[0-9]))?
Explanation: Any string (topic name) starting with t1., followed by exactly t and number, optionally followed by a dot, a t and a number
當然,這是一個非常簡單的定義,可以根據其他匹配規則進行推廣。對于您的匹配要求,它應該像以下測驗所示那樣作業:
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.regex.Pattern;
import static java.util.stream.Collectors.toList;
import static junit.framework.Assert.assertEquals;
public class RegexTest {
final List<String> topicNames = List.of("t1.t2", "t1.t3", "t1.t4", "t1.t3.t5", "t1.t4.t6");
@Test
void regexForAsteriskSpecification(){
final Pattern asteriskPattern = Pattern.compile("(t1\\.)(t[0-9])");
java.util.List<String> collect = topicNames.stream().filter(n -> n.matches(asteriskPattern.pattern())).collect(toList());
assertEquals(collect, List.of("t1.t2", "t1.t3", "t1.t4"));
}
@Test
void regexForHashtagSpecification(){
final Pattern asteriskPattern = Pattern.compile("(t1\\.)(t[0-9])(\\.(t[0-9]))?");
java.util.List<String> collect = topicNames.stream().filter(n -> n.matches(asteriskPattern.pattern())).collect(toList());
assertEquals(collect, topicNames);
}
}
uj5u.com熱心網友回復:
首先,您應該添加方法來計算要在匹配中使用的匹配*級別
class Topic {
private String name;
public String getName() {return name;}
public void setName(String name) {this.name = name;}
// add this method to compute level based on how many dot (.)
public int level() {return (int) this.name.chars().filter(it -> it == '.').count();}
}
public List<Topic> getMatchingTopics(Topic topic, List<Topic> currentTopics) {
List<Topic> matchingTopics = new ArrayList<>();
String topicString = topic.getName();
// if match topic is ends with `#` | eg. `topicString` = `"t1.#"`
if (topicString.endsWith(".#")) {
// drop `#` char | `topicPrefix` = `"t1."`
String topicPrefix = topicString.substring(0, topicString.length() - 1);
for (Topic currentTopic : currentTopics) {
// check if topic name is start with `topicPrefix` (`"t1."`)
// this will match any topic start with "t1."
if (currentTopic.getName().startsWith(topicPrefix)) {
matchingTopics.add(currentTopic);
}
}
} else if (topicString.endsWith(".*")) {
// drop `*` char | `topicPrefix` = `"t1."`
String topicPrefix = topicString.substring(0, topicString.length() - 1);
// level is based on dot as previous step `"t1.*"` is `1`
int topicLevel = topic.level();
for (Topic currentTopic : currentTopics) {
// check if topic is start with `topicPrefix` (`"t1."`)
if (currentTopic.getName().startsWith(topicPrefix)
// AND check if topic is at same level
// `"t1.t2"` have level 1 = match
// `"t1.t2.t3"` have level 2 = not match
&& currentTopic.level() == topicLevel) {
matchingTopics.add(currentTopic);
}
}
} else {
// your logic
for (Topic currentTopic : currentTopics) {
if (currentTopic.getName().equals(topicString)) {
matchingTopics.add(currentTopic);
}
}
}
return matchingTopics;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/516173.html
標籤:爪哇细绳通配符
上一篇:布林值不從假變為真
下一篇:Java中介面的回傳串列
