Because of the recent worldly travel restrictions, I recently found myself writing more code than usual. After having reviewed it, I noticed I was not very satisfied with it. I believe that comes from the fact that Java is an "old" language, but it has evolved a lot, especially in its latest versions. While working with a language for a long time, one is bound to get habits, whether good or bad. When the language changes, it takes a conscious effort to change those habits. Yet, this is necessary, because a good practice in one version of the language might become a bad one in another.
I started using version 1.3 - compared to old-timers, I feel like a newbie. However, that doesn’t change my point above about practices. In this short post, I’d like to first show the original code I wrote, and how I reworked it. It all starts with a stream.
persons.stream() .filter(person -> person instanceof Customer) .map(person -> (Customer) person) .map(Customer::getSalesRep);
While this code works - and is readable, it felt wrong to me. One part is functional, the other uses traditional operators. Using the latter and the former feels weird.
Actually, all operators used above have an equivalent API. Thus, the above code can easily be rewritten as:
persons.stream() .filter(Customer.class::isInstance) .map(Customer.class::cast) .map(Customer::getSalesRep);
Note that those are not new methods!
Class.isInstance() is available since version 1.1.
Class.cast() is available since version 1.5, which was released in 2004!
You might qualify the above code as Functional Programming… or not. Nonetheless, Java has made progress toward more functional code by providing APIs that allow developers to focus on the "what" instead of letting them handle the "how". If you start using streams, you should embrace the flow and start using modern APIs. And in all cases, it pays to learn about the latter.