SoFunction
Updated on 2025-03-08

Basic concepts and creation methods of Java Stream

Preface

I believe that many people (including myself) have used JDK 1.8 for a long time, but have never used the powerful new feature of Stream, which has been added since 1.8. This article will start with how to create a Stream and gradually learn how to use Stream. This article will not involve operations on data in streams, but will only discuss several methods of creating streams and some basic concepts. The practical operations on streams will be introduced one by one in subsequent articles.

The difference between Stream and Collection

1. Different uses and concerns

Collection mainly focuses on the storage of objects, through the use ofList MapSetetc. to allow the data to be better organized for easy use. Stream focuses on the operation of objects, includingreducemapfilterAnd practical operations.

2. Stream is lazy search (Laziness-seeking)

Let’s take a look at an example first and consider the code:

Random random = new Random(29);
()
   .filter(v -> v > 5 && v < 31)
   .limit(3)
   .forEach(::println);

// output:
//  21
//  22
//  28

The code first creates a random integer stream, then filters the numbers in the range (5, 31), and finally gets 3 numbers and outputs. The stream created here is the infinite stream mentioned in 3. During the execution process, the stream will be added to the result sequence once it obtains an integer that satisfies the condition, and starts the next round of search until 3 satisfying integers are found. The stream will only complete the given task (find 3 integers that meet the specified range and output them), and there will be no additional operations.

3. The size of the stream can be infinite

Although the data volume of the Collection can also be expanded and changed dynamically, since the computer memory is limited, the data volume size can always be regarded as only a finite size. But Stream is different, since streams are lazy to load, so when usinglimitIn a similar short circuit operation, an infinite current can be received using the reasons of feature 2.

4. There are no side effects on flow operations

Unlike some operations in Collection, such as removing the elements in the collection, the stream will not modify the data in the original collection of the generated stream. For example, when using filter, a new stream filtered by the element will be generated, without modifying the data in the original collection.

5. The flow is a consumable

Unlike Collection, there is no limit on the number of accesses and usage. A stream can only be executed once in its life cycle. After the terminal operation is executed (terminal operation will be introduced in a later article), even if the stream is not closed, such as forEach in the above code, it cannot be accessed again (similar to iterator). As shown in the following code, if you want to operate again, you must recreate a stream.

IntStream stream = new Random(29).ints();
(v -&gt; v &gt; 5 &amp;&amp; v &lt; 31)
   .limit(3)
   .forEach(::println);
// When the terminal operation is executed and then used, an exception message will appear// : stream has already been operated upon or closed
(::println);

Create a stream

Streams can be created in many ways, and the following is introduced one by one:

How family creation

For classes that implement the Collection interface, you can create corresponding streams through stream() and parallelStream(), as shown in the following code:

List&lt;Integer&gt; list = new ArrayList&lt;&gt;((1, 2, 3, 4, 5));
// Create a normal streamStream&lt;Integer&gt; stream = ();
// Create a parallel streamStream&lt;Integer&gt; parallelStream = ();

2. How to create an array family

For array type elements, you can use Arrays classstream()Create a corresponding stream, if you want to obtain parallel streams, you need to use itparallel()The method is as follows:

IntStream stream = (new int[]{1, 2, 3});
// Generate parallel streams corresponding to the streamIntStream parallelStream = ();

Family factory method

There are many ways to create streams through factory methods, and you canemptyofconcatgenerateiteraterangerangeClosedas well asbuilderCreate a stream with other methods, the following is a code example:

// Generate a stream that does not contain any elementsStream&lt;Object&gt; stream1 = ();

// Stream generated by the given elementStream&lt;Integer&gt; stream2 = (1, 2, 3);

// Merge two streams to generate a new streamStream&lt;Object&gt; stream3 = (stream1, stream2);

// Create an <infinite stream>, where the data in the stream is generated by calling the passed functionStream&lt;Double&gt; stream4 = (Math::random);

// Create an <infinite stream>, the data in the stream is from the first parameter,// The first parameter is called as a function parameter and continuously// The value obtained by the function call is composed of continuous call as a parameter.// For example, the following will generate an integer stream of 1, 2, 3...Stream&lt;Integer&gt; stream5 = (1, v -&gt; v + 1);

// Create an integer stream consisting of ranges [1, 5)IntStream stream6 = (1, 5);

// Create an integer stream consisting of ranges [1, 5]IntStream stream7 = (1, 5);

// Create a stream through the builder mode of the stream&lt;Integer&gt; builder = ();
for (int i = 0; i &lt; 10; i++) {
  // Both add and accept methods can add elements to the stream  // The difference is that add has no return value, accept will return this object of the current builder  // The underlying add method is also called accept and then returns this  // Therefore, chain calls can be made for the add method  (i);
  (i);
}
Stream&lt;Integer&gt; stream8 = ();

/Methods in the NIO family

Except for two acquisitionslinesThe generated flow is rarely used in several other ways, so just understand this part.

try {
  String dir = ("");
  // Both of the following methods are to obtain streams composed of row data in the file  Stream&lt;String&gt; stream1 = new BufferedReader(new FileReader(dir + "\\")).lines();
  Stream&lt;String&gt; stream2 = ((dir + "\\"));
  // Get the stream composed of paths of all files/folders under the specified path  Stream&lt;Path&gt; stream3 = (("d:\\temp"));
  // Get the stream composed of all files/folders under the specified path and within the specified deepest file level (here is 2) that meet the function conditions  Stream&lt;Path&gt; stream4 = (
    ("d:\\temp"), 1, (path, basicFileAttributes) -&gt; ());
  // Get the stream composed of all files/folders under the specified path and within the specified deepest file level (here is 2)  Stream&lt;Path&gt; stream5 = (("d:\\temp"), 2);
} catch (IOException e) {
  ();
}

How to get streams

Since the Random class is used directly to generate a random number infinite stream, which are all streams composed of basic data types, it is usually necessary to use itboxedMethods are packed (formerly, any generatedIntStreamDoubleStreamLongStreamAll are the same) so that more rich features can be used.

Random random = new Random();
// The following three methods are all obtained from <infinite flow> composed of random numbersIntStream stream1 = ();
DoubleStream stream2 = ();
LongStream stream3 = ();
Stream&lt;Integer&gt; boxedStream = ();

Let’s give a specific practical example first. In the subsequent article, we will introduce some practical operations in detail. Here we can learn about it first:

// Sort array elements in reverse order// If boxed is not performed, you can only use the default ascending sorting method// By packing, you can use custom comparators to achieve more diverse sortingint[] arr = {1, 5, 4, 6, 3, 9, 4, 5, 6, 4};
int[] reverseArr = (arr)
             .boxed()
             .sorted(())
             .mapToInt(Integer::valueOf)
             .toArray();
// output: [9, 6, 6, 5, 5, 4, 4, 4, 3, 1]
((reverseArr));

6. Other classes that can generate streams

In addition to the above-mentioned classes that can mainly generate streams, there are some other less common classes that can be streamed. The following is some code display:

String s = "1,2,3,4,5,6,7";
// Stream composed of divided strings// Here is a stream composed of "1", "2", "3", "4", "5", "6", "7"Stream&lt;String&gt; stream1 = (",").splitAsStream(s);
BitSet bitSet = new BitSet();
for (int i = 0; i &lt; 10; i++) {
  if (i % 2 == 0) {
    (i);
  }
}
// Stream consisting of bit subscripts set to true in bitset// Here is 0, 2, 4, 6, 8IntStream stream2 = ();
try {
  String dir = ("");
  JarFile jarFile = new JarFile(dir + "\\");
  // Stream formed by JarEntry objects that specify all files and folders in the jar package  Stream&lt;JarEntry&gt; stream3 = ();
} catch (IOException e) {
  ();
}

In addition, you can also generate and operate streams through the StreamSupport tool class. Since the article includes the subsequent articles mainly for getting started and getting started with it easily, there will be no detailed discussion here. Those who are interested can check the information by themselves.

Summarize

This article briefly introduces the new feature of Stream that has been introduced since 1.8, and then briefly introduces some basic concepts and ways to create streams. In the following article, we will also introduce some practical operations of streams. I hope to learn to use the practical feature of Stream with you. Of course, there are inevitably errors in this article, and I hope to get your corrections.

The above is the detailed content of the basic concepts and creation methods of Java Stream. For more information about JAVA Stream, please follow my other related articles!