CodeGym /Courses /Java Syntax Zero /Working with streams, part 3

Working with streams, part 3

Java Syntax Zero
Level 19 , Lesson 6
Available

1. Checking

I think you might already be bored with learning how to chain together data streams. You want to finally do something with the data.

The Stream class has three standard methods that do not construct streams, but instead check what kind of data is in them. These methods are: anyMatch(), allMatch(), and noneMatch().

boolean anyMatch(rule) method

This method checks whether the stream has at least one element that satisfies the rule that is passed to the method. If there is such an element, the method returns true, otherwise false.

Examples

Code Note
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.anyMatch(x -> x > 0);

true
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.anyMatch(x -> x > 0);

true
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).anyMatch(x -> x > 0);

false

In the last example, we first retain only the elements that are less than zero, and then we check the result to see whether any of filtered elements is greater than zero. Of course, such elements are no longer there.

boolean allMatch(rule) method

This method checks whether all elements in the stream match the rule (also known as a predicate). The rule is passed as an argument to the method:

Code Note
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.allMatch(x -> x > 0);
true
(all elements greater than zero)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.allMatch(x -> x > 0);
false
(are there elements less than or equal to zero?)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).allMatch(x -> x < 0);
true
(we retained the elements that are less than zero)

In the last example, we first allow only elements that are less than zero to pass through the filter, and then we check whether all the retained elements are less than zero. The check yields a positive result.

boolean noneMatch(rule) method

The noneMatch() method checks whether the stream has no elements that match the passed rule. It is like the opposite of the anyMatch() method.

Code Note
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.noneMatch(x -> x > 0);

false
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.noneMatch(x -> x > 0);

false
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).noneMatch(x -> x > 0);

true


2. Utility classes: Optional class

Sometimes it is very inconvenient for programmers to work with null references. For example, suppose you are comparing two strings. If both variables are not null, then you can simply call s1.equals(s2), and everything will work. But if s1 could be null, then you have to write code that handles this situation in order to avoid a NullPointerException.

That's why programmers came up with the Optional<T> utility class. Its code looks roughly like this:

Code Note
class Optional<Type>
{
   private final Type value;
   private Optional() { this.value = null;}
   private Optional(value) { this.value = value;}
   public static <Type> Optional<Type> of(Type value)
   {
      return new Optional<Type>(value);
   }

   public boolean isPresent()
   {
      return value != null;
   }

   public boolean isEmpty()
   {
      return value == null;
   }

   public Type get()
   {
      if (value == null)
      {
         throw new NoSuchElementException();
      }
      return value;
   }

   public Type orElse(Type other)
   {
      return value != null ? value : other;
   }

   public Type orElseThrow()
   {
      if (value == null)
      {
         throw new NoSuchElementException();
      }
      return value;
   }
}










Checks whether the value is not null



Checks whether the value is null




Returns the stored value. Throws an exception if the value is null.







Returns the stored non-null value. Or if the stored value is null, then returns the value passed in as a method argument



Returns the stored non-null value or throws an exception if the value is null.

The purpose of this class is simply to store a T object (a reference to an object whose type is T). The object reference inside an Optional<T> object can be null.

This class lets programmers write slightly prettier code. Let's compare:

Using Optional Not using Optional
public void printString(String s)
{
   Optional<String> str = Optional.ofNullable(s);
   System.out.println(str.orElse(""));
}
public void printString(String s)
{
   String str = s != null ? s : "";
   System.out.println(str)
}

One Optional object can always be compared to another Optional object using the equals method, even if they store null references.

Simply speaking, the Optional class lets you write "beautiful" checks for null and "beautiful" actions in the event that an Optional object stores a null value.



3. Finding elements

Let's return to the Stream class. The Stream class has 4 more methods that let you search for elements in a stream. These methods are findFirst(), findAny(), min(), and max().

Optional<T> findFirst() method

The findFirst() method simply returns the first element in the stream. That's all it does.

The more interesting thing to note here is that the method does not return a T object, but rather an Optional<T> wrapper object. This ensures that the method will never return null after failing to find an object.

Example:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
String str = list.stream().findFirst().get(); // Hello

For greater clarify, let's break the last line into several lines:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");

Stream<String> stream = list.stream();
Optional<String> result = stream.findFirst();
String str = result.get(); // Hello

The last get() method is simply retrieves the value stored inside the Optional object.

Optional<T> findAny() method

The findAny() method returns any element from the stream and ends there. This method is similar to findFirst(), but it is great for streams used in parallel operations.

When processing streams in parallel, it may be an element has already been found in some part of a stream, but it is not yet clear whether it is the first or not.

If many elements have matched all the filters, and it is important for the programmer to get exactly the first of them, then the findFirst() method is what should be called. If the programmer knows that in reality 0 or 1 element will match all the filters, then it is enough to simply call findAny() — and this will be faster.

Optional<T> min(Comparator<T>) method

The min() method uses a comparator object to compare all elements in the stream and returns the minimum element. The most convenient way to define a comparator object is with a lambda function.

Example of searching for the shortest string:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
String min = list.stream().min( (s1, s2)-> s1.length()-s2.length() ).get();

Optional<T> max(Comparator<T>) method

The max() method uses a comparator object to compare all elements in the stream and returns the maximum element. The most convenient way to define a comparator object is with a lambda function.

Example of searching for the longest string:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
String max = list.stream().max( (s1, s2)-> s1.length()-s2.length() ).get();
Comments (2)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Alex Tor Level 31, Bulgaria
30 October 2022
The getMostExpensiveCar(Stream<Car>) method looks for the most expensive car in a list; The getMoreExpensiveCar(Stream<Car>, Car) method searches another list for a car that is more expensive than the one passed to the getMostExpensiveCar(Stream<Car>) method. BOOM, my computer just blew up due to outdated drivers of Logic 🤣
Music Lord Level 33, Czech Republic
29 September 2022
The printList(List<String>) method should not use loops, an if-else statement, or a ternary operator. BOOM using foreach loop to print each string...