Truncating a Stream – Streams
Truncating a Stream
The limit() operation returns an output stream whose maximum size is equal to the max size specified as an argument to the method. The input stream is only truncated if its size is greater than the specified max size.
In Figure 16.6, Query 4 creates a list with the first two CDs that were released in 2018. The stream pipeline uses a filter() operation first to select CDs released in 2018, and the limit() operation truncates the stream, if necessary, so that, at most, only two CDs are passed to its output stream. The short-circuit execution of this stream pipeline is illustrated in Figure 16.6, showing the resulting list containing two CDs (cd2, cd3). The execution of the stream pipeline terminates after the limit() operation has reached its limit if there are no more elements left to process. In Figure 16.6, we can see that the limit was reached and execution was terminated. Regardless of the fact that the last element in the initial stream was not processed, the stream cannot be reused once the execution of the pipeline terminates due to a short-circuiting operation.
Figure 16.6 Truncating a Stream
The limit() operation is ideal for turning an infinite stream into a finite stream. Numerous examples of using the limit() operation with the iterate() and generate() methods can be found in §16.4, p. 894, and with the Random.ints() method in §16.4, p. 900.
For a given value n, limit(n) and skip(n) are complementary operations on a stream, as limit(n) comprises the first n elements of the stream and skip(n) comprises the remaining elements in the stream. In the code below, the resultList from processing the resulting stream from concatenating the two substreams is equal to the stream source CD.cdList.
List<CD> resultList = Stream
.concat(CD.cdList.stream().limit(2), CD.cdList.stream().skip(2))
.toList();
System.out.println(CD.cdList.equals(resultList)); // true
The skip() operation can be used in conjunction with the limit() operation to process a substream of a stream, where the skip() operation can be used to skip to the start of the substream and the limit() operation to limit the size of the substream. The substream in the code below starts at the second element and comprises the next three elements in the stream.
List<CD> substream = CD.cdList
.stream()
.skip(1)
.limit(3)
.toList();
System.out.println(“Query 5: ” + substream);
// Query 5: [<Jaav, “Java Jam”, 6, 2017, JAZZ>,
// <Funkies, “Lambda Dancing”, 10, 2018, POP>,
// <Genericos, “Keep on Erasing”, 8, 2018, JAZZ>]
The limit() operation is a short-circuiting stateful intermediate operation, as it needs to keep state for tracking the number of elements in the output stream. It changes the stream size, but not the stream element type or the encounter order. For an ordered stream, we can expect the elements in the resulting stream to have the same order, but we cannot assume any order if the input stream is unordered.
Example 16.5 contains the code snippets presented in this subsection.
Example 16.5 Filtering
import java.time.Year;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
public final class Filtering {
public static void main(String[] args) {
// Query 1: Find CDs whose titles are in the set of popular CD titles.
Set<String> popularTitles = Set.of(“Java Jive”, “Java Jazz”, “Java Jam”);
// Using Stream.filter().
List<CD> popularCDs1 = CD.cdList
.stream()
.filter(cd -> popularTitles.contains(cd.title()))
.toList();
System.out.println(“Query 1a: ” + popularCDs1);
// Using Collection.removeIf().
List<CD> popularCDs2 = new ArrayList<>(CD.cdList);
popularCDs2.removeIf(cd -> !(popularTitles.contains(cd.title())));
System.out.println(“Query 1b: ” + popularCDs2);
// Query 2: Create a list of unique CDs with pop music.
List<CD> miscCDList = List.of(CD.cd0, CD.cd0, CD.cd1, CD.cd0);
List<CD> uniquePopCDs1 = miscCDList
.stream()
.filter(CD::isPop)
.distinct() // distinct() after filter()
.toList();
System.out.println(“Query 2: ” + uniquePopCDs1);
// Query 3a: Create a list of jazz CDs, after skipping the first two CDs.
List<CD> jazzCDs1 = CD.cdList
.stream()
.skip(2) // skip() before filter().
.filter(CD::isJazz)
.toList();
System.out.println(“Query 3a: ” + jazzCDs1);
// Query 3b: Create a list of jazz CDs, but skip the first two jazz CDs.
List<CD> jazzCDs2 = CD.cdList // Not equivalent to Query 3
.stream()
.filter(CD::isJazz)
.skip(2) // skip() after filter().
.toList();
System.out.println(“Query 3b: ” + jazzCDs2);
// Query 4: Create a list with the first 2 CDs that were released in 2018.
List<CD> twoFirstCDs2018 = CD.cdList
.stream()
.filter(cd -> cd.year().equals(Year.of(2018)))
.limit(2)
.toList();
System.out.println(“Query 4: ” + twoFirstCDs2018);
// limit(n) and skip(n) are complementary.
List<CD> resultList = Stream
.concat(CD.cdList.stream().limit(2), CD.cdList.stream().skip(2))
.toList();
System.out.println(CD.cdList.equals(resultList));
// Query 5: Process a substream by skipping 1 and limiting the size to 3.
List<CD> substream = CD.cdList
.stream()
.skip(1)
.limit(3)
.toList();
System.out.println(“Query 5: ” + substream);
}
}
Output from the program (formatted to fit on the page):
Query 1a: [<Jaav, “Java Jive”, 8, 2017, POP>, <Jaav, “Java Jam”, 6, 2017, JAZZ>]
Query 1b: [<Jaav, “Java Jive”, 8, 2017, POP>, <Jaav, “Java Jam”, 6, 2017, JAZZ>]
Query 2: [<Jaav, “Java Jive”, 8, 2017, POP>]
Query 3a: [<Genericos, “Keep on Erasing”, 8, 2018, JAZZ>,
<Genericos, “Hot Generics”, 10, 2018, JAZZ>]
Query 3b: [<Genericos, “Hot Generics”, 10, 2018, JAZZ>]
Query 4: [<Funkies, “Lambda Dancing”, 10, 2018, POP>,
<Genericos, “Keep on Erasing”, 8, 2018, JAZZ>]
true
Query 5: [<Jaav, “Java Jam”, 6, 2017, JAZZ>,
<Funkies, “Lambda Dancing”, 10, 2018, POP>,
<Genericos, “Keep on Erasing”, 8, 2018, JAZZ>]
Archives
- July 2024
- June 2024
- May 2024
- March 2024
- February 2024
- January 2024
- December 2023
- October 2023
- September 2023
- May 2023
- March 2023
- January 2023
- December 2022
- November 2022
- October 2022
- September 2022
- August 2022
- July 2022
- April 2022
- March 2022
- November 2021
- October 2021
- September 2021
- July 2021
- June 2021
- March 2021
- February 2021
Calendar
M | T | W | T | F | S | S |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |