The Java Stream API Tutorial

Last updated: October 5, 2023

java stream assignment

  • Java Streams
  • >= Java 8

announcement - icon

It's finally here:

>> The Road to Membership and Baeldung Pro .

Going into ads, no-ads reading , and bit about how Baeldung works if you're curious :)

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page .

You can also ask questions and leave feedback on the Azure Container Apps GitHub page .

Java applications have a notoriously slow startup and a long warmup time. The CRaC (Coordinated Restore at Checkpoint) project from OpenJDK can help improve these issues by creating a checkpoint with an application's peak performance and restoring an instance of the JVM to that point.

To take full advantage of this feature, BellSoft provides containers that are highly optimized for Java applications. These package Alpaquita Linux (a full-featured OS optimized for Java and cloud environment) and Liberica JDK (an open-source Java runtime based on OpenJDK).

These ready-to-use images allow us to easily integrate CRaC in a Spring Boot application:

Improve Java application performance with CRaC support

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page .

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page .

Whether you're just starting out or have years of experience, Spring Boot is obviously a great choice for building a web application.

Jmix builds on this highly powerful and mature Boot stack, allowing devs to build and deliver full-stack web applications without having to code the frontend. Quite flexibly as well, from simple web GUI CRUD applications to complex enterprise solutions.

Concretely, The Jmix Platform includes a framework built on top of Spring Boot, JPA, and Vaadin , and comes with Jmix Studio, an IntelliJ IDEA plugin equipped with a suite of developer productivity tools.

The platform comes with interconnected out-of-the-box add-ons for report generation, BPM, maps, instant web app generation from a DB, and quite a bit more:

>> Become an efficient full-stack developer with Jmix

DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema .

The way it does all of that is by using a design model , a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.

And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.

>> Take a look at DBSchema

Get non-trivial analysis (and trivial, too!) suggested right inside your IDE or Git platform so you can code smart, create more value, and stay confident when you push.

Get CodiumAI for free and become part of a community of over 280,000 developers who are already experiencing improved and quicker coding.

Write code that works the way you meant it to:

>> CodiumAI. Meaningful Code Tests for Busy Devs

The AI Assistant to boost Boost your productivity writing unit tests - Machinet AI .

AI is all the rage these days, but for very good reason. The highly practical coding companion, you'll get the power of AI-assisted coding and automated unit test generation . Machinet's Unit Test AI Agent utilizes your own project context to create meaningful unit tests that intelligently aligns with the behavior of the code. And, the AI Chat crafts code and fixes errors with ease, like a helpful sidekick.

Simplify Your Coding Journey with Machinet AI :

>> Install Machinet AI in your IntelliJ

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

Download the E-book

Do JSON right with Jackson

Get the most out of the Apache HTTP Client

Get Started with Apache Maven:

Working on getting your persistence layer right with Spring?

Explore the eBook

Building a REST API with Spring?

Get started with Spring and Spring Boot, through the Learn Spring course:

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Get started with Spring and Spring Boot, through the reference Learn Spring course:

>> LEARN SPRING

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth , to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project .

You can explore the course here:

>> Learn Spring Security

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot .

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

1. Overview

In this comprehensive tutorial, we’ll go through the practical uses of Java 8 Streams from creation to parallel execution.

To understand this material, readers need to have a basic knowledge of Java 8 (lambda expressions, Optional, method references) and of the Stream API. In order to be more familiar with these topics, please take a look at our previous articles: New Features in Java 8 and Introduction to Java 8 Streams .

Further reading:

Lambda expressions and functional interfaces: tips and best practices, guide to java collectors, 2. stream creation.

There are many ways to create a stream instance of different sources. Once created, the instance will not modify its source, therefore allowing the creation of multiple instances from a single source.

2.1. Empty Stream

We should use the empty() method in case of the creation of an empty stream:

We often use the empty() method upon creation to avoid returning null for streams with no element:

2.2. Stream of Collection

We can also create a stream of any type of Collection ( Collection, List, Set ):

2.3. Stream of Array

An array can also be the source of a stream:

We can also create a stream out of an existing array or of part of an array:

2.4. Stream.builder()

When builder is used, the desired type should be additionally specified in the right part of the statement, otherwise the build() method will create an instance of the Stream<Object>:

2.5. Stream.generate()

The generate() method accepts a Supplier<T> for element generation. As the resulting stream is infinite, the developer should specify the desired size, or the generate() method will work until it reaches the memory limit:

The code above creates a sequence of ten strings with the value “element.”

2.6. Stream.iterate()

Another way of creating an infinite stream is by using the iterate() method:

The first element of the resulting stream is the first parameter of the iterate() method. When creating every following element, the specified function is applied to the previous element. In the example above the second element will be 42.

2.7. Stream of Primitives

Java 8 offers the possibility to create streams out of three primitive types: int, long and double. As Stream<T> is a generic interface, and there is no way to use primitives as a type parameter with generics, three new special interfaces were created: IntStream, LongStream, DoubleStream.

Using the new interfaces alleviates unnecessary auto-boxing, which allows for increased productivity:

The range(int startInclusive, int endExclusive) method creates an ordered stream from the first parameter to the second parameter. It increments the value of subsequent elements with the step equal to 1. The result doesn’t include the last parameter, it is just an upper bound of the sequence.

The  rangeClosed(int startInclusive, int endInclusive)   method does the same thing with only one difference, the second element is included. We can use these two methods to generate any of the three types of streams of primitives.

Since Java 8, the Random class provides a wide range of methods for generating streams of primitives. For example, the following code creates a DoubleStream, which has three elements:

2.8. Stream of String

We can also use  String as a source for creating a stream with the help of the chars() method of the String class. Since there is no interface for CharStream in JDK, we use the IntStream to represent a stream of chars instead.

The following example breaks a String into sub-strings according to specified RegEx :

2.9. Stream of File

Furthermore, Java NIO class Files allows us to generate a Stream<String> of a text file through the lines() method. Every line of the text becomes an element of the stream:

The Charset can be specified as an argument of the lines() method.

3. Referencing a Stream

We can instantiate a stream, and have an accessible reference to it, as long as only intermediate operations are called. Executing a terminal operation makes a stream inaccessible .

To demonstrate this, we will forget for a while that the best practice is to chain the sequence of operation. Besides its unnecessary verbosity, technically the following code is valid:

However, an attempt to reuse the same reference after calling the terminal operation will trigger the IllegalStateException:

As the IllegalStateException is a RuntimeException , a compiler will not signalize about a problem. So it is very important to remember that Java 8 streams can’t be reused.

This kind of behavior is logical. We designed streams to apply a finite sequence of operations to the source of elements in a functional style, not to store elements.

So to make the previous code work properly, some changes should be made:

4. Stream Pipeline

To perform a sequence of operations over the elements of the data source and aggregate their results, we need three parts: the source , intermediate operation(s) and a terminal operation.

Intermediate operations return a new modified stream. For example, to create a new stream of the existing one without few elements, the skip() method should be used:

If we need more than one modification, we can chain intermediate operations. Let’s assume that we also need to substitute every element of the current Stream<String> with a sub-string of the first few chars. We can do this by chaining the skip() and map() methods:

As we can see, the map() method takes a lambda expression as a parameter. If we want to learn more about lambdas, we can take a look at our tutorial Lambda Expressions and Functional Interfaces: Tips and Best Practices .

A stream by itself is worthless; the user is interested in the result of the terminal operation, which can be a value of some type or an action applied to every element of the stream. We can only use one terminal operation per stream.

The correct and most convenient way to use streams is by a stream pipeline, which is a chain of the stream source, intermediate operations, and a terminal operation:

5. Lazy Invocation

Intermediate operations are lazy. This means that they will be invoked only if it is necessary for the terminal operation execution.

For example, let’s call the method wasCalled() , which increments an inner counter every time it’s called:

Now let’s call the method wasCalled () from operation filter() :

As we have a source of three elements, we can assume that the filter() method will be called three times, and the value of the counter variable will be 3. However, running this code doesn’t change counter at all, it is still zero, so the filter() method wasn’t even called once. The reason why is missing of the terminal operation.

Let’s rewrite this code a little bit by adding a map() operation and a terminal operation, findFirst(). We will also add the ability to track the order of method calls with the help of logging:

The resulting log shows that we called the filter() method twice and the map() method once. This is because the pipeline executes vertically. In our example, the first element of the stream didn’t satisfy the filter’s predicate. Then we invoked the filter() method for the second element, which passed the filter. Without calling the filter() for the third element, we went down through the pipeline to the map() method.

The findFirst() operation satisfies by just one element. So in this particular example, the lazy invocation allowed us to avoid two method calls, one for the filter() and one for the map().

6. Order of Execution

From the performance point of view, the right order is one of the most important aspects of chaining operations in the stream pipeline:

Execution of this code will increase the value of the counter by three. This means that we called the map() method of the stream three times, but the value of the size is one. So the resulting stream has just one element, and we executed the expensive map() operations for no reason two out of the three times.

If we change the order of the skip() and the map() methods , the counter will increase by only one. So we will call the map() method only once:

This brings us to the following rule: intermediate operations which reduce the size of the stream should be placed before operations which are applying to each element. So we need to keep methods such as s kip(), filter(), and distinct() at the top of our stream pipeline.

7. Stream Reduction

The API has many terminal operations which aggregate a stream to a type or to a primitive: count(), max(), min(), and sum(). However, these operations work according to the predefined implementation. So what if a developer needs to customize a Stream’s reduction mechanism? There are two methods which allow us to do this, the reduce() and the collect() methods.

7.1. The reduce() Method

There are three variations of this method, which differ by their signatures and returning types. They can have the following parameters:

identity – the initial value for an accumulator, or a default value if a stream is empty and there is nothing to accumulate

accumulator – a function which specifies the logic of the aggregation of elements. As the accumulator creates a new value for every step of reducing, the quantity of new values equals the stream’s size and only the last value is useful. This is not very good for the performance.

combiner – a function which aggregates the results of the accumulator. We only call combiner in a parallel mode to reduce the results of accumulators from different threads.

Now let’s look at these three methods in action:

reduced = 6 (1 + 2 + 3)

reducedTwoParams = 16 (10 + 1 + 2 + 3)

The result will be the same as in the previous example (16), and there will be no login, which means that combiner wasn’t called. To make a combiner work, a stream should be parallel:

The result here is different (36), and the combiner was called twice. Here the reduction works by the following algorithm: the accumulator ran three times by adding every element of the stream to identity . These actions are being done in parallel. As a result, they have (10 + 1 = 11; 10 + 2 = 12; 10 + 3 = 13;). Now combiner can merge these three results. It needs two iterations for that (12 + 13 = 25; 25 + 11 = 36).

7.2. The collect() Method

The reduction of a stream can also be executed by another terminal operation, the collect() method. It accepts an argument of the type Collector, which specifies the mechanism of reduction. There are already created, predefined collectors for most common operations. They can be accessed with the help of the Collectors type.

In this section, we will use the following List as a source for all streams:

Converting a stream to the Collection ( Collection, List or Set ):

Reducing to String :

The joining() method can have from one to three parameters (delimiter, prefix, suffix). The most convenient thing about using joining() is that the developer doesn’t need to check if the stream reaches its end to apply the suffix and not to apply a delimiter. Collector will take care of that.

Processing the average value of all numeric elements of the stream:

Processing the sum of all numeric elements of the stream:

The methods averagingXX(), summingXX() and summarizingXX() can work with primitives ( int, long, double ) and with their wrapper classes ( Integer, Long, Double ). One more powerful feature of these methods is providing the mapping. As a result, the developer doesn’t need to use an additional map() operation before the collect() method.

Collecting statistical information about stream’s elements:

By using the resulting instance of type IntSummaryStatistics , the developer can create a statistical report by applying the toString() method. The result will be a String common to this one “IntSummaryStatistics{count=5, sum=86, min=13, average=17,200000, max=23}.”

It is also easy to extract from this object separate values for count, sum, min, average , and  max by applying the methods getCount(), getSum(), getMin(), getAverage(), and getMax(). All of these values can be extracted from a single pipeline.

Grouping of stream’s elements according to the specified function:

In the example above, the stream was reduced to the Map , which groups all products by their price.

Dividing stream’s elements into groups according to some predicate:

Pushing the collector to perform additional transformation:

In this particular case, the collector has converted a stream to a Set , and then created the unchangeable Set out of it.

Custom collector:

If for some reason a custom collector should be created, the easiest and least verbose way of doing so is to use the method of() of the type Collector.

In this example, an instance of the Collector got reduced to the LinkedList <Persone>.

8. Parallel Streams

Before Java 8, parallelization was complex. The emergence of the ExecutorService and the ForkJoin simplified a developer’s life a little bit, but it was still worth remembering how to create a specific executor, how to run it, and so on. Java 8 introduced a way of accomplishing parallelism in a functional style.

The API allows us to create parallel streams, which perform operations in a parallel mode. When the source of a stream is a Collection or an array , it can be achieved with the help of the parallelStream() method:

If the source of a stream is something other than a Collection or an array , the parallel() method should be used:

Under the hood, Stream API automatically uses the ForkJoin framework to execute operations in parallel. By default, the common thread pool will be used and there is no way (at least for now) to assign some custom thread pool to it. This can be overcome by using a custom set of parallel collectors.

When using streams in parallel mode, avoid blocking operations. It is also best to use parallel mode when tasks need a similar amount of time to execute. If one task lasts much longer than the other, it can slow down the complete app’s workflow.

The stream in parallel mode can be converted back to the sequential mode by using the sequential() method:

9. Conclusion

The Stream API is a powerful, but simple to understand set of tools for processing the sequence of elements. When used properly, it allows us to reduce a huge amount of boilerplate code, create more readable programs, and improve an app’s productivity.

In most of the code samples shown in this article, we left the streams unconsumed (we didn’t apply the close() method or a terminal operation). In a real app, don’t leave an instantiated stream unconsumed, as that will lead to memory leaks.

The complete code samples that accompany this article are available over on GitHub.

Looking for the ideal Linux distro for running modern Spring apps in the cloud?

Meet Alpaquita Linux : lightweight, secure, and powerful enough to handle heavy workloads.

This distro is specifically designed for running Java apps . It builds upon Alpine and features significant enhancements to excel in high-density container environments while meeting enterprise-grade security standards.

Specifically, the container image size is ~30% smaller than standard options, and it consumes up to 30% less RAM:

>> Try Alpaquita Containers now.

Explore the secure, reliable, and high-performance Test Execution Cloud built for scale. Right in your IDE:

Basically, write code that works the way you meant it to.

AI is all the rage these days, but for very good reason. The highly practical coding companion, you'll get the power of AI-assisted coding and automated unit test generation . Machinet's Unit Test AI Agent utilizes your own project context to create meaningful unit tests that intelligently aligns with the behavior of the code.

Get started with Spring Boot and with core Spring, through the Learn Spring course:

Build your API with SPRING - book cover

HowToDoInJava

Java Stream API: Real-world Examples for Beginners

Java Streams can be defined as a sequence of elements from a source that supports aggregate operations on them. The source refers to a collection or array.

Lokesh Gupta

September 19, 2023

java_8_lambdas

A Stream in Java can be defined as a sequence of elements from a source . The source of elements here refers to a Collection or Array that provides data to the Stream.

  • Java streams are designed in such a way that most of the stream operations (called intermediate operations ) return a Stream. This helps to create a chain of stream operations. This is called a stream pipeline .
  • Java streams also support the aggregate or terminal operations on the elements. The aggregate operations are operations that allow us to express common manipulations on stream elements quickly and clearly, for example, finding the max or min element, finding the first element matching giving criteria, and so on.
  • Not that a stream maintains the same ordering of the elements as the ordering in the stream source .

1. What is a Stream?

All of us have watched online videos on YouTube. When we start watching a video, a small portion of the video file is first loaded into our computer and starts playing. we don’t need to download the complete video before we start watching it. This is called video streaming. At a very high level, we can think of the small portions of the video file as a stream and the whole video as a Collection.

At the granular level, the difference between a Collection and a Stream is when the things are computed. A Collection is an in-memory data structure that holds all the data structure’s values . Every element in the Collection has to be computed before it can be added to the Collection. While a Stream is conceptually a pipeline in which elements are computed on demand .

This concept gives rise to significant programming benefits. The idea is that a user will extract only the values they require from a Stream, and these elements are produced invisibly to the user, as and when required. This is a form of a producer-consumer relationship.

In Java, java.util.Stream interface represents a stream on which one or more operations can be performed.

  • Stream operations are either intermediate or terminal . The terminal operations return a result of a certain type, and intermediate operations return the stream itself so we can chain multiple methods in a row to perform the operation in multiple steps.
  • Streams are created on a source, e.g. a java.util.Collection like List or Set . The Map is not supported directly, we can create a stream of map keys, values or entries.
  • Stream operations can either be executed sequentially or in parallel. when performed parallelly, it is called a parallel stream .

Based on the above points, we can say that a Stream is:

  • Designed for lambdas or functional programming
  • Not a data structure to store objects
  • Do not support indexed access
  • Can easily be aggregated as arrays or lists
  • Lazy access supported
  • Parallelizable

2. Creating Streams

The given below ways are the most popular different ways to build streams from collections.

2.1. Stream.of()

In the given example, we are creating a stream of a fixed number of integers.

2.2. Stream.of(array)

In the given example, we are creating a stream from the array. The elements in the stream are taken from the array.

2.3. List.stream()

In the given example, we are creating a stream from the List . The elements in the stream are taken from the List.

2.4. Stream.generate() or Stream.iterate()

In the given example, we are creating a stream from generated elements. This will produce a stream of 20 random numbers. We have restricted the elements count using limit() function.

2.5. Stream of String chars or tokens

In the given example, first, we create a stream from the characters of a given string. In the second part, we are creating the stream of tokens received from splitting from a string.

There are some more ways also such as using Stream.Buider or using intermediate operations. We will learn about them in separate posts from time to time.

3. Stream Collectors

After performing the intermediate operations on elements in the stream, we can collect the processed elements again into a Collection using the stream Collector methods.

3.1. Collect Stream Elements to a List

In the given example, first, we create a stream on integers 1 to 10. Then we process the stream elements to find all even numbers.

At last, we are collecting all even numbers into a List .

3.2. Collect Stream Elements to an Array

The given example is similar to the first example shown above. The only difference is that we are collecting even numbers in an Array.

There are plenty of other ways also to collect stream into a Set , Map or into multiple ways. Just go through Collectors class and try to keep them in mind.

4. Stream Operations

Stream abstraction has a long list of useful functions. Let us look at a few of them.

Before moving ahead, let us build a List of strings beforehand. We will build our examples on this list so that it is easy to relate and understand.

These core methods have been divided into 2 parts given below:

4.1. Intermediate Operations

Intermediate operations return the stream itself so you can chain multiple methods calls in a row. Let’s learn important ones.

4.1.1. Stream.filter()

The filter() method accepts a Predicate to filter all elements of the stream. This operation is intermediate, enabling us to call another stream operation (e.g. forEach() ) on the result.

Program Output:

4.1.2. Stream.map()

The map() intermediate operation converts each element in the stream into another object via the given function.

The following example converts each string into an UPPERCASE string. But we can use map() to transform an object into another type as well.

4.1.2. Stream.sorted()

The sorted() method is an intermediate operation that returns a sorted view of the stream. The elements in the stream are sorted in natural order unless we pass a custom Comparator .

Please note that the sorted() method only creates a sorted view of the stream without manipulating the ordering of the source Collection. In this example, the ordering of string in the memberNames is untouched.

4.2. Terminal operations

Terminal operations return a result of a certain type after processing all the stream elements.

Once the terminal operation is invoked on a Stream, the iteration of the Stream and any of the chained streams will get started. Once the iteration is done, the result of the terminal operation is returned.

4.2.1. Stream.forEach()

The forEach() method helps iterate over all stream elements and perform some operation on each of them. The operation to be performed is passed as the lambda expression.

4.2.2. Stream.collect()

The collect() method is used to receive elements from steam and store them in a collection.

4.2.3. Stream.match()

Various matching operations can be used to check whether a given predicate matches the stream elements. All of these matching operations are terminal and return a boolean result.

4.2.4. Stream.count()

The count() is a terminal operation returning the number of elements in the stream as a long value.

4.2.5. Stream.reduce()

The reduce() method performs a reduction on the elements of the stream with the given function. The result is an Optional holding the reduced value.

In the given example, we are reducing all the strings by concatenating them using a separator # .

5. Short-circuit Operations

Though stream operations are performed on all elements inside a collection satisfying a Predicate, it is often desired to break the operation whenever a matching element is encountered during iteration.

In external iteration, we will do with the if-else block . In the internal iterations such as in streams, there are certain methods we can use for this purpose.

5.1. Stream.anyMatch()

The anyMatch() will return true once a condition passed as predicate satisfies. Once a matching value is found, no more elements will be processed in the stream.

In the given example, as soon as a String is found starting with the letter 'A' , the stream will end and the result will be returned.

5.2. Stream.findFirst()

The findFirst() method will return the first element from the stream and then it will not process any more elements.

6. Parallel Streams

With the Fork/Join framework added in Java SE 7, we have efficient machinery for implementing parallel operations in our applications.

But implementing a fork/join framework is a complex task, and if not done right; it is a source of complex multi-threading bugs that have the potential to crash the application. With the introduction of internal iterations , we got the possibility of operations to be done in parallel more efficiently.

To enable parallelism, all we have to do is to create a parallel stream, instead of a sequential stream. And to our surprise, this is really very easy.

In any of the above-listed stream examples, anytime we want to do a particular job using multiple threads in parallel cores, all we have to call parallelStream() method instead of stream() method.

A key driver for Stream APIs is making parallelism more accessible to developers. While the Java platform provides strong support for concurrency and parallelism already, developers face unnecessary impediments in migrating their code from sequential to parallel as needed.

Therefore, it is important to encourage idioms that are both sequential- and parallel-friendly. This is facilitated by shifting the focus towards describing what computation should be performed rather than how it should be performed.

It is also important to strike the balance between making parallelism easier and not going so far as to make it invisible. Making parallelism transparent would introduce non-determinism and the possibility of data races where users might not expect it.

7. Stream Methods

7.1 creating streams, 7.2 intermediate operations, 7.3. terminal operations.

  • forEachOrdered()
  • noneMatch()
  • findFirst()

Happy Learning !!

Sourcecode on Github

Weekly Newsletter

Stay Up-to-Date with Our Weekly Updates. Right into Your Inbox.

Photo of author

Internal vs. External Iteration in Java

Java comparator with lambda.

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Tutorial Series

Privacy Policy

REST API Tutorial

  • Prev Class
  • Next Class
  • No Frames
  • All Classes
  • Summary: 
  • Nested  | 
  • Field | 
  • Constr | 
  • Detail: 

Interface Stream<T>

  • must be non-interfering (they do not modify the stream source); and
  • in most cases must be stateless (their result should not depend on any state that might change during execution of the stream pipeline).

Nested Class Summary

Nested Classes 
Modifier and Type Interface and Description
< > .

Method Summary

All Methods         
Modifier and Type Method and Description
( <? super > predicate)
( <? super > predicate)
<T> () .
( <? super ,A,R> collector) operation on the elements of this stream using a .
( <R> supplier, <R,? super > accumulator, <R,R> combiner) operation on the elements of this stream.
<T> ( <? extends T> a, <? extends T> b)
()
< > () ) of this stream.
<T> () .
< > ( <? super > predicate)
< > () describing some element of the stream, or an empty if the stream is empty.
< > () describing the first element of this stream, or an empty if the stream is empty.
<R> ( <? super ,? extends <? extends R>> mapper)
( <? super ,? extends > mapper) consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.
( <? super ,? extends > mapper) consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.
( <? super ,? extends > mapper) consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.
( <? super > action)
( <? super > action)
<T> ( <T> s) .
<T> (T seed, <T> f) produced by iterative application of a function to an initial element , producing a consisting of , , , etc.
< > (long maxSize) in length.
<R> ( <? super ,? extends R> mapper)
( <? super > mapper) consisting of the results of applying the given function to the elements of this stream.
( <? super > mapper) consisting of the results of applying the given function to the elements of this stream.
( <? super > mapper) consisting of the results of applying the given function to the elements of this stream.
< > ( <? super > comparator) .
< > ( <? super > comparator) .
( <? super > predicate)
<T> (T... values)
<T> (T t) containing a single element.
< > ( <? super > action)
< > ( < > accumulator) on the elements of this stream, using an accumulation function, and returns an describing the reduced value, if any.
(  identity, < > accumulator) on the elements of this stream, using the provided identity value and an accumulation function, and returns the reduced value.
(U identity, <U,? super ,U> accumulator, <U> combiner) on the elements of this stream, using the provided identity, accumulation and combining functions.
< > (long n) elements of the stream.
< > ()
< > ( <? super > comparator) .
[] ()
( <A[]> generator) function to allocate the returned array, as well as any additional arrays that might be required for a partitioned execution or for resizing.

Methods inherited from interface java.util.stream. BaseStream

Method detail, maptodouble, flatmaptoint, flatmaptolong, flatmaptodouble, foreachordered.

Submit a bug or feature For further API reference and developer documentation, see Java SE Documentation . That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples. Copyright © 1993, 2024, Oracle and/or its affiliates. All rights reserved. Use is subject to license terms . Also see the documentation redistribution policy .

Scripting on this page tracks web page traffic, but does not change the content in any way.

  • Skip to content
  • Accessibility Policy
  • QUICK LINKS
  • Oracle Cloud Infrastructure
  • Oracle Fusion Cloud Applications
  • Oracle Database
  • Download Java
  • Careers at Oracle

 alt=

  • Create an Account

Processing Data with Java SE 8 Streams, Part 1

by Raoul-Gabriel Urma

Use stream operations to express sophisticated data processing queries.

What would you do without collections? Nearly every Java application makes and processes collections. They are fundamental to many programming tasks: they let you group and process data. For example, you might want to create a collection of banking transactions to represent a customer’s statement. Then, you might want to process the whole collection to find out how much money the customer spent. Despite their importance, processing collections is far from perfect in Java.

  • Originally published in the March/April 2014 issue of Java Magazine . Subscribe today.

First, typical processing patterns on collections are similar to SQL-like operations such as “finding” (for example, find the transaction with highest value) or “grouping” (for example, group all transactions related to grocery shopping). Most databases let you specify such operations declaratively. For example, the following SQL query lets you find the transaction ID with the highest value: "SELECT id, MAX(value) from transactions" .

As you can see, we don’t need to implement how to calculate the maximum value (for example, using loops and a variable to track the highest value). We only express what we expect. This basic idea means that you need to worry less about how to explicitly implement such queries—it is handled for you. Why can’t we do something similar with collections? How many times do you find yourself reimplementing these operations using loops over and over again?

Second, how can we process really large collections efficiently? Ideally, to speed up the processing, you want to leverage multicore architectures. However, writing parallel code is hard and error-prone. 

Java SE 8 to the rescue! The Java API designers are updating the API with a new abstraction called Stream that lets you process data in a declarative way. Furthermore, streams can leverage multi-core architectures without you having to write a single line of multithread code. Sounds good, doesn’t it? That’s what this series of articles will explore.

Here’s a mind-blowing idea: these two operations can produce elements “forever.”

Before we explore in detail what you can do with streams, let’s take a look at an example so you have a sense of the new programming style with Java SE 8 streams. Let’s say we need to find all transactions of type grocery and return a list of transaction IDs sorted in decreasing order of transaction value. In Java SE 7, we’d do that as shown in Listing 1 . In Java SE 8, we’d do it as shown in Listing 2 .

Figure 1 illustrates the Java SE 8 code. First, we obtain a stream from the list of transactions (the data) using the stream() method available on List . Next, several operations ( filter , sorted , map , collect ) are chained together to form a pipeline, which can be seen as forming a query on the data.

streams-f1

So how about parallelizing the code? In Java SE 8 it’s easy: just replace stream() with parallel Stream() , as shown in Listing 3 , and the Streams API will internally decompose your query to leverage the multiple cores on your computer.

Don’t worry if this code is slightly overwhelming. We will explore how it works in the next sections. However, notice the use of lambda expressions (for example, t-> t.getCategory() == Transaction.GROCERY ) and method references (for example, Transaction::getId ), which you should be familiar with by now. (To brush up on lambda expressions, refer to previous Java Magazine articles and other resources listed at the end of this article.)

For now, you can see a stream as an abstraction for expressing efficient, SQL-like operations on a collection of data. In addition, these operations can be succinctly parameterized with lambda expressions.

At the end of this series of articles about Java SE 8 streams, you will be able to use the Streams API to write code similar to Listing 3 to express powerful queries.

Getting Started with Streams

Let’s start with a bit of theory. What’s the definition of a stream? A short definition is “a sequence of elements from a source that supports aggregate operations.” Let’s break it down: 

  • Sequence of elements: A stream provides an interface to a sequenced set of values of a specific element type. However, streams don’t actually store elements; they are computed on demand.
  • Source: Streams consume from a data-providing source such as collections, arrays, or I/O resources.
  • Aggregate operations: Streams support SQL-like operations and common operations from functional programing languages, such as filter , map , reduce , find , match , sorted , and so on. 

Furthermore, stream operations have two fundamental characteristics that make them very different from collection operations:

  • Pipelining: Many stream operations return a stream themselves. This allows operations to be chained to form a larger pipeline. This enables certain optimizations, such as laziness and short-circuiting , which we explore later.
  • Internal iteration: In contrast to collections, which are iterated explicitly ( external iteration ), stream operations do the iteration behind the scenes for you. 

Let’s revisit our earlier code example to explain these ideas. Figure 2 illustrates Listing 2 in more detail.

streams-f2

We first get a stream from the list of transactions by calling the stream() method. The datasource is the list of transactions and will be providing a sequence of elements to the stream. Next, we apply a series of aggregate operations on the stream: filter (to filter elements given a predicate), sorted (to sort the elements given a comparator), and map (to extract information). All these operations except collect return a Stream so they can be chained to form a pipeline, which can be viewed as a query on the source.

No work is actually done until collect is invoked. The collect operation will start processing the pipeline to return a result (something that is not a Stream ; here, a List ). Don’t worry about collect for now; we will explore it in detail in a future article. At the moment, you can see collect as an operation that takes as an argument various recipes for accumulating the elements of a stream into a summary result. Here, toList() describes a recipe for converting a Stream into a List .

Before we explore the different methods available on a stream, it is good to pause and reflect on the conceptual difference between a stream and a collection.

Streams Versus Collections

Both the existing Java notion of collections and the new notion of streams provide interfaces to a sequence of elements. So what’s the difference? In a nutshell, collections are about data and streams are about computations.

Consider a movie stored on a DVD. This is a collection (perhaps of bytes or perhaps of frames—we don’t care which here) because it contains the whole data structure. Now consider watching the same video when it is being streamed over the internet. It is now a stream (of bytes or frames). The streaming video player needs to have downloaded only a few frames in advance of where the user is watching, so you can start displaying values from the beginning of the stream before most of the values in the stream have even been computed (consider streaming a live football game).

In the coarsest terms, the difference between collections and streams has to do with when things are computed. A collection is an in-memory data structure, which holds all the values that the data structure currently has—every element in the collection has to be computed before it can be added to the collection. In contrast, a stream is a conceptually fixed data structure in which elements are computed on demand.

Using the Collection interface requires iteration to be done by the user (for example, using the enhanced for loop called foreach ); this is called external iteration.

In contrast, the Streams library uses internal iteration—it does the iteration for you and takes care of storing the resulting stream value somewhere; you merely provide a function saying what’s to be done. The code in Listing 4 (external iteration with a collection) and Listing 5 (internal iteration with a stream) illustrates this difference.

In Listing 4 , we explicitly iterate the list of transactions sequentially to extract each transaction ID and add it to an accumulator. In contrast, when using a stream, there’s no explicit iteration. The code in Listing 5 builds a query, where the map operation is parameterized to extract the transaction IDs and the collect operation converts the resulting Stream into a List .

You should now have a good idea of what a stream is and what you can do with it. Let’s now look at the different operations supported by streams so you can express your own data processing queries.

Stream Operations: Exploiting Streams to Process Data

The Stream interface in java.util .stream.Stream defines many operations, which can be grouped in two categories. In the example illustrated in Figure 1 , you can see the following operations: 

  • filter , sorted , and map , which can be connected together to form a pipeline
  • collect , which closed the pipeline and returned a result 

Stream operations that can be connected are called intermediate operations . They can be connected together because their return type is a Stream . Operations that close a stream pipeline are called terminal operations . They produce a result from a pipeline such as a List , an Integer , or even void (any non- Stream type).

You might be wondering why the distinction is important. Well, intermediate operations do not perform any processing until a terminal operation is invoked on the stream pipeline; they are “lazy.” This is because intermediate operations can usually be “merged” and processed into a single pass by the terminal operation.

For example, consider the code in Listing 6 , which computes two even square numbers from a given list of numbers. You might be surprised that it prints the following:

This is because limit(2) uses short-circuiting ; we need to process only part of the stream, not all of it, to return a result. This is similar to evaluating a large Boolean expression chained with the and operator: as soon as one expression returns false , we can deduce that the whole expression is false without evaluating all of it. Here, the operation limit returns a stream of size 2 . 

In addition, the operations filter and map have been merged in the same pass.

To summarize what we’ve learned so far, working with streams, in general, involves three things: 

  • A datasource (such as a collection) on which to perform a query
  • A chain of intermediate operations, which form a stream pipeline
  • One terminal operation, which executes the stream pipeline and produces a result 

The Streams API will internally decompose your query to leverage the multiple cores on your computer.

Let’s now take a tour of some of the operations available on streams. Refer to the java.util .stream.Stream interface for the complete list, as well as to the resources at the end of this article for more examples.

Filtering. There are several operations that can be used to filter elements from a stream: 

  • filter(Predicate) : Takes a predicate ( java.util.function.Predicate ) as an argument and returns a stream including all elements that match the given predicate
  • distinct : Returns a stream with unique elements (according to the implementation of equals for a stream element)
  • limit(n) : Returns a stream that is no longer than the given size n
  • skip(n) : Returns a stream with the first n number of elements discarded 

Finding and matching. A common data processing pattern is determining whether some elements match a given property. You can use the anyMatch , allMatch , and noneMatch operations to help you do this. They all take a predicate as an argument and return a boolean as the result (they are, therefore, terminal operations). For example, you can use allMatch to check that all elements in a stream of transactions have a value higher than 100, as shown in Listing 7 .

In addition, the Stream interface provides the operations findFirst and findAny for retrieving arbitrary elements from a stream. They can be used in conjunction with other stream operations such as filter . Both findFirst and findAny return an Optional object, as shown in Listing 8 .

The Optional<T> class ( java.util .Optional ) is a container class to represent the existence or absence of a value. In Listing 8 , it is possible that findAny doesn’t find any transaction of type grocery . The Optional class contains several methods to test the existence of an element. For example, if a transaction is present, we can choose to apply an operation on the optional object by using the ifPresent method, as shown in Listing 9 (where we just print the transaction).

Mapping. Streams support the method map , which takes a function ( java.util.function.Function ) as an argument to project the elements of a stream into another form. The function is applied to each element, “mapping” it into a new element.

For example, you might want to use it to extract information from each element of a stream. In the example in Listing 10 , we return a list of the length of each word from a list. Reducing. So far, the terminal operations we’ve seen return a boolean ( allMatch and so on), void ( forEach ), or an Optional object ( findAny and so on). We have also been using collect to combine all elements in a Stream into a List .

However, you can also combine all elements in a stream to formulate more-complicated process queries, such as “what is the transaction with the highest ID?” or “calculate the sum of all transactions’ values.” This is possible using the reduce operation on streams, which repeatedly applies an operation (for example, adding two numbers) on each element until a result is produced. It’s often called a fold operation in functional programming because you can view this operation as “folding” repeatedly a long piece of paper (your stream) until it forms one little square, which is the result of the fold operation.

It helps to first look at how we could calculate the sum of a list using a for loop:

Each element of the list of numbers is combined iteratively using the addition operator to produce a result. We essentially “reduced” the list of numbers into one number. There are two parameters in this code: the initial value of the sum variable, in this case 0 , and the operation for combining all the elements of the list, in this case + .

Using the reduce method on streams, we can sum all the elements of a stream as shown in Listing 11 . The reduce method takes two arguments:

int sum = numbers.stream().reduce(0, (a, b) -> a + b);

Listing 11  

  • An initial value, here 0
  • A BinaryOperator<T> to combine two elements and produce a new value 

The reduce method essentially abstracts the pattern of repeated application. Other queries such as “calculate the product” or “calculate the maximum” (see Listing 12 ) become special use cases of the reduce method.

Numeric Streams

You have just seen that you can use the reduce method to calculate the sum of a stream of integers. However, there’s a cost: we perform many boxing operations to repeatedly add Integer objects together. Wouldn’t it be nicer if we could call a sum method, as shown in Listing 13 , to be more explicit about the intent of our code?

Java SE 8 introduces three primitive specialized stream interfaces to tackle this issue— IntStream , DoubleStream , and LongStream —that respectively specialize the elements of a stream to be int , double , and long .

The most-common methods you will use to convert a stream to a specialized version are mapToInt , mapToDouble , and mapToLong . These methods work exactly like the method map that we saw earlier, but they return a specialized stream instead of a Stream<T> . For example, we could improve the code in Listing 13 as shown in Listing 14 . You can also convert from a primitive stream to a stream of objects using the boxed operation.

Finally, another useful form of numeric streams is numeric ranges. For example, you might want to generate all numbers between 1 and 100. Java SE 8 introduces two static methods available on IntStream , DoubleStream , and LongStream to help generate such ranges: range and rangeClosed .

Both methods take the starting value of the range as the first parameter and the end value of the range as the second parameter. However, range is exclusive, whereas rangeClosed is inclusive. Listing 15 is an example that uses rangeClosed to return a stream of all odd numbers between 10 and 30.

Building Streams

There are several ways to build streams. You’ve seen how you can get a stream from a collection. Moreover, we played with streams of numbers. You can also create streams from values, an array, or a file. In addition, you can even generate a stream from a function to produce infinite streams! 

Creating a stream from values or from an array is straightforward: just use the static methods Stream .of for values and Arrays.stream for an array, as shown in Listing 16 .

In contrast to collections, which are iterated explicitly ( external iteration ), stream operations do the iteration behind the scenes for you.

You can also convert a file in a stream of lines using the Files.lines static method. For example, in Listing 17 we count the number of lines in a file.

Infinite streams. Finally, here’s a mind-blowing idea before we conclude this first article about streams. By now you should understand that elements of a stream are produced on demand. There are two static methods— Stream.iterate and Stream .generate —that let you create a stream from a function. However, because elements are calculated on demand, these two operations can produce elements “forever.” This is what we call an infinite stream : a stream that doesn’t have a fixed size, as a stream does when we create it from a fixed collection.

  • Java 8 Lambdas in Action
  • GitHub repository with Java SE 8 code examples
  • “ Java 8: Lambdas, Part 1 ” by Ted Neward

Listing 18 is an example that uses iterate to create a stream of all numbers that are multiples of 10. The iterate method takes an initial value (here, 0 ) and a lambda (of type UnaryOperator<T> ) to apply successively on each new value produced.

Stream<Integer> numbers = Stream.iterate(0, n -> n + 10);

We can turn an infinite stream into a fixed-size stream using the limit operation. For example, we can limit the size of the stream to 5, as shown in Listing 19 .

numbers.limit(5).forEach(System.out::println); // 0, 10, 20, 30, 40

Java SE 8 introduces the Streams API, which lets you express sophisticated data processing queries. In this article, you’ve seen that a stream supports many operations such as filter , map , reduce , and iterate that can be combined to write concise and expressive data processing queries. This new way of writing code is very different from how you would process collections before Java SE 8. However, it has many benefits. First, the Streams API makes use of several techniques such as laziness and short-circuiting to optimize your data processing queries. Second, streams can be parallelized automatically to leverage multicore architectures. In the next article in this series, we will explore more-advanced operations, such as flatMap and collect . Stay tuned.

Raoul-Gabriel Urma

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Java 8: assigning a value from a stream to a variable?

I just started to learn streams in java8. I am trying to convert a basic for each loop into a stream that does the exact same thing. I have checked around here and found this: Convert For-Loop into Java stream . The issue with this is that the example collects the results at the end and I don't think I need to collect anything but to assign the value which is not explained.

the loop which I want to convert is this. As you can see I want to assign the value to the vanTire.

What I have so far with streams is this. How do I assign the value to the vanTire variable since filtering and casting is already done?

  • java-stream

Jason Aller's user avatar

  • In general, you don't assign values from within the stream to a variable; you extract a result from the stream (like the last VanTire instance). –  Louis Wasserman Commented Aug 13, 2020 at 21:11
  • 1 Do you want the very last element from the loop only? Since that is what your original loop is doing. If not, you should break; upon the first match. It is completely unecessary to loop the full list if you already found your match. –  Zabuzard Commented Aug 14, 2020 at 18:47
  • hei Zabuzard, i managed to do make it work, thanks and greetings to you ! –  helloApp Commented Aug 14, 2020 at 19:29

2 Answers 2

After getting the correct items, you need to use .findFirst or .findAny to get an element, along with orElse to provide a default value

.elseGet and .elseThrow in Optional documentation

.findFirst or .findAny in Stream documentation

azro's user avatar

  • You meant .orElseGet and .,orElseThrow here in the Optional documentation? –  tpdi Commented Aug 13, 2020 at 21:21
  • 1 filter(tire -> tire instanceof VanTire) can be filter(vanTire.class::isInstance) –  tpdi Commented Aug 13, 2020 at 21:22
  • 1 I suggest being consistent. Either use .filter(VanTire.class::isInstance) .map(VanTire.class::cast) or use .filter(tire -> tire instanceof VanTire).map(tire-> (VanTire)tire) . But note that the mapping step is obsolete here. You can apply the typecast when assigning: VanTire vanTire = (VanTire)tireList.stream().filter(tire -> tire instanceof VanTire).findAny().orElse(null); –  Holger Commented Aug 14, 2020 at 8:09

In general, Stream s should be stateless . This is due to the fact that the elements in Stream s might be processed out of order. Thus, I would suggest a solution that does not assing the value from within the Stream , but rather yield a result from the stream that is assignable to the desired type:

I used .orElse(null) since this maps to the semantics of the sample code provided wrt. the behaviour when tireList is empty. Depending on the business case, however, continuing computation with an Optional or calling orElseThrow(...) might be a better option.

Turing85's user avatar

  • 3 When you want the same semantics as the provided sample code, you need to replace findAny() with reduce((a,b) -> b) , as the loop keeps the last element when there are multiple occurrences. –  Holger Commented Aug 14, 2020 at 8:13
  • @Holger true. I reworded my answer in this regard. –  Turing85 Commented Aug 14, 2020 at 10:43

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged java loops java-8 java-stream or ask your own question .

  • The Overflow Blog
  • Ryan Dahl explains why Deno had to evolve with version 2.0
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • What does a new user need in a homepage experience on Stack Overflow?

Hot Network Questions

  • How can I push back on my co-worker's changes that I disagree with?
  • Fast circular buffer
  • Can the speed of light inhibit the synchronisation of a power grid?
  • How does a closed-cycle rocket engine keep the chamber pressure from stalling the pump turbine?
  • Who gave God the name 'Jealous' as referred to in Exodus 34:14?
  • Everyone hates this Key Account Manager, but company won’t act
  • Should I be worried about this giant crack?
  • Why did Worf respond when Picard ordered the Enterprise out of the asteroid in TNG: The Pegasus?
  • One IO to control two LEDs. When one is lit, the other is not
  • bash script quoting frustration
  • Kids' educational VHS series about a man who's friends with a parrot and a chimpanzee
  • Calling get_GeodesicArea from ogr2ogr
  • Linear Regulator Pass Transistor vs Parallel Regulators
  • Is it OK to use the same field in the database to store both a percentage rate and a fixed money fee?
  • Should it be "until" or "before" in "Go home until it's too late"?
  • How "the unity of opposites" represents non-duality?
  • Can objective morality be derived as a corollary from the assumption of God's existence?
  • block-structure matrix
  • Retroactively specifying `-only` or `-or-later` for GPLv2 in an adopted project
  • Would weightlessness (i.e. in thrill rides, planes, skydiving, etc.) be different on a Flat Earth?
  • Unit fractions summing to 1 - proving upper bound for the denominators.
  • Calculate the sum of numbers in a rectangle
  • 32 MHz xtal on ST MB1874_HP reference schematic questions
  • Which BASIC dialect first featured a single-character comment introducer?

java stream assignment

Learn Java and Programming through articles, code examples, and tutorials for developers of all levels.

  • online courses
  • certification
  • free resources

Saturday, September 9, 2023

Top 15 java 8 stream and functional programming interview questions answers, 10 java functional programming and stream interview questions, 1. what is the difference between collection and stream  ( answer ), 2. what does the map() function do why you use it  ( answer ).

Top 10 Stream and Functional Programming Interview Questions in Java 8

  • Introduction

The forEach() method is part of the Stream interface and is used to execute a specified operation, defined by a Consumer .

The Consumer interface represents any operation that takes an argument as input, and has no output. This sort of behavior is acceptable because the forEach() method is used to change the program's state via side-effects, not explicit return types.

Therefore, the best target candidates for Consumers are lambda functions and method references. It's worth noting that forEach() can be used on any Collection .

  • forEach() on List

The forEach() method is a terminal operation, which means that after we call this method, the stream along with all of its integrated transformations will be materialized. That is to say, they'll "gain substance", rather than being streamed.

Let's generate a small list:

Traditionally, you could write a for-each loop to go through it:

This would print:

Alternatively, we can use the forEach() method on a Stream :

This also outputs:

We can make this even simpler via a method reference :

  • forEach() on Map

The forEach() method is really useful if we want to avoid chaining many stream methods. Let's generate a map with a few movies and their respective IMDB scores:

Now, let's print out the values of each film that has a score higher than 8.4 :

This results in:

Here, we've converted a Map to a Set via entrySet() , streamed it, filtered based on the score and finally printed them out via a forEach() . Instead of basing this on the return of filter() , we could've based our logic on side-effects and skipped the filter() method:

Finally, we can omit both the stream() and filter() methods by starting out with forEach() in the beginning:

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

  • forEach() on Set

Let's take a look at how we can use the forEach method on a Set in a bit more tangible context. First, let's define a class that represents an Employee of a company:

Imagining we're the manager, we'll want to pick out certain employees that have worked overtime and award them for the hard work. First, let's make a Set :

Then, let's calculate each employee's dedication score:

Now that each employee has a dedication score, let's remove the ones with a score that's too low:

Finally, let's reward the employees for their hard work:

And for clarity's sake, let's print out the names of the lucky workers:

After running the code above, we get the following output:

  • Side-effects Vs Return Values

The point of every command is to evaluate the expression from start to finish. Everything in-between is a side-effect . In this context, it means altering the state, flow or variables without returning any values.

Let's take a look at the difference on another list:

This approach is based on the returned values from an ArrayList :

And now, instead of basing the logic of the program on the return type, we'll perform a forEach() on the stream and add the results to an AtomicInteger (streams operate concurrently):

The forEach() method is a really useful method to use to iterate over collections in Java in a functional approach.

In certain cases, they can massively simplify the code and enhance clarity and brevity. In this article, we've gone over the basics of using a forEach() and then covered examples of the method on a List , Map and Set .

We've covered the difference between the for-each loop and the forEach() , as well as the difference between basing logic on return values versus side-effects.

You might also like...

  • Java: Finding Duplicate Elements in a Stream
  • Spring Boot with Redis: HashOperations CRUD Functionality
  • Spring Cloud: Hystrix
  • Java Regular Expressions - How to Validate Emails

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

In this article

java stream assignment

Monitor with Ping Bot

Reliable monitoring for your app, databases, infrastructure, and the vendors they rely on. Ping Bot is a powerful uptime and performance monitoring tool that helps notify you and resolve issues before they affect your customers.

OpenAI

Vendor Alerts with Ping Bot

Get detailed incident alerts about the status of your favorite vendors. Don't learn about downtime from your customers, be the first to know with Ping Bot.

Supabase

© 2013- 2024 Stack Abuse. All rights reserved.

Java Guides

Java Guides

Search this blog, java stream api interview questions and answers.

In this article, we will discuss some important and  frequently asked   Java 8 Stream API Interview Questions and Answers.

YouTube Video

1. What is a Stream? 

java stream assignment

2. Explain Stream Operations?

3. how to create streams in java, creating empty stream, creating stream from from collections, creating stream object from arrays, creating stream object from string using chars() method, 4. what is the difference between collections api and streams api, 5. what does the stream map() function do why you use it, 6. what does the stream filter() method do when you use it, 7. what does the stream flatmap() function do why you need it, 8. difference between stream map() and flatmap() functions.

  • The function you pass to the map() operation returns a single value.
  • The function you pass to flatMap() operation returns a Stream of value.
  • flatMap() is a combination of map and flat operation.
  • map() is used for transformation only, but flatMap() is used for both transformation and flattening.

9. What is the difference between intermediate and terminal operations on Stream?

  • noneMatch()
  • findFirst()

Post a Comment

Leave Comment

My Top and Bestseller Udemy Courses

  • Spring 6 and Spring Boot 3 for Beginners (Includes Projects)
  • Building Real-Time REST APIs with Spring Boot
  • Building Microservices with Spring Boot and Spring Cloud
  • Full-Stack Java Development with Spring Boot 3 & React
  • Testing Spring Boot Application with JUnit and Mockito
  • Master Spring Data JPA with Hibernate
  • Spring Boot Thymeleaf Real-Time Web Application - Blog App

Check out all my Udemy courses and updates: Udemy Courses - Ramesh Fadatare

Copyright © 2018 - 2025 Java Guides All rights reversed | Privacy Policy | Contact | About Me | YouTube | GitHub

  • ▼Java Exercises
  • ▼Java Basics
  • Basic Part-I
  • Basic Part-II
  • ▼Java Data Types
  • Java Enum Types
  • ▼Java Control Flow
  • Conditional Statement
  • Recursive Methods
  • ▼Java Math and Numbers
  • ▼Object Oriented Programming
  • Java Constructor
  • Java Static Members
  • Java Nested Classes
  • Java Inheritance
  • Java Abstract Classes
  • Java Interface
  • Java Encapsulation
  • Java Polymorphism
  • Object-Oriented Programming
  • ▼Exception Handling
  • Exception Handling Home
  • ▼Functional Programming
  • Java Lambda expression
  • ▼Multithreading
  • Java Thread
  • Java Multithreading
  • ▼Data Structures
  • ▼Strings and I/O
  • File Input-Output
  • ▼Date and Time
  • ▼Advanced Concepts
  • Java Generic Method
  • ▼Algorithms
  • ▼Regular Expressions
  • Regular Expression Home
  • ▼JavaFx Exercises
  • JavaFx Exercises Home
  • ..More to come..

Java Stream - Exercises, Practice, Solutions

Java streams exercises [ 8 exercises with solution].

[ An editor is available at the bottom of the page to write and execute the scripts.   Go to the editor ]

Processing Data with Java SE 8 Streams:

Stream is a sequence of elements from a source that supports aggregate operations. Let’s break it down:

  • Sequence of elements: A stream provides an interface to a sequenced set of values of a specific element type. However, streams don’t actually store elements; they are computed on demand.
  • Source: Streams consume from a data-providing source such as collections, arrays, or I/O resources.
  • Aggregate operations: Streams support SQL-like operations and common operations from functional programing languages, such as filter, map, reduce, find, match, sorted, and so on.

1. Write a Java program to calculate the average of a list of integers using streams.

Click me to see the solution

2. Write a Java program to convert a list of strings to uppercase or lowercase using streams.

3. Write a Java program to calculate the sum of all even, odd numbers in a list using streams.

4. Write a Java program to remove all duplicate elements from a list using streams.

5. Write a Java program to count the number of strings in a list that start with a specific letter using streams.

6. Write a Java program to sort a list of strings in alphabetical order, ascending and descending using streams.

7. Write a Java program to find the maximum and minimum values in a list of integers using streams.

8. Write a Java program to find the second smallest and largest elements in a list of integers using streams.

Java Code Editor

More to Come !

Do not submit any solution of the above exercises at here, if you want to contribute go to the appropriate exercise page.

Follow us on Facebook and Twitter for latest update.

  • Weekly Trends and Language Statistics
  • Trending Now
  • Foundational Courses
  • Data Science
  • Practice Problem
  • Machine Learning
  • System Design
  • DevOps Tutorial

Java-Stream-programs

image

Improve your Coding Skills with Practice

 alt=

Java Code Geeks

Using Java Streams to Determine Max and Min Dates in a List

Photo of Omozegie Aziegbe

Java Streams offer a powerful way to perform operations on collections of data. When working with a list of objects that contain date fields, we may need to use a Java list stream to find the maximum and minimum dates. This article will guide us through finding both the maximal and minimal dates using Java Streams.

1. Example Setup

Let’s assume we have a simple class Event with a LocalDate field representing the date of the event:

In this class:

  • name represents the name of the event.
  • date represents the date of the event.

2. Finding the Maximal and Minimal Dates

Now, let’s say we have a list of Event objects, and we want to find the event with the earliest(minimum) and latest(maximum) dates. Java Streams provide a convenient way to process collections of data. To find the maximal and minimal dates, We can use the Stream API combined with the Comparator interface.

Here’s how we can achieve this:

  • The stream() method creates a sequential Stream from the list of Event objects.
  • The Comparator.comparing(Event::getDate) creates a comparator that compares Event objects based on their date field.
  • The min() method is used to find the element with the smallest date in the list. This returns an Optional<Event> containing the event with the earliest date.
  • Similarly, the max() method finds the element with the largest date in the list, returning an Optional<Event> containing the event with the latest date.

Running the above code will yield the following output:

java stream assignment

  • Empty List : If the list of events is empty, both min() and max() will return an empty Optional . It’s essential to handle this scenario using ifPresent() or orElse() methods.
  • Same Dates : If multiple events have the same date, min() and max() will return the first occurrence in the list.

This example can be expanded to include more complex scenarios, such as filtering events by certain criteria before finding the minimal or maximal dates. With Streams, we can easily compose such operations to handle a wide range of data processing tasks.

3. Conclusion

In this article, we explored how to find the maximum and minimum dates in a Java list using the Stream API. Using Java Streams, finding the maximum and minimum dates in a list of objects is straightforward. By leveraging the Comparator and Stream API, we can write clean code to perform this task.

4. Download the Source Code

This was an article on how to find the maximum and minimum date using Java list and stream.

java stream assignment

We will contact you soon.

Photo of Omozegie Aziegbe

Omozegie Aziegbe

Related articles.

java stream assignment

Java 8 Streams – Group By Multiple Fields with Collectors.groupingBy()

Java program to calculate average using arrays, 150 java interview questions and answers – the ultimate list (pdf download & video), java 8 streams filter with multiple conditions examples, java arraylist insert/replace at index, switch as an expression in java with lambda-like syntax, 13 best java decompilers for download and online use for java developers, how to format/parse dates with localdatetime in java 8 – example tutorial.

guest

This site uses Akismet to reduce spam. Learn how your comment data is processed .

COMMENTS

  1. The Java 8 Stream API Tutorial

    2.7. Stream of Primitives. Java 8 offers the possibility to create streams out of three primitive types: int, long and double. As Stream<T> is a generic interface, and there is no way to use primitives as a type parameter with generics, three new special interfaces were created: IntStream, LongStream, DoubleStream.

  2. 10 Examples of Stream API in Java 8

    2. Java 8 Filter Example 2: Count String whose length is more than three. This is similar to the previous example of Stream with just one difference; instead of the isEmpty () method, we are using the length () method of String. long num = strList. stream() . filter(x -> x. length() > 3 ) . count();

  3. Stream In Java

    A stream in Java is a sequence of objects that supports various methods that can be pipelined to produce the desired result. Use of Stream in Java: The uses of Stream in Java are mentioned below: Stream API is a way to express and process collections of objects. Enable us to perform operations like filtering, mapping, reducing, and sorting.

  4. A Guide to Java Streams in Java 8

    Streams are not data structures but tools for performing operations like map-reduce transformations on collections. This functionality—java.util.stream—supports functional-style operations on streams of elements. This tutorial will guide you through the core concepts and new features, starting with basic stream operations and progressing to more advanced topics.

  5. Streamline Your Java Code: A Cheat Sheet for Mastering Streams

    8. skip(n): The skip(n) operation in Java Streams allows you to bypass a specific number of elements at the beginning of the stream, essentially starting the processing from a later point. For ...

  6. Java 8 Stream Tutorial

    Java 8 Stream Tutorial. Java 8 introduces Stream, which is a new abstract layer, and some new additional packages in Java 8 called java.util.stream. A Stream is a sequence of components that can be processed sequentially. These packages include classes, interfaces, and enum to allow functional-style operations on the elements.

  7. Java Stream API: Real-world Examples for Beginners

    A Stream in Java can be defined as a sequence of elements from a source.The source of elements here refers to a Collection or Array that provides data to the Stream.. Java streams are designed in such a way that most of the stream operations (called intermediate operations) return a Stream.This helps to create a chain of stream operations.

  8. Java 8 Stream API with Examples

    Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result…

  9. Stream (Java Platform SE 8 )

    Stream pipelines may execute either sequentially or in parallel. This execution mode is a property of the stream. Streams are created with an initial choice of sequential or parallel execution. (For example, Collection.stream() creates a sequential stream, and Collection.parallelStream() creates a parallel one.)

  10. Mastering Java Streams: Comprehensive Guide with Examples

    "In this video, we dive deep into Java Streams, demonstrating a wide range of operations with detailed examples. From filtering and mapping to reducing and c...

  11. Processing Data with Java SE 8 Streams, Part 1

    Figure 1 illustrates the Java SE 8 code. First, we obtain a stream from the list of transactions (the data) using the stream() method available on List. Next, several operations ( filter, sorted, map, collect) are chained together to form a pipeline, which can be seen as forming a query on the data. Figure 1.

  12. Java 8: assigning a value from a stream to a variable?

    In general, Streams should be stateless.This is due to the fact that the elements in Streams might be processed out of order.Thus, I would suggest a solution that does not assing the value from within the Stream, but rather yield a result from the stream that is assignable to the desired type:. VanTire vanTire = tireList.stream() .filter(VanTire.class::isInstance) .findAny() .map(VanTire.class ...

  13. Top 15 Java 8 Stream and Functional Programming Interview Questions

    Since it is a functional interface, you can also use it as the assignment target for a lambda expression or method reference. A Consumer is also a functional interface in JDK 8, ... That's all about some of the common Java 8 Stream and Functional programming concepts-based interview questions. Since Java 8 is now the modern way of writing Java ...

  14. Java 8 Stream API Commonly Asked Interview Questions

    Java Streams can be used to process a series of components and are essentially a pipeline of aggregating operations. In this article, I have explained some Java 8 stream API coding questions that ...

  15. Guide to Java Streams: forEach() with Examples

    The forEach() method is a really useful method to use to iterate over collections in Java in a functional approach. In certain cases, they can massively simplify the code and enhance clarity and brevity. In this article, we've gone over the basics of using a forEach() and then covered examples of the method on a List, Map and Set.

  16. Java I/O Streams

    In Java, streams are the sequence of data that are read from the source and written to the destination. Courses Tutorials Examples . Try Programiz PRO. Course Index Explore Programiz Python JavaScript SQL HTML R C C++ Java RUST Golang Kotlin Swift C# DSA. Learn Java practically and Get Certified.

  17. Java Stream API Interview Questions and Answers

    Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. You can use Stream to filter, collect, print, and convert from one data structure to another, etc. Stream does not store elements.

  18. Java Stream: Exercises, Practice, Solutions

    Write a Java program to calculate the sum of all even, odd numbers in a list using streams. Click me to see the solution. 4. Write a Java program to remove all duplicate elements from a list using streams. Click me to see the solution. 5. Write a Java program to count the number of strings in a list that start with a specific letter using streams.

  19. Java 8 Stream API Interview Questions and Answers

    Stream API is one of the hot topics to be chosen by the interviewer in interviews. Let us read and know the most used concepts of stream API questions. Let us see some of the questions and answers ...

  20. Java-Stream-programs Archives

    Convert Stream to Set in Java. Last Updated: 11 December 2018. Below given are some methods which can be used to convert Stream to Set in Java.Method 1 : Using CollectorsStream collect () method takes ele ...read more. Misc.

  21. Using Java Streams to Determine Max and Min Dates in a List

    Java Streams offer a powerful way to perform operations on collections of data. When working with a list of objects that contain date fields, we may need to use a Java list stream to find the maximum and minimum dates. This article will guide us through finding both the maximal and minimal dates using Java Streams. 1. Example Setup

  22. Java Stream API Coding Interview Questions and Answers

    Now, let's dive into the world of Java Stream API interview coding questions and uncover the secrets to mastering this powerful API! Write a program to find the sum of all elements in a list ...