我试图查看给定主机名是否以逗号分隔字符串的形式出现在主机列表中,如下所示:
String list = "aa.com,bb.com,cc.com,dd.net,ee.com,ff.net";
String host1 = "aa.com"; // should be a match
String host2 = "a.com"; // shouldn't be a match
String host3 = "ff.net" // should be a match
// here is a test for host1
if (list.matches(".*[,^]" + host1 + "[$,].*")) {
System.out.println(host1 + " matched");
}
else {
System.out.println(host1 + " not matched");
}
但我与主持人(aa.com)不匹配,但后来我对正则表达不是很熟悉。请指正!
BTW我不想使用一个解决方案,你可以将主机列表拆分成一个数组,然后在那里进行匹配。它太慢了,因为主机列表可能很长。正则表达式可能会更糟,但我试图让它先工作。
答案 0 :(得分:1)
如果你正在寻找完全匹配,我也认为Regexes太慢了,所以我试着编写一个方法来查找列表中主机名的出现并检查每个子字符串是否它不是一个部分更广泛的主机名(例如" a.com"是" aa.com"的一部分)。如果不是 - 结果是真的,列表中就有这样的主机。这是代码:
boolean containsHost(String list, String host) {
boolean result = false;
int i = -1;
while((i = list.indexOf(host, i + 1)) >= 0) { // while there is next match
if ((i == 0 || list.charAt(i - 1) == ',') // beginning of the list or has a comma right before it
&& (i == (list.length() - host.length()) // end of the list
|| list.charAt(i + host.length()) == ',')) { // or has a comma right after it
result = true;
break;
}
}
return result;
}
但后来我认为只检查3个案例会更快 - 在列表的开头,中间和末尾匹配,这可以通过startsWith
完成,{{1}分别是}和contains
方法。这是第二个选项,我希望在您的情况下:
endsWith
UPD:ZouZou对你的帖子的评论看起来也不错,我建议比较一下类似你在实际情况下的大小的速度,并选择最快的。
答案 1 :(得分:0)
这完全有效,没有正则表达式
String list = "aa.com,bb.com,cc.com,dd.net,ee.com,ff.net";
String host1 = "aa.com";
String host2 = "a.com";
String host3 = "ff.net";
boolean checkingFlag=false;
String [] arrayList=list.split(",");
System.out.println(arrayList.length);
for(int i=0;i<arrayList.length;i++)
{
// here is a test for host1
if (arrayList[i].equalsIgnoreCase(host1))
checkingFlag=true;
}
if (checkingFlag)
System.out.println("Matched");
else
System.out.println("Not matched");
执行一个包含100万条记录的循环几乎不需要20-30毫秒。根据您刚刚编辑的评论。您可以查看此内容。
long startingTime=System.currentTimeMillis();
for(int i=0;i<1000000;i++)
{
if (i==999999)
checkingFlag=true;
}
long endingTime=System.currentTimeMillis();
System.out.println("total time in millisecond:"+ (endingTime-startingTime));
答案 2 :(得分:0)
就像在评论中提到的那样。您不应该使用Matches
,因为它会尝试将正则表达式模式与整个逗号分隔的字符串进行匹配。你不是想这样做。您正在尝试检测给定子字符串是否出现在逗号分隔的源字符串中。
为了做到这一点,您只需在findall
方法中使用主机名即可。但是,您可以使用不会产生正则表达式编译开销的子字符串。
正则表达式用于匹配可能在匹配的模式中有变化的字符串。当您想要进行精确的字符串匹配时,切勿使用正则表达式。
答案 3 :(得分:0)
您可以使用lambda流式传输数组,并为匹配返回boolean
。
String list = "aa.com,bb.com,cc.com,dd.net,ee.com,ff.net";
String host1 = "aa.com"; // should be a match
String host2 = "a.com"; // shouldn't be a match
String host3 = "ff.net"; // should be a match
ArrayList<String> alist = new ArrayList<String>();
for(String item : list.split("\\,"))
{
alist.add(item);
}
boolean contains_host1 = alist.stream().anyMatch(b -> b.equals(host1));
boolean contains_host2 = alist.stream().anyMatch(b -> b.equals(host2));
boolean contains_host3 = alist.stream().anyMatch(b -> b.equals(host3));
System.out.println(contains_host1);
System.out.println(contains_host2);
System.out.println(contains_host3);
控制台输出:
true
false
true
答案 4 :(得分:0)
试试这个:
String list = "aa.com,bb.com,cc.com,dd.net,ee.com,ff.net";
String host1 = "aa.com"; // should be a match
String host2 = "a.com"; // shouldn't be a match
String host3 = "ff.net" // should be a match
//For host1
Pattern p1 = Pattern.compile("\\b[A-Za-z]{2}.com");
Matcher m1 = p1.matcher(list);
if(m1.find()){
System.out.println(host1 + " matched");
}else{
System.out.println(host1 + " not matched");
}
//for host2
p1 = Pattern.compile("\\b[A-Za-z]{1}.com");
m1 = p1.matcher(list);
if(m1.find()){
System.out.println(host2 + " matched");
}else{
System.out.println(host2+"Not mached");
}
//and so on...
\ b表示单词边界(在这种情况下是单词的开头)。 [A-Za-z] {n} .com表示A-Z或a-z之间的字符n次,后跟.com