DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • The Complete Guide to Stream API and Collectors in Java 8
  • Anatomy of Sequential Data Processing With Java Streams
  • Bridge the Gap of Zip Operation
  • Using Java Stream Gatherers To Improve Stateful Operations

Trending

  • Modern Test Automation With AI (LLM) and Playwright MCP
  • Event-Driven Microservices: How Kafka and RabbitMQ Power Scalable Systems
  • Apple and Anthropic Partner on AI-Powered Vibe-Coding Tool – Public Release TBD
  • Secrets Sprawl and AI: Why Your Non-Human Identities Need Attention Before You Deploy That LLM
  1. DZone
  2. Data Engineering
  3. Databases
  4. Become a Master of Java Streams — Part 1: Creating Streams

Become a Master of Java Streams — Part 1: Creating Streams

Check out the article below to become a master of Java Streams!

By 
Per-Åke Minborg user avatar
Per-Åke Minborg
·
Julia Gustafsson user avatar
Julia Gustafsson
·
Updated Oct. 15, 19 · Tutorial
Likes (39)
Comment
Save
Tweet
Share
52.7K Views

Join the DZone community and get the full member experience.

Join For Free

Java streams

Check out the article below to become a master of Java Streams!

Declarative code (e.g. functional composition with Streams) provides superior code metrics in many cases. Code your way through this hands-on-lab article series and mature into a better Java programmer by becoming a Master of Java Streams.

The whole idea with Streams is to represent a pipeline through which data will flow and the pipeline's functions operate on the data. This way, functional-style operations on Streams of elements can be expressed. This article is the first out of five where you will learn firsthand how to become a Master of Streams. We start with basic stream examples and progress with more complex tasks until you know how to connect standard Java Streams to databases in the Cloud.

You may also like: Why Declarative Programming Makes You a Better Programmer

Once you have completed all five articles, you will be able to drastically reduce your codebase and know how to write pure Java code for the entire applications in a blink.

Here is a summary of the upcoming articles:

  • Part 1: Creating Streams
  • Part 2: Intermediate Operations
  • Part 3: Terminal Operations
  • Part 4: Database Streams
  • Part 5: Creating a Database Application Using Streams

Since we are firm believers in the concept of "learning by doing," the series is complemented by a GitHub repository that contains Stream exercises split into 5 units — each corresponding to the topic of an article. Instructions on how to use the source code are provided in the README-file.

What Are Java Streams?

The Java Stream interface was first introduced in Java 8 and, together with lambdas, acts as a milestone in the development of Java since it contributes greatly to facilitating a declarative (functional) programming style. If you want to learn more about the advantages of declarative coding we refer you to this article.

A Java Stream can be visualized as a pipeline through which data will flow (see the image below). The pipeline's functions will operate on the data by e.g. filtering, mapping, and sorting the items. Lastly, a terminal operation can be performed to collect the items in a preferred data structure such as a List, an Array, or a Map. An important thing to notice is that a Stream can only be consumed once.

A Stream Pipeline contains three main parts: the stream source, the intermediate operation(s) (zero to many), and terminal operation.

Let's have a look at an example to get a glimpse of what we will be teaching throughout this series. We encourage you to look at the code below and try to figure out what the print-statement will result in before reading the next paragraph.

List<String> list = Stream.of("Monkey", "Lion", "Giraffe","Lemur")
    .filter(s -> s.startsWith("L"))
    .map(String::toUpperCase)
    .sorted()
    .collect(toList());

System.out.println(list);


Since the Stream API is descriptive and most often intuitive to use, you will probably have a pretty good understanding of the meaning of these operations regardless if you have encountered them before or not. We start off with a Stream of a List containing four Strings, each representing an African animal. The operations then filter out the elements that start with the letter "L", converts the remaining elements to uppercase letters, sorts them in natural order (which in this case means alphabetical order), and lastly collects them into a List. Hence, resulting in the output ["LEMUR", "LION"].

It is important to understand that Streams are "lazy" in the sense that elements are "requested" by the terminal operation (in this case the .collect() statement). If the terminal operation only needs one element (like, for example, the terminal operation .findFirst()), then, at most, one element is ever going to reach the terminal operation and the reminding elements (if any) will never be produced by the source. This also means that just creating a Stream is often a cheap operation whereas consuming it might be expensive, depending on the stream pipeline and the number of potential elements in the stream.

In this case, the Stream Source was a List although many other types can act as a data source. We will spend the rest of this article describing some of the most useful source alternatives.

Stream Sources

Streams are mainly suited for handling collections of objects and can operate on elements of any type T. Although, there exist three special Stream implementations: IntStream, LongStream, and DoubleStream, which are restricted to handle the corresponding primitive types.

An empty Stream of any of these types can be generated by calling Stream.empty() in the following manner:

Stream<T>     Stream.empty()
IntStream     IntStream.empty()
LongStream    LongStream.empty()
DoubleStream  DoubleStream.empty()


Empty Streams are indeed handy in some cases, but the majority of the time we are interested in filling our Stream with elements. This can be accomplished in a large number of ways. We will start by looking at the special case of an IntStream since it provides a variety of useful methods.

Useful IntStreams

A basic case is generating a Stream over a small number of items. This can be accomplished by listing the integers using  IntStream.of(). The code below yields a simple stream of elements 1, 2, and 3.

IntStream oneTwoThree = IntStream.of(1, 2, 3);


Listing all elements manually can be tedious if the number of items grows large. In the case where we are interested in values in a certain range, the command .rangeClosed() is more effective. The operation is inclusive, meaning that the following code will produce a stream of all elements from 1 to 9.

IntStream positiveSingleDigits = IntStream.rangeClosed(1, 9);


An even more powerful command is .iterate(), which enables greater flexibility in terms of what numbers to include. Below, we show an example of how it can be used to produce a Stream of all numbers that are powers of two.

IntStream powersOfTwo = IntStream.iterate(1, i -> i * 2);


There are also several perhaps more unexpected ways of producing a Stream. The method chars() can be used to Stream over the characters in a String, in this case, the elements "A", "B," and "C".

IntStream chars = "ABC".chars();


There is also a simple way to generate a Stream of random integers.

IntStream randomInts = new Random().ints();


Stream an Array

Streaming existing data collections is another option. We can stream the elements of an existing Array or choose to list items manually using Stream.of(), as previously shown and repeated below.

String[] array = {"Monkey", "Lion", "Giraffe", "Lemur"};
Stream<String> stream2 = Stream.of(array);

Stream<String> stream = Stream.of("Monkey", "Lion", "Giraffe", "Lemur"); 


Stream From a Collection

It is also very simple to stream any Collection. The examples below demonstrate how a List or Set can be streamed with the simple command .stream().

List<String> list = Arrays.asList("Monkey", "Lion", "Giraffe", "Lemur");
Stream<String> streamFromList = list.stream();
Set<String> set = new HashSet<>(list); 
Stream<String> streamFromSet = set.stream(); 


Stream From a Text File

Sometimes, it can also be useful to stream the contents of a text-file. The following command will provide a Stream that holds every line from the referenced file as a separate element.

Stream<String> lines = Files.lines(Paths.get("file.txt"));


Exercise

Now that we have familiarized you with some of the ways of creating a Stream, we encourage you to clone this GitHub repo and start practicing. The content of the article will be enough to solve the first Unit, which is called Create. The Unit1Create interface contains JavaDocs, which describes the intended implementation of the methods in Unit1MyCreate.

public interface Unit1Create {
 /**
  * Creates a new Stream of String objects that contains
  * the elements "A", "B" and "C" in order.
  *
  * @return a new Stream of String objects that contains
  *   the elements "A", "B" and "C" in order
  */
  Stream newStreamOfAToC();


The provided tests (e.g. Unit1MyCreateTest) will act as an automatic grading tool, letting you know if your solution was correct or not.

If you have not done so yet, go ahead and solve the work items in the Unit1MyCreate class. "Gotta catch 'em all."

In the next article, we will continue to describe several intermediate operations that can be applied to these Streams and that will convert them into other Streams. See you soon!

Further Reading

Why Declarative Programming Makes You a Better Programmer

A Guide to Streams: In-Depth Tutorial With Examples



If you enjoyed this article and want to learn more about Java Streams, check out this collection of tutorials and articles on all things Java Streams.

Stream (computing) Java (programming language) master Element Database application

Published at DZone with permission of Per-Åke Minborg, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Complete Guide to Stream API and Collectors in Java 8
  • Anatomy of Sequential Data Processing With Java Streams
  • Bridge the Gap of Zip Operation
  • Using Java Stream Gatherers To Improve Stateful Operations

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!