List<WebElement> cheeses = driver.findElements(By.className("cheese"));
findElements()
does not wait, but returns list of elements (located by locator). List is empty if nothing is found (reference).
Also, Selenium elders very strongly advise to use only explicit waits (no implicit). And especially warn about mixing implicit and explicit waits.
In my work experience (in Python), converting to pure explicit waits substantially increased the stability of the test (decreased flakiness).
In response to @dzieciou comment about style vs performance:
I always give priority to programmer's productivity, even if generated code will be 10% slower (compilers are getting ever better). Remember, the most important speed in programming is speed to the market.
If 90% of your computing time is spend in communication between your script and the browser, outside of your control and independent of the language you use, then it makes strong sense to use the language in which you are most productive (can write, debug and maintain most code per day).
If you use language in which you are twice as productive, even if such code will be half as slow as say C# code (and it would not be: OOP languages with dynamic dispatch are inherently slower than statically compiled, like C), it still does not matter: Something would take 110 sec instead of 100 sec (your code taking 20 sec instead of 10 sec, rest is spent in libraries and communication outside your control).
So you can deliver twice the value, and server running the test will spend extra 10% time running the tests. Nobody cares, and if: just buy faster server, they are cheap, compared to programmer's salary. If you can buy 10% faster server for 1 month salary, it pays for itself in 1 month. And after that all is just gravy, double your productivity for free.