You are on page 1of 16

Java 8 Feature „Streams‟

A
Seminar
submitted
in partial fulfillment
for the award of the Degree of
Bachelor of Technology
in Department of Computer Science & Engineering

Submitted To: Submitted By:

Mr. Amit Mishra Payal Tikyani


Sr. Asst. Professor 8th Semester, 4th Year
Department of CSE, JIET Department of CSE, JIET

Department of Computer Science &Engineering

Jodhpur Institute of Engineering & Technology

Rajasthan Technical University


March 2019
Candidate’s Declaration

I hereby declare that the work, which is being presented in the Seminar, entitled “Java 8 Feature
Streams” in partial fulfillment for the award of Degree of “Bachelor of Technology” in Computer
Science & Engineering and submitted to the Department of Computer Science & Engineering,
Jodhpur Institute of Engineering & Technology, Rajasthan Technical University is a record of my own
WORK carried under the Guidance of Ms. Vinita Mathur, Associate Prof., Department of Computer
Science & Engineering.

Payal Tikyani
Computer Science
University Roll No: 15EJICS080
Jodhpur Institute of Engineering & Technology

Counter Signed by

Ms. Vinita Mathur


Associate Prof.,
Department of CSE, JIET

II
ACKNOWLEDGEMENT

It gives me immense pleasure and satisfaction in presenting this seminar report on the research topic
named “Java 8 Feature Streams”. I would like to take this opportunity to express my Sincere gratitude
to several people, without whose help and encouragement, it would had been impossible for me to
carry out the desired work.

I would like to express my sincere thanks to Ms. Vinita Mathur, seminar guide, for her invaluable
guidance throughout the research work. I am indebted for her guidance, encouragement, understanding
and insightful support in the documentation process and overall guidance.

Last but not the least I would like to thank my friends for their support and continuous encouragement
throughout the work.

With extreme regards and obligation.

Payal Tikyani
15EJICS080
Computer Science & Engineering

III
ABSTRACT
The Java Stream API provides a functional approach to processing collections of objects. The Java
Stream API was added in Java 8 along with several other functional programming features.

Introduction to the chapters mentioned below :

Chapter 1: Introduction to Streams


This chapter describes the brief overview and introduction of Streams.

Chapter 2: Creation of Streams

This chapter discusses the ways for creating streams in Java 8 with different use of them.

Chapter 3: Operations on Streams


This chapter describes the operations that are to be performed on streams for better use of
collection framework.

Chapter 4: Parallel Streams


This chapter includes the information about more functionality of sreams which are of much use
in current scenario.

IV
TABLE OF CONTENTS

Acknowledgment _________________________________________________________iii

Abstract_ __________________________________________________________________iv

Table of Contents____________________________________________________________v

List of Tables_______________________________________________________________vi

List of Figures______________________________________________________________vii

1. Introduction ________________________________________________________________1

2. Literature survey____________________________________________________________2

3. Chapters Describing the work__________________________________________________3


1. Introduction to Streams____________________________________________________3
2. Creation of Streams_______________________________________________________6
3. Operation on Streams_____________________________________________________7
4. Parallel Streams_________________________________________________________9
4. Conclusions_________________________________________________________________10

References_____________________________________________________________________11

V
INTRODUCTION

Java 8 introduced Java Streams which allows us to express data processing queries in a short functional and
elegant way.
Simply put, streams are wrappers around a data source, allowing us to operate with that data source and making
bulk processing convenient and fast.
A stream does not store data and, in that sense, is not a data structure. It also never modifies the underlying data
source.
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.
 Internal iteration: In contrast to collections, which are iterated explicitly (external iteration), stream
operations do the iteration behind the scenes for you.

1
LITERATURE SURVEY

1. “Java 8 Lambdas in Action”

Java 8 Lambdas in Action is probably the best book to learn Java 8 features. It's one of the clearly-
written guides to Java 8 lambdas and functional programming in Java. It begins with a practical
introduction to the structure and benefits of lambda expressions in real-world Java code.

The book then introduces the Stream API and shows how it can make the collections-related code
radically easier to understand and maintain.

2. “Processing Data with Java SE 8 Streams” by Raoul-Gabriel Urma

This article shows 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 we would process collections before Java SE 8.

2
CHAPTERS DESCRIBING THE WORK

 Chapter 1: Introduction to Streams


Java 8 introduced Java Streams which allows us to express data processing queries in a short functional and
elegant way and stored in java.util.stream package which perform filter/map/reduce like operations with the
collection. Stream API will allow sequential as well as parallel execution.

Collection interface has been extended with stream() and parallelStream() default methods to get the Stream
for sequential and parallel execution.

Simply put, streams are wrappers around a data source, allowing us to operate with that data source and
making bulk processing convenient and fast.

A stream does not store data and, in that sense, is not a data structure. It also never modifies the underlying
data source.

A Java Stream is a component that is capable of internal iteration of its elements, meaning it can iterate its
elements itself. In contrast, when we are using the Java Collections iteration features (e.g a Java Iterator or
the Java for-each loop used with a Java Iterable) we have to implement the iteration of the elements by
ourself.

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.
 Internal iteration: In contrast to collections, which are iterated explicitly (external iteration), stream
operations do the iteration behind the scenes for you.

3
Stream Processing:-
We can attach listeners to a Stream. These listeners are called when the Stream iterates the elements internally. The
listeners are called once for each element in the stream. That way each listener gets to process each element in the
stream. This is referred to as stream processing.

The listeners of a stream form a chain. The first listener in the chain can process the element in the stream, and
then return a new element for the next listener in the chain to process. A listener can either return the same element
or a new, depending on what the purpose of that listener (processor) is.

Classification of streams:-
Input and output streams:-
 Based on the direction of data flow, streams can be categorized as input streams and output streams.

Byte and character streams:-

Based on the type of data we can classify streams as byte streams and text streams (aka character streams).

 Byte streams:-

o represent data in the form of bytes.

o All byte stream classes are descended from InputStream and OutputStream.

o Class names of byte streams end with the word stream as in FileInputStream and FileOutputStream.

 Text streams (or character streams):-

o represent data as characters.

o All character stream classes are descended from Reader and Writer.

o Class names of text streams end with the word „Reader‟ or „Writer‟ as in FileReader and FileWriter.

o Java stores character values using Unicode conventions. Text streams automatically convert the
Unicode internal format to and from the local character set.

Wrapper streams:-
 One stream may wrap around another stream to add some functionality to the inner stream or to make the
inner stream do some low level tasks.

 Filter streams wrap around other streams and transform the data providing additional functionality.

4
 Subclasses of FilterInputStream are BufferedInputStream, CheckedInputStream, CipherInputStream,
DataInputStream, DeflaterInputStream, DigestInputStream, InflaterInputStream, LineNumberInputStream,
ProgressMonitorInputStream and PushbackInputStream.

 Subclasses of FilterOutputStream are BufferedOutputStream, CheckedOutputStream, CipherOutputStream,


DataOutputStream, DeflaterOutputStream, DigestOutputStream and InflaterOutputStream.

Markable streams:-

Markable streams provide the capability to mark a position in the stream and then later reset the stream so that it
can be reread from the marked position.

 The markSupported() method returns true if the stream is markable.

 The mark() method marks a position in the stream and it takes the buffer capacity as an integer parameter.

o The buffer memory is used to keep track of the data between the mark and the current position and
when this buffer memory is exceeded, the mark becomes invalid.

 The reset() method simply repositions the stream to its last marked position.

5
 Chapter 2 : Creation of Streams

To get started with Streams, we need a method to create them. Here are five ways to create a Stream in Java 8.

1. Creating a Stream from a Collection:-


Probably the most obvious method is to create a Stream from a Collection. This is the interface that lists, sets,
queues and the like implement. With the introduction of Java 8 and default methods, a method called stream()
was added to the Collection interface. It returns a sequential Stream with the collection as its source.

2. Creating a Stream from arrays:-


Arrays don‟t have the same convenient methods that Collections have. Therefore to create a stream from an
array, you need to use the static method stream() in the Arrays class.
In addition to general Streams, the Arrays class contains overloaded methods for specialized streams as well.
These are streams that can be used with Java‟s primitive types. Giving the stream() method an array of primitive
types returns a specialized stream.

3. Creating a Stream from values:-


Instead of creating an array or a collection and then converting it into a Stream, it is possible to create a Stream
directly using the static method of() in the Stream interface.

4. Creating a Stream from files:-


Java 8 allows to create a Stream from a file. The java.nio.file.Files class contains several static methods which
return a Stream of the file contents.
Alternatively, if we are not interested in a particular file but rather in a directory in the file
system, Files.list() method can create a lazily populated Stream of the elements that are the entries in the
directory.

5. Creating a stream from functions:-


Two static methods in the Stream interface allow you to create infinite Streams. Yes, that‟s right. Unlike a
Collection or an array, a Stream can have no bounds. The methods are iterate() and generate().

 Iterate
Iterate accepts an initial element and a function which is applied to the previous element to produce the
next element.

 Generate
Generate accepts a Supplier to generate an infinite Stream of unsorted elements. This method is good for
generating a Stream of random elements.

6
 Chapter 3: Operations on Streams
The Stream interface in java.util .stream.Stream defines many operations, which can be grouped in two categories.
 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).
This distinction of operations 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.

Java 8 Stream intermediate operations return another Stream which allows you to call multiple operations in a form
of a query. Stream intermediate operations do not get executed until a terminal operation is invoked. All
Intermediate operations are lazy, so they‟re not executed until a result of a processing is actually needed. Traversal
of the Stream does not begin until the terminal operation of the pipeline is executed.
Here is the list of all Stream intermediate operations:
 filter()
 map()
 flatMap()
 distinct()
 sorted()
 peek()
 limit()
 skip()

Some of the intermediate operations in detail for the processing are:-

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

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.

7
Java-8 Stream terminal operations produces a non-stream, result such as primitive value, a collection or no value at
all. Terminal operations are typically preceded by intermediate operations which return another Stream which
allows operations to be connected in a form of a query.
Here is the list of all Stream terminal operations:-

 toArray()
 collect()
 count()
 reduce()
 forEach()
 forEachOrdered()
 min()
 max()
 anyMatch()
 allMatch()
 noneMatch()
 findAny()
 findFirst()

Some of the terminal operations in detail for the processing are:-

Finding and matching:-


A common data processing pattern is determining whether some elements match a given property. We can use
the anyMatch, allMatch, and noneMatch operations to help us do this. They all take a predicate as an argument and
return a boolean as the result (they are, therefore, terminal operations).
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.

Reducing:-
The Java Stream reduce() method is a terminal operation that can reduce all elements in the stream to a single
element.

Min and Max:-


 min():- The Java Stream min() method is a terminal operation that returns the smallest element in the
Stream. Which element is the smallest is determined by the Comparator implementation you pass to the
min() method.
 max():- The Java Stream max() method is a terminal operation that returns the largest element in the
Stream. Which element is the largest is determined by the Comparator implementation you pass to the
max() method.

8
 Chapter 4: Parallel Streams

Before Java 8, parallelization was complex. Emerging of the ExecutorService and


the ForkJoin simplified developer‟s life a little bit, but they still should keep in mind 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 creating 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 stream is something different 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 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 and use parallel mode when tasks
need the 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

Java SE 8 introduces the Streams API, which lets us express sophisticated data processing queries. We‟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 we
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 our data processing queries. Second, streams
can be parallelized automatically to leverage multicore architectures.

We saw various operations supported and how lambdas and pipelines can be used to write concise code. We
also saw some characteristics of streams like lazy evaluation, parallel and infinite streams.

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

10
REFERENCES

1. https://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html
2. https://dzone.com/articles/a-guide-to-streams-in-java-8-in-depth-tutorial-wit
3. https://www.journaldev.com/2389/java-8-features-with-examples
4. https://www.youtube.com/watch?v=b0On2gN020k&list=PLsyeobzWxl7otduRddQWYTQezVul0xI
X6&index=14

11

You might also like