As I write, there are two great answers which do it in one regex.
I want to suggest that unless you're optimising for performance (and remember, premature optimisation is bad, m'kay?) it's worth splitting into more, simpler, regexs, and using language features for readability.
Not that complex regex's are always efficient anyway -- it's easy to accidentally write a regex that backtracks all over the place.
It's also kind to readers of your code who may be unfamiliar with the more exotic features of whatever regex dialect you have.
boolean isMatch(String s) {
// First pass test
Pattern basicPattern = Pattern.compile("\bMary\b.*\bare\b");
// ... and a test for exclusions
String rejectRE = "\bMary\b.*\bBob\b.*\bare\b";
Matcher m = basicPattern.matcher(s);
while(m.find()) {
// We have a candidate match
if(! m.group().matches(rejectRE)) {
// and it passed the secondary test
return true;
}
}
// we fell through
return false;
}