15

I have an Array and want to perform some matching on it's element.

I came to know that it could be done in two ways in java 8 :

String[] alphabet = new String[]{"A", "B", "C"};

anyMatch :

Arrays.stream(alphabet).anyMatch("A"::equalsIgnoreCase);

findAny :

Arrays.stream(alphabet).filter("a"::equalsIgnoreCase)
        .findAny().orElse("No match found"));

As I can understand both are doing the same work. However, I could not found which one to prefer?

Could someone please make it clear what is the difference between both of them.

Mehraj Malik
  • 14,872
  • 15
  • 58
  • 85

2 Answers2

40

They do the same job internally, but their return value is different. Stream#anyMatch() returns a boolean while Stream#findAny() returns an object which matches the predicate.

Sanket Makani
  • 2,491
  • 2
  • 15
  • 23
Dariusz
  • 21,561
  • 9
  • 74
  • 114
  • 11
    They _almost_ do the same work. `anyMatch` is a short-circuit operation, but `filter` will always process the whole stream. – Jorn Vernee May 25 '17 at 11:48
  • 1
    @JornVernee are you entirely certain of that statement? As far as I remember streams are "lazy", which, for sequential streams, means that after encountering the first matching value in anyMatch it will be returned and the filter will not be processed further. – Dariusz May 25 '17 at 11:49
  • 1
    Hmm, I suppose you are right. At least it depends on the implementation. I'm going of the documentation here, where only `anyMatch` explicitly mentions that it's a short-circuit operation. – Jorn Vernee May 25 '17 at 11:54
  • 6
    @JornVernee findAny code : `if (!stop && predicate.test(t) == matchKind.stopOnPredicateMatches) { stop = true; ...` it is short-circuiting. – Eugene May 25 '17 at 11:54
  • 1
    @Eugene is that the JDK9 implementation? The `findAny` I have doesn't accept a predicate – Jorn Vernee May 25 '17 at 11:58
  • 2
    @JornVernee that's the third time this week! :( yes, it is jdk-9; that's the default I have. sorry – Eugene May 25 '17 at 11:59
  • 2
    @MehrajMalik Well, it's supposed to come out on [2017/07/27](http://openjdk.java.net/projects/jdk9/) That's not too long from now. – Jorn Vernee May 25 '17 at 12:04
  • @JornVernee I checked, take a look at https://stackoverflow.com/questions/44180155/is-stream-findany-a-short-circuit-operation – Dariusz May 25 '17 at 12:04
  • 2
    @JornVernee you might have some "substance" here. One is implemented via `FindOps` and the other via `MatchOps`. It could have been easily done so that `match` would call `find` and just return `isPresent` on the resulting `Optional`. I just know I will not be able to sleep normally until I understand why... – Eugene May 25 '17 at 15:01
  • Another example how Java lambdas are very inconsistent and confusing in their syntax. Instead of `anyMatch` they should have added `exists()` without predicate. So streams become reusable and always follow same pattern. Would be so easy intuitive with `stream.filter().exists()` instead. All part till filter is reusable for example in a DAO first check with same stream exists any and then load a paginated resultset. – djmj Aug 06 '22 at 20:49
4

There are more than two ways in Java 8

String[] alphabet = new String[]{"A", "B", "C"};

The difference is in the type of the return value:

  1. Stream#findAny():

    Returns an Optional describing some element of the stream, or an empty Optional if the stream is empty.

    String result1 = Arrays.stream(alphabet)
            .filter("a"::equalsIgnoreCase)
            .findAny()
            .orElse("none match");
    
  2. Stream#findFirst()

    Returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty. If the stream has no encounter order, then any element may be returned.

    String result2 = Arrays.stream(alphabet)
            .filter("a"::equalsIgnoreCase)
            .findFirst()
            .orElse("none match");
    
  3. Stream#count()

    Returns the count of elements in this stream. This is a special case of a reduction and is equivalent to:

    return mapToLong(e -> 1L).sum();
    
    boolean result3 = Arrays.stream(alphabet)
            .filter("a"::equalsIgnoreCase)
            .count() > 0;
    
  4. Stream#anyMatch(Predicate)

    Returns whether any elements of this stream match the provided Predicate. May not evaluate the predicate on all elements if not necessary for determining the result. If the stream is empty then false is returned and the predicate is not evaluated.

    boolean result4 = Arrays.stream(alphabet)
            .anyMatch("a"::equalsIgnoreCase);
    
  5. Stream#allMatch(Predicate)

    Returns whether all elements of this stream match the provided Predicate. May not evaluate the predicate on all elements if not necessary for determining the result. If the stream is empty then true is returned and the predicate is not evaluated.

    boolean result5 = Arrays.stream(alphabet)
            .allMatch("a"::equalsIgnoreCase);