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
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

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

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

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

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
  • Thread-Safety Pitfalls in XML Processing

Trending

  • How to Build Scalable Mobile Apps With React Native: A Step-by-Step Guide
  • How to Format Articles for DZone
  • Unlocking Data with Language: Real-World Applications of Text-to-SQL Interfaces
  • Blue Skies Ahead: An AI Case Study on LLM Use for a Graph Theory Related Application
  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
  • Thread-Safety Pitfalls in XML Processing

Partner Resources

×

Comments

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: