Java. The concept of final and intermediate operations.

The concept of final and intermediate operations. Examples. Methods stream(), parallelStream()


Contents


Search other websites:




1. Final and intermediate operations. Definition

Under operation involves calling a method that handles stream. When processing a stream, the concepts of a final operation and an intermediate operation arise. If the term “final operation” is described in the definition of a method, it means that the entire stream has been revised (processed) from beginning to end and the final result has been obtained. After that, this stream is considered consumed and cannot be reused. If you try to process the consumed stream after the final operation (method) has been completed, the system will generate an exception.
If an “intermediate operation” is specified in the description of an operation (method), it means that a new data stream is created (produced), which can be further processed in a pipeline mode. The pipeline mode provides for the further use of intermediate or final operations on the newly created stream. In this case, the final operation is called last.

 

2. Final operation. Example

The example demonstrates the use of final operations.

Task. Calculate the minimum and maximum values in a set of random numbers of type Double.

The demo program is as follows.

import java.util.ArrayList;
import java.util.Optional;
import java.util.stream.*;

public class StreamAPI {

  public static void main(String[] args) {
    // Convert a stream of numbers to a Double[] array
    // 1. Declare a set of numbers as a collection
    ArrayList<Double> AL = new ArrayList<Double>();

    // 2. Fill a set of numbers with random values
    for (int i=0; i<10; i++)
      AL.add((Math.random()*10));

    // 3. Create a stream of numbers
    Stream<Double> stream = AL.stream();

    // 4. Find the maximum value in an array
    Optional<Double> max = stream.max(Double::compare);
    System.out.println("max = " + max.get());

    // 5. Attempt to call another operation - search for the minimum
    stream = AL.stream(); // Be sure to create a new stream
    Optional<Double> min = stream.min(Double::compare);
    System.out.println("min = " + min.get());
  }
}

The above code first searches for the maximum, then searches for the minimum. Maximum search operation

stream.max (Double::compare);

is the final. This means that after its execution, the stream is considered consumed.

The consumed stream cannot be processed further. If, after searching for the maximum, remove the line

stream = AL.stream ();

then after running for execution, the program will throw an IllegalStateException exception.

The result of the program

max = 8.627680677435304
min = 1.4456409633880085

 

3. Intermediate operation. Example

The example demonstrates performing an intermediate operation that sorts a stream of numbers in descending order.

import java.util.*;
import java.util.function.*;
import java.util.stream.*;

public class StreamAPI {

  public static void main(String[] args) {
    // Sorting a stream of numbers in descending order of values
    // 1. Create a set of numbers
    ArrayList<Integer> AL = new ArrayList<Integer>();
    for (int i=0; i<10; i++)
      AL.add((int)(Math.random()*10));
    System.out.println("AL = " + AL);

    // 2. Create a stream of numbers based on the AL collection
    Stream<Integer> stream = AL.stream();

    // 3. Call an intermediate sort operation - a new stream is created
    // 3.1. Create comparison method
    Comparator<Integer> comparator = (a, b) -> b-a;

    // 3.2. Create a new sorted stream is an intermediate operation,
    // after which the stream can be processed further
    Stream<Integer> sortStream = stream.sorted(comparator);

    // 3.3. Output a new stream
    System.out.print("sorted AL = ");

    // 3.3.1. Create an action that displays a stream item on the screen
    Consumer<Integer> action;

    action = (n) -> {
      System.out.print(n + " ");
    };

    // Pass the action to the forEach() method for elementwise processing
    sortStream.forEach(action); // forEach() - final operation
  }
}

The above code creates a stream of numbers stream from the AL collection. The resulting stream is sorted by an intermediate sorted() operation. The sorted() method creates a new sorted stream

Stream<Integer> sortStream = stream.sorted(comparator);

Since sorted() is an intermediate operation, the new stream can be processed further. In our case, the entire stream is outputted element by element using the forEach() method as shown below

sortStream.forEach(action); // forEach() - final operation

The forEach() method is the final operation. This means that the sortStream has been consumed. To reuse the stream, it needs to be restored from its source – a set of AL numbers.

After execution, the program will give the following result

AL = [5, 4, 0, 5, 2, 9, 1, 3, 0, 2]
sorted AL = 9 5 5 4 3 2 2 1 0 0

 

4. Formation of new data streams using a conveyer. Example

Task. A stream of numbers is given. Find the minimum number of the stream numbers that are greater than 5 and less than 20.

Solution. To solve the problem, you need to use a conveyer approach to modify the stream. Using two operations (methods):

  • operation (method) filter() – intermediate operation;
  • operation (method) min() – final operation.

The text of the solution to the problem is as follows

import java.util.*;
import java.util.function.*;
import java.util.stream.*;

public class StreamAPI {

  public static void main(String[] args) {

    // Task. A stream of numbers is given. Find the minimum
    // number of the stream numbers that are greater than 5 and less than 20.
    // 1. Create a set of numbers
    ArrayList<Integer> AL = new ArrayList<Integer>();

    AL.add(15);
    AL.add(13);
    AL.add(7);
    AL.add(1);
    AL.add(23);
    AL.add(6);
    AL.add(3);
    AL.add(11);
    AL.add(22);
    AL.add(2);

    // 2. Create a stream of numbers based on the AL collection
    Stream<Integer> stream = AL.stream();
    System.out.println("AL = " + AL);

    // 3. Call an intermediate filtering operation - a new stream is created
    // 3.1. Create comparison method - numbers greater than 5
    Predicate<Integer> predicate = (a) -> a>5; // condition

    // 3.2. Create a new filtered stream
    // after which the stream can be processed further
    Stream<Integer> filteredStream = stream.filter(predicate);

    // 4. Call another intermediate filtering operation - a new stream is created
    // This time, numbers that are less than 20 are filtered.
    predicate = (a) -> a<20;

    // 5. Filter the same stream again
    filteredStream = filteredStream.filter(predicate); // this is again an intermediate operation

    // 6. Find the minimum value in the newly created stream
    Optional<Integer> min = filteredStream.min(Integer::compare); // this is final operation

    // 7. Display the minimum value on the screen
    System.out.println("min = " + min.get());
  }
}

After execution, the program will give the following result

AL = [15, 13, 7, 1, 23, 6, 3, 11, 22, 2]
min = 6

 

5. Examples of receiving (opening) a data stream. Methods stream(), parallelStream()

The example implements obtaining a data stream for various types of collections. The stream() method is used to get a sequential stream. The parallelStream() method is used to get a parallel stream.

import java.util.*;
import java.util.stream.*;

public class StreamAPI {

  public static void main(String[] args) {

    // Task. A set of numbers is given. Create a stream from this set
    // 1. Create a data stream from a collection of type ArrayList<T>
    // 1.1. Create a collection of numbers
    ArrayList<Integer> AL = new ArrayList<Integer>();

    AL.add(15); AL.add(13); AL.add(7); AL.add(1); AL.add(23);
    AL.add(6); AL.add(3); AL.add(11); AL.add(22); AL.add(2);

    // 1.2. Create sequential data stream based on AL collection
    Stream<Integer> stream = AL.stream();

    // 1.3. Create parallel data stream from AL collection
    Stream<Integer> parallelStream = AL.parallelStream();

    // 2. Create data stream from the array of integers
    int[] AI = { 2, 5, 4, 8, -1, 3, 9 };
    IntStream streamInt = Arrays.stream(AI); // sequential stream
    IntStream parallelStreamInt = streamInt.parallel(); // parallel stream

    // 3. Create data stream from the array of real numbers
    double[] AD = { 0.5, -1.8, 3.77, 4.23, 21.7, -10.8 };
    DoubleStream streamDouble = Arrays.stream(AD); // sequential stream to a given
    DoubleStream parallelStreamDouble = streamDouble.parallel(); // parallel stream

    // 4. Create a stream of data from the array of type long
    Long[] ALong = { 282039l, 3239290l, 23902309l, 72083289L };
    Stream<Long> streamLong = Arrays.stream(ALong); // sequential stream
    Stream<Long> parallelStreamLong = streamLong.parallel(); // parallel stream
  }
}

 


Related topics