0

i have several String patterns:

ArrayList<String> tmp = new ArrayList<String>();
tmp.add("INFO");
tmp.add("Error");
tmp.add("Debug");
tmp.add("Failed");
tmp.add("Unable");

also i am checking the every lines in the file whether lines are matched with any one of the string pattern.if matched,i will display the line.my code is,

for (String pattern : tmp) {
    if (line.contains(pattern)) {
    System.out.println(line);
    }
}

Now the problem is,if line match with more than one string pattern,line gets displayed by every time whenever gets matched.

i want to display the line by only one time(need to check any of the string patterns are matched with line).How to do this.

1
  • If you know the exakt strings you are gonne match against I suggest that you use a Enum to represent your strings. That will make it easier for you to add/delete/update your log strings and it will be easier to access them from other places in your code. Commented Jun 18, 2011 at 12:10

2 Answers 2

4

just put a break in there:

for (String pattern : tmp) {
 if (line.contains(pattern)) {
   System.out.println(line);
   break;
  }
}

Also, please properly format your code (indent it with 4 spaces), as it makes it easier to read.

Sign up to request clarification or add additional context in comments.

2 Comments

I though about suggesting this. Obviously it is an improvement, but there are still potentially n checks per line (n being the number of patterns).
Indeed, I thought about suggesting regex! Of course, the regex still has to do upto n checks per line under the hood, but I've no idea which would be faster. Both solutions are worth knowing, and I'd say regex is the better solution for this particular problem (since it's more readable), but I used break because the OP doesn't seem to know about it, and that's more fundamental.
2

Use a regular expression:

Pattern pattern = Pattern.compile("INFO|Error|Debug|Failed|Unable");
for(String line : lines){
    if(pattern.matcher(line).find()){
        System.out.println(line);
    }
}

This will print every line that contains one or more of the supplied keywords.

See the Regular Expression Tutorial for more info.

Also, you could further improve this if you let the regex engine do the line splitting instead of passing individual lines:

Pattern pattern = Pattern.compile("^.*(?:INFO|Error|Debug|Failed|Unable).*$",
                                  Pattern.MULTILINE);
Matcher matcher = pattern.matcher(theWholeSourceText);
while(matcher.find()){
    System.out.println(matcher.group());
}

Update: Ok, if the pattern is dynamic you can just build it dynamically from your list:

StringBuilder sb = new StringBuilder();
sb.append("^.*(?:");
Iterator<String> it = patternsList.iterator();
if(it.hasNext())sb.append(it.next());
while(it.hasNext())sb.append('|').append(it.next());
sb.append(").*$");
Matcher matcher = Pattern.compile(sb.toString(), Pattern.MULTILINE)
                         .matcher(theWholeSourceText);
while(matcher.find()){
    System.out.println(matcher.group());
}

2 Comments

patric "but "INFO|Error|Debug|Failed|Unable" these values are dynamically changed. if these values are constant we can do like this. but these all are dynamic.how to do for dynamic.
@ssbecse I added an update to create a pattern from the list. if you need dynamic pattern changes while searching, things get more complicated, because you have to create a new Matcher when the pattern has changed and initialize it's start point to the old end point. I'd say that's where it gets too complicated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.