0% found this document useful (0 votes)
71 views13 pages

Stream API Abw

Stream API allows processing objects from a collection. Java.util.streams process collection objects while java.io streams process binary/character file data. A collection can be converted to a stream using the stream() method to then filter, map, or otherwise process the objects. Streams have two phases - configuration using filter/map and processing using methods like collect(), count(), sorted(), min/max(), forEach(), and toArray().

Uploaded by

Trip Photos
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
71 views13 pages

Stream API Abw

Stream API allows processing objects from a collection. Java.util.streams process collection objects while java.io streams process binary/character file data. A collection can be converted to a stream using the stream() method to then filter, map, or otherwise process the objects. Streams have two phases - configuration using filter/map and processing using methods like collect(), count(), sorted(), min/max(), forEach(), and toArray().

Uploaded by

Trip Photos
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 13

Stream API

To process objects of the collection, in 1.8 version Streams concept


introduced.

What is the differences between java.util.streams and java.io streams?


java.util streams meant for processing objects from the collection. Ie, it
represents a stream of objects from the collection but java.io streams meant
for processing binary and character data with respect to file. i.e it
represents stream of binary data or character data from the file .hence
java.io streams and java.util streams both are different.

What is the difference between collection and stream?


if we want to represent a group of individual objects as a single entity then
we should go for collection.
if we want to process a group of objects from the collection then we should
go for streams.
we can create a stream object to the collection by using stream()method of
Collection interface.
stream() method is a default method added to the Collection in 1.8 version.

default Stream stream()


Ex:
Stream s = c.stream();
Stream is an interface pre sent in java.util.stream.
once we got the stream, by using that we can process objects of that
collection.
we can process the objects in the following two phases
1.configuration
2.processing

1. configuration:
we can configure either by using filter mechanism or by using map mechanism.
Filtering:
we can configure a filter to filter elements from the collection based on some
boolean condition by using filter()method of Stream interface.
public Stream filter(Predicate<T> t)
here (Predicate<T > t ) can be a Boolean valued function/lambda expression
Ex:
Stream s=c.stream();
Stream s1=s.filter(i -> i%2==0);
Hence to filter elements of collection based on some boolean condition we
should go for filter()method.
Mapping:
If we want to create a separate new object, for every object present in the
collection based on our requirement then we should go for map () method of
Stream interface.
public Stream map (Function f); It can be lambda expression also

Ex:
Stream s = c.stream();

Stream s1 = s.map(i-> i+10);

Once we performed configuration we can process objects by using several


methods.

2. Processing
A) processing by collect() method
B) Processing by count()method
C) Processing by sorted()method
D) Processing by min() and max() methods
E) forEach() method
F) toArray() method
G) Stream.of()method

A) processing by collect() method


This method collects the elements from the stream and adding to the specified
to the collection indicated (specified)by argument.
Ex:1
To collect only even numbers from the array list

import java.util.*;

import java.util.stream.*;

class Test {

public static void main(String[] args) {

ArrayList<Integer> l1 = new ArrayList<Integer>();

for(inti=0; i<=10; i++) {

l1.add(i);
}

System.out.println(l1);

List<Integer> l2 = l1.stream().filter(i -> i%2==0).collect(Collectors.toList());

System.out.println(l2);

Ex: Program for map() and collect() Method


import java.util.*;

import java.util.stream.*;

class Test {

public static void main(String[] args) {

ArrayList<String> l = new ArrayList<String>();

l.add("rvk"); l.add("rk"); l.add("rkv"); l.add("rvki"); l.add("rvkir");

System.out.println(l);

List<String> l2 = l.Stream().map(s ->s.toUpperCase()).collect(Collectors.toList());

System.out.println(l2);

The Stream.collect() Method

Stream.collect() is one of the Java 8's Stream API‘s terminal methods. It allows


us to perform mutable fold operations (repackaging elements to some data
structures and applying some additional logic, concatenating them, etc.) on data
elements held in a Stream instance.

The strategy for this operation is provided via the Collector interface


implementation.

AD

3. Collectors

All predefined implementations can be found in the Collectors class. It's common


practice to use the following static import with them to leverage increased
readability:
import static java.util.stream.Collectors.*;

We can also use single import collectors of our choice:

import static java.util.stream.Collectors.toList;

import static java.util.stream.Collectors.toMap;

import static java.util.stream.Collectors.toSet;

In the following examples, we'll be reusing the following list:

List<String> givenList = Arrays.asList("a", "bb", "ccc", "dd");

3.1. Collectors.toList()

The  toList collector can be used for collecting all Stream elements into


a List instance. The important thing to remember is that we can't assume any
particular List implementation with this method. If we want to have more control
over this, we can use toCollection  instead.

Let's create a Stream instance representing a sequence of elements, and then


collect them into a List instance:

AD

List<String> result = givenList.stream()

.collect(toList());

3.1.1. Collectors.toUnmodifiableList()

Java 10 introduced a convenient way to accumulate the Stream elements into


an unmodifiable List:

List<String> result = givenList.stream()

.collect(toUnmodifiableList());

Now if we try to modify the result List, we'll get


an UnsupportedOperationException:

assertThatThrownBy(() -> result.add("foo"))

.isInstanceOf(UnsupportedOperationException.class);

3.2. Collectors.toSet()

The  toSet collector can be used for collecting all Stream elements into


a Set instance. The important thing to remember is that we can't assume any
particular Set implementation with this method. If we want to have more control
over this, we can use toCollection  instead.

Let's create a Stream instance representing a sequence of elements, and then


collect them into a Set instance:

Set<String> result = givenList.stream()

.collect(toSet());

A Set doesn't contain duplicate elements. If our collection contains elements


equal to each other, they appear in the resulting Set only once:

AD

List<String> listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb");

Set<String> result = listWithDuplicates.stream().collect(toSet());

assertThat(result).hasSize(4);

3.2.1. Collectors.toUnmodifiableSet()

Since Java 10, we can easily create an unmodifiable Set using


the toUnmodifiableSet() collector:

Set<String> result = givenList.stream()

.collect(toUnmodifiableSet());

Any attempt to modify the result Set will end up with


an UnsupportedOperationException:

assertThatThrownBy(() -> result.add("foo"))

.isInstanceOf(UnsupportedOperationException.class);

3.3. Collectors.toCollection()

As we've already noted, when using the toSet  and toList collectors, we can't make


any assumptions of their implementations. If we want to use a custom
implementation, we'll need to use the toCollection collector with a provided
collection of our choice.

Let's create a Stream instance representing a sequence of elements, and then


collect them into a LinkedList instance:

List<String> result = givenList.stream()

.collect(toCollection(LinkedList::new))
Notice that this will not work with any immutable collections. In such a case, we
would need to either write a custom Collector implementation or
use collectingAndThen.

3.4. Collectors.toMap()

The  toMap collector can be used to collect Stream elements into a Map instance.


To do this, we need to provide two functions:

 keyMapper
 valueMapper

We'll use  keyMapper to extract a  Map key from a Stream element,


and  valueMapper to extract a value associated with a given key.

Let's collect those elements into a Map that stores strings as keys and their
lengths as values:

AD

Map<String, Integer> result = givenList.stream()

.collect(toMap(Function.identity(), String::length))

Function.identity() is just a shortcut for defining a function that accepts and


returns the same value.

So what happens if our collection contains duplicate elements? Contrary


to toSet, toMap doesn't silently filter duplicates, which is understandable
because how would it figure out which value to pick for this key?

List<String> listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb");

assertThatThrownBy(() -> {

listWithDuplicates.stream().collect(toMap(Function.identity(), String::length));

}).isInstanceOf(IllegalStateException.class);

Note that toMap doesn't even evaluate whether the values are also equal. If it
sees duplicate keys, it immediately throws an IllegalStateException.

In such cases with key collision, we should use toMap with another signature:

Map<String, Integer> result = givenList.stream()

.collect(toMap(Function.identity(), String::length, (item, identicalItem) -> item));

The third argument here is a BinaryOperator, where we can specify how we want
collisions to be handled. In this case, we'll just pick any of these two colliding
values because we know that the same strings will always have the same lengths
too.

3.4.1. Collectors.toUnmodifiableMap()

Similar to with Lists and Sets, Java 10 introduced an easy way to


collect Stream elements into an unmodifiable Map:

Map<String, Integer> result = givenList.stream()

.collect(toMap(Function.identity(), String::length))

As we can see, if we try to put a new entry into a result Map, we'll get
an UnsupportedOperationException:

assertThatThrownBy(() -> result.put("foo", 3))

.isInstanceOf(UnsupportedOperationException.class);

3.5. Collectors.collectingAndThen()

CollectingAndThen is a special collector that allows us to perform another action


on a result straight after collecting ends.

AD

Let's collect Stream elements to a List instance, and then convert the result into


an ImmutableList instance:

List<String> result = givenList.stream()

.collect(collectingAndThen(toList(), ImmutableList::copyOf))

3.6. Collectors.joining()

Joining collector can be used for joining Stream<String> elements.

We can join them together by doing:

String result = givenList.stream()

  .collect(joining());

This will result in:

"abbcccdd"

We can also specify custom separators, prefixes, postfixes:

String result = givenList.stream()

.collect(joining(" "));
This will result in:

"a bb ccc dd"

We can also write:

String result = givenList.stream()

.collect(joining(" ", "PRE-", "-POST"));

This will result in:

AD

"PRE-a bb ccc dd-POST"

3.7. Collectors.counting()

Counting is a simple collector that allows for the counting of


all Stream elements.

Now we can write:

Long result = givenList.stream()

.collect(counting());

3.8. Collectors.summarizingDouble/Long/Int()

SummarizingDouble/Long/Int is a collector that returns a special class containing


statistical information about numerical data in a  Stream of extracted elements.

We can obtain information about string lengths by doing:

DoubleSummaryStatistics result = givenList.stream()

.collect(summarizingDouble(String::length));

In this case, the following will be true:

assertThat(result.getAverage()).isEqualTo(2);

assertThat(result.getCount()).isEqualTo(4);

assertThat(result.getMax()).isEqualTo(3);

assertThat(result.getMin()).isEqualTo(1);

assertThat(result.getSum()).isEqualTo(8);

3.9. Collectors.averagingDouble/Long/Int()
AveragingDouble/Long/Int is a collector that simply returns an average of
extracted elements.

We can get the average string length by doing:

Double result = givenList.stream()

.collect(averagingDouble(String::length));

3.10. Collectors.summingDouble/Long/Int()

SummingDouble/Long/Int is a collector that simply returns a sum of extracted


elements.

AD

We can get the sum of all string lengths by doing:

Double result = givenList.stream()

.collect(summingDouble(String::length));

3.11. Collectors.maxBy()/minBy()

MaxBy/MinBy collectors return the biggest/smallest element of a Stream according


to a provided Comparator instance.

We can pick the biggest element by doing:

Optional<String> result = givenList.stream()

.collect(maxBy(Comparator.naturalOrder()));

We can see that the returned value is wrapped in an Optional instance. This forces
users to rethink the empty collection corner case.

3.12. Collectors.groupingBy()

GroupingBy collector is used for grouping objects by some property, and then


storing the results in a Map instance.

We can group them by string length, and store the grouping results
in Set instances:

Map<Integer, Set<String>> result = givenList.stream()

.collect(groupingBy(String::length, toSet()));
This will result in the following being true:

assertThat(result)

.containsEntry(1, newHashSet("a"))

.containsEntry(2, newHashSet("bb", "dd"))

.containsEntry(3, newHashSet("ccc"));

We can see that the second argument of the groupingBy method is a Collector. In


addition, we're free to use any Collector of our choice.

AD

3.13. Collectors.partitioningBy()

PartitioningBy is a specialized case of groupingBy that accepts


a Predicate instance, and then collects Stream elements into a Map instance that
stores Boolean values as keys and collections as values. Under the “true” key, we
can find a collection of elements matching the given Predicate, and under the
“false” key, we can find a collection of elements not matching the
given Predicate.

We can write:

Map<Boolean, List<String>> result = givenList.stream()

.collect(partitioningBy(s -> s.length() > 2))

This results in a Map containing:

{false=["a", "bb", "dd"], true=["ccc"]}

3.14. Collectors.teeing()

Let's find the maximum and minimum numbers from a given Stream using the
collectors we've learned so far:

List<Integer> numbers = Arrays.asList(42, 4, 2, 24);

Optional<Integer> min = numbers.stream().collect(minBy(Integer::compareTo));

Optional<Integer> max = numbers.stream().collect(maxBy(Integer::compareTo));

// do something useful with min and max

Here we're using two different collectors, and then combining the results of those
two to create something meaningful. Before Java 12, in order to cover such use
cases, we had to operate on the given Stream twice, store the intermediate results
into temporary variables, and then combine those results afterwards.

Fortunately, Java 12 offers a built-in collector that takes care of these steps on
our behalf; all we have to do is provide the two collectors and the combiner
function.

Since this new collector tees the given stream towards two different directions,
it's called teeing:

numbers.stream().collect(teeing(

minBy(Integer::compareTo), // The first collector

maxBy(Integer::compareTo), // The second collector

(min, max) -> // Receives the result from those collectors and combines them

));

B) Processing by count()method
this method returns number of elements present in the stream.
public long count()

Ex:
long count=l.stream().filter(s ->s.length()==5).count();

sop(“the number of 5 length strings is:”+count);

C) Processing by sorted()method
if we sort the elements present inside stream then we should go for sorted()
method.

the sorting can either default natural sorting order or customized sorting
order specified by comparator.
sorted()- default natural sorting order
sorted(Comparator c)-customized sorting order.
Ex:
List<String> l3=l.stream().sorted().collect(Collectors.toList());

sop(“according to default natural sorting order:”+l3);

List<String> l4=l.stream().sorted((s1,s2)->s1.compareTo(s2)).collect(Collectors.toList());

sop(“according to customized sorting order:”+l4);

D) Processing by min() and max() methods


min(Comparator c)

returns minimum value according to specified comparator.


max(Comparator c)
returns maximum value according to specified comparator
Ex:
String min=l.stream().min((s1,s2) -> s1.compareTo(s2)).get();

sop(“minimum value is:”+min);

String max=l.stream().max((s1,s2) -> s1.compareTo(s2)).get();

sop(“maximum value is:”+max);

E) forEach() method
this method will not return anything.
this method will take lambda expression as argument and apply that lambda
expression for each element present in the stream.
Ex:
l.stream().forEach(s->sop(s));

l3.stream().forEach(System.out:: println);

Ex:
import java.util.*;

import java.util.stream.*;

class Test1 {

public static void main(String[] args) {

ArrayList<Integer> l1 = new ArrayaList<Integer>();

l1.add(0); l1.add(15); l1.add(10); l1.add(5); l1.add(30); l1.add(25); l1.add(20);

System.out.println(l1);

ArrayList<Integer> l2=l1.stream().map(i-> i+10).collect(Collectors.toList());

System.out.println(l2);

long count = l1.stream().filter(i->i%2==0).count();


System.out.println(count);

List<Integer> l3=l1.stream().sorted().collect(Collectors.toList());

System.out.println(l3);

Comparator<Integer> comp=(i1,i2)->i1.compareTo(i2);

List<Integer> l4=l1.stream().sorted(comp).collect(Collectors.toList());

System.out.println(l4);

Integer min=l1.stream().min(comp).get();

System.out.println(min);

Integer max=l1.stream().max(comp).get();

System.out.println(max);

l3.stream().forEach(i->sop(i));

l3.stream().forEach(System.out:: println);

}
F) toArray() method
we can use toArray() method to copy elements present in the stream into
specified array
Integer[] ir = l1.stream().toArray(Integer[] :: new);

for(Integer i: ir) {

sop(i);

G) Stream.of()method
we can also apply a stream for group of values and for arrays.
Ex:
Stream s=Stream.of(99,999,9999,99999);

s.forEach(System.out:: println);

Double[] d={10.0,10.1,10.2,10.3};

Stream s1=Stream.of(d);

s1.forEach(System.out :: println);

You might also like