1

I understand from Java Pattern Matcher: create new or reset? that it's best to reuse a Matcher if I'm in a single-threaded context.

So let's say I have a stream of paths using File.list(basePath) and I want to filter them based upon matching their filenames against a regex. It seems I should use matcher.reset(filename) for each path filename in the stream. Wonderful.

But how do I initialize the Matcher so that I can reuse it, without first creating it and matching against something? Because I don't know what the first "something" will be—I won't even know if there will be a "something" (e.g. a file in some directory).

So do I do this to kick things off?

final Matcher filenamePatternMatcher=filenamePattern.matcher("");

That seems cumbersome and wasteful. But if I set filenamePatternMatcher to null, I'll have to do needless checks processing the individual files, like:

if((filenamePatternMatcher!=null
    ? filenamePatternMatcher.reset(filename)
    : filenamePattern.matcher(filename)).matches) {…}

Besides, I can't even do that within a Stream<Path>, because the matcher must be effectively final.

So what's an elegant way to create a matcher that will later match against strings using Matcher.reset()? Did the Java API creators not think of this use case?

Garret Wilson
  • 18,219
  • 30
  • 144
  • 272

1 Answers1

0

I did a few timings on some file name matching I do frequently, and calling Matcher.reset(String) improves the matching speed by ~20% / cuts down memory used.

Fortunately Matcher.reset() returns this to make it easy to reference within a stream filter, and although it appears a little wasteful to setup a blank matcher before use, it is worth the effort to change from:

stream.filter(s -> pattern.matcher(s).matches())

... to have extra line to initialise the Matcher:

Matcher matcher = pattern.matcher("");
stream.filter(s -> matcher.reset(s).matches())
DuncG
  • 12,137
  • 2
  • 21
  • 33