Я пытаюсь посмотреть, отображается ли указанное имя хоста в списке хостов в виде строки с разделителями-запятыми, например:
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 Я не хочу использовать решение, в котором вы разделяете список узлов в массиве и затем выполняете соответствующие настройки. Это было слишком медленно, потому что список хостов может быть довольно длинным. Regex apporoach может быть еще хуже, но я пытался заставить его работать в первую очередь.
Я также думаю, что регулярные выражения слишком медленны, если вы ищете точное соответствие, поэтому я попытался написать метод, который ищет вхождения имени хоста в списке и проверяет каждую подстроку, не является ли она частью более широкого имени хоста (например, "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
, contains
и endsWith
методов соответственно. Вот второй вариант, который я бы предпочел в вашем случае:
boolean containsHostShort(String list, String host) {
return list.contains("," + host + ",") || list.startsWith(host + ",") || list.endsWith("," + host);
}
UPD: комментарий ZouZou к вашему сообщению тоже кажется хорошим, я бы рекомендовал сравнить скорость в списке, подобном имеющимся в реальной ситуации, и выбрать самый быстрый.
Попробуй это:
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 означает символ между AZ или az n раз, за которым следует.com
Вы можете использовать лямбда для потока массива и вернуть 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
Как это упоминается в комментариях. Вы не должны использовать Matches
, как он пытается соответствовать шаблону регулярного выражения для всей строки, разделенных запятыми. Вы не пытаетесь это сделать. Вы пытаетесь определить, присутствует ли данная подстрока в исходной строке, разделенной запятой.
Для этого вы просто используете имя хоста в методе findall
. Однако вы можете просто использовать подстроку, которая не имела бы накладных расходов на компиляцию регулярных выражений.
Регулярные выражения используются для сопоставления строк, которые могут иметь изменения в сопоставленном шаблоне. Никогда не используйте регулярное выражение, если вы хотите выполнить точное сопоставление строк.
Это работает префектно, без регулярного выражения
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");
Едва ли принято 20-30 millsecs для выполнения цикла с 1 миллионом записей. В соответствии с вашим комментарием я только что отредактировал. Вы можете проверить это.
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));
HashSet
) для выполнения этой задачи.
matches()
соответствует всей строке, а не ее части. Вам придется либо разбить строку и сравнить с каждым элементом, либо использоватьPattern ...; Matcher ...;
,