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

4
Task
Java Core,  level 6lesson 5
Locked
join: at the right time in the right place
The join method is very useful and is often used to terminate a thread. Think about where and on what object you need to call this method to have the result displayed
18
Task
Java Core,  level 6lesson 5
Locked
Horse racing
Programming is better than gambling... Still, horse races and other races perfectly illustrate multithreading! Figure out what the code does, and implement a method that counts the number of horses that have crossed the finish line. One more thing: you need to wait for the longshots to finish the race.

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.


9
Task
Java Core,  level 6lesson 5
Locked
Promotion during political debates
Mr Chump is our candidate! And we'll help him a bit by making him give a speech, and then another, and then another during a political debate. We'll help him a little by making him talk until all the available time has been taken. Threads come to our rescue!

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();
4
Task
Java Core,  level 6lesson 5
Locked
Justice
Justice is the name of an ancient Terrian deity that no one ever saw in the flesh. That said, Justice is sometimes encountered in man-made systems. We've got some mice here. For some reason, one of the mice, the alpha male, eats first while the others wait. Figure out why and remove this method call.
9
Task
Java Core,  level 6lesson 5
Locked
Arranging calls to join()
First, the cat gives birth to kittens. Then all the kittens climb out of the basket in random order. Finally, the cat brings them back into the basket. These events for one cat may be interspersed with events for another cat. Now implement this scenario with join().