evan
evan

Reputation: 431

How to convert a for-loop to find the first occurrence to Java streams?

I have the following code that is functionally working

for (UniversityClass class : allClasses)
    {
        Period<Date> classDate = class.getClassDates();
        if (classDate.start().before(classEndDate)
                && classDate.end().after(classBeginDate))
        {
            classBooked = true;
            break;
        }
    }

I have tried this:

allClasses.stream().filter(class -> {
            Period<Date> classDate = class.getClassDates();
            if (classDate.start().before(classEndDate)
                && classDate.end().after(classBeginDate))

            return true;
        }).findFirst().ifPresent($ -> {
            classBooked = true;
        });

But this throws to add a return statement. Also, the classBooked variable needs to be declared final, but that cannot be done. What is the mistake being done?

Also, once true, I need to break from it. that is why I thought of adding findFirst().ifPresent()

Upvotes: 14

Views: 460

Answers (3)

Konrad Rudolph
Konrad Rudolph

Reputation: 545588

To fix the specific problems in your code, your lambda always needs to return a value, and the ifPresent needs to be changed to isPresent:

final boolean classBooked = allClasses.stream()
        .filter(c -> {
            final Period<Date> classDate = c.getClassDates();
            return classDate.start().before(classEndDate)
                && classDate.end().after(classBeginDate)
        })
        .findFirst().isPresent();

However, anyMatch, as shown in the other answers, is a better solution.

Upvotes: 8

Hadi
Hadi

Reputation: 17289

you can do:

allClasses.stream()
          .anyMatch(uc-> (uc.getClassDates().start().before(classEndDate)
                              && uc.getClassDates().end().after(classBeginDate)));

Upvotes: 6

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36401

You can use anyMatch in place of filter, findFirst:

classBooked = allClasses.stream()
                        .anyMatch(c -> {
                            Period<Date> classDate = c.getClassDates();
                            return (classDate.start().before(classEndDate) && classDate.end().after(classBeginDate));
                        });

You may also use map to be slightly more readable:

classBooked = allClasses.stream()
                        .map(UniversityClass::getClassDates)
                        .anyMatch(d -> d.start().before(classEndDate) && d.end().after(classBeginDate));

Upvotes: 8

Related Questions