Use Optionals as Streams

 class​ BackupJob {
 
  Communicator communicator;
  Storage storage;
 
 void​ backupToEarth() {
  Optional<Connection> connectionOptional =
  communicator.getConnectionToEarth();
»if​ (!connectionOptional.isPresent()) {
 throw​ ​new​ IllegalStateException();
  }
 
» Connection connection = connectionOptional.get();
 if​ (!connection.isFree()) {
 throw​ ​new​ IllegalStateException();
  }
 
  connection.send(storage.getBackup());
  }
 }

In the previous comparisons, we’ve shown that Optional can be a good replacement for null. But it’s not just that, and there’s a good reason why the class was added to lambda expressions in Java. An Optional is also a special kind of stream, one with either zero or exactly one element.

That means that you can directly apply all regular stream operations, such as filter() or map(), to an Optional. This makes for a good opportunity to write more concise code.

Take a look at the code above. It stores a (possibly absent) value in the variable named connectionOptional. That’s necessary, because we need to a) check if there’s an actual value by calling isPresent(), and b) retrieve that value by calling get(). But it doesn’t really make for a good or descriptive variable name.

The reason for storing the Optional in a variable and its awkward name lies in an impedance mismatch. Although this is barely visible in the code, the Optional class is made for the functional programming style, where the rest of the method follows an imperative style. When you switch between these styles, you have to use methods like get() to perform the switch. You can make the code much more readable just by avoiding this context switch.

You’ll find such switches very often in code in practice. The functional programming style is still very new for Java. Many developers aren’t yet familiar with it, or they have problems applying it fully. That’s why they often switch back to an imperative style, even when they started differently.

Check out how much you can improve the code by implementing everything functionally:

 class​ BackupJob {
 
  Communicator communicator;
  Storage storage;
 
 void​ backupToEarth() {
  Connection connection = communicator.getConnectionToEarth()
» .filter(Connection::isFree)
» .orElseThrow(IllegalStateException::​new​);
  connection.send(storage.getBackup());
  }
 }

It’s actually quite simple. Just use the arsenal of methods available in the Optional class: the intermediate operations filter(), map(), and flatMap(), and the terminal operations orElse(), orElseThrow(), orElseGet(), and ifPresent().

In the code above, we used filter() to check if the code is available and free and orElseThrow() to trigger the exception if it’s not. That makes for a drastic reduction of the amount of code. Just compare the code listings. In this case, less is more!

The code is way more concise now. And that’s not just because we got rid of the strange connectionOptional variable. The code also signals clearly what happens if the connection is absent or not free through the orElseThrow() operation. Before, this was distributed into two separate if conditions.

Other methods of Optional might be more appropriate in a different situation. For example, if you don’t really care about an absent value, you can just call ifPresent() instead. And if you’re only interested in reading from the Optional, you can transform it and provide a default value with .map().orElse(defaultValue).

The latter usage is quite common. Take a look at an example in the code below:

 String state = communicator.getConnectionToEarth()
  .map(Connection::isFree)
  .map(isFree -> isFree ? ​"free"​ : ​"busy"​)
  .orElse(​"absent"​);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.136.84