0% found this document useful (0 votes)
2 views

java8

The document discusses various built-in functional interfaces in Java, such as Runnable, Comparable, ActionListener, and Callable, introduced in Java SE 1.8. It explains commonly used functional interfaces like Function, Consumer, Supplier, Predicate, and BiFunction, along with their usage through code examples. Additionally, it covers stream operations, including creating streams, intermediate operations, and terminal operations, as well as Java 8 date and time APIs and the Optional class.

Uploaded by

findurmilarai
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

java8

The document discusses various built-in functional interfaces in Java, such as Runnable, Comparable, ActionListener, and Callable, introduced in Java SE 1.8. It explains commonly used functional interfaces like Function, Consumer, Supplier, Predicate, and BiFunction, along with their usage through code examples. Additionally, it covers stream operations, including creating streams, intermediate operations, and terminal operations, as well as Java 8 date and time APIs and the Optional class.

Uploaded by

findurmilarai
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 27

Name any four built-in Java Functional Interfaces?

Since Java SE 1.8 onwards, there are many interfaces that are converted into
functional interfaces.
All these interfaces are annotated with @FunctionalInterface. These interfaces are
as follows:

Runnable: The interface only contains the run() method.


Comparable: This interface only contains the compareTo() method.
ActionListener: This interface only contains the actionPerformed() method.
Callable: This interface only contains the call() method.

Explain some of the functional interfaces which are used in Java?


There are many functional interfaces that are used in Java. The following are
commonly used by the developers.

Function: Function is the most common functional interface out of all. It accepts
only one argument and returns a specified result

Consumer: It is the same as Function interface, Consumer is also a functional


interface that takes only one argument, and no result is returned by it.

Supplier: Supplier is a type of functional interface in Java that does not accept
any argument and still returns the desired result.

Predicate: The type of functional interface in Java that accepts one argument and
returns a boolean value is known as Predicate functional interface.

BiFunction: The Bi-Function is substantially related to a Function. Besides, it


takes two arguments, whereas Function accepts one argument. Just like Function, it
also returns a specified result.

Predicate is a functional interface, which accepts an argument and returns a


boolean.

@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}

Predicate<Integer> noGreaterThan5 = x -> x > 5;

package com.mkyong.java8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Java8Predicate {

public static void main(String[] args) {

Predicate<Integer> noGreaterThan5 = x -> x > 5;

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);


List<Integer> collect = list.stream()
.filter(noGreaterThan5)
.collect(Collectors.toList());

System.out.println(collect); // [6, 7, 8, 9, 10]

In Java 8, Function is a functional interface; it takes an argument (object of type


T) and returns an object (object of type R). The argument and output can be a
different type.

@FunctionalInterface
public interface Function<T, R> {

R apply(T t);

package com.mkyong;

import java.util.function.Function;

public class JavaMoney {

public static void main(String[] args) {

Function<String, Integer> func = x -> x.length();

Integer apply = func.apply("mkyong"); // 6

System.out.println(apply);

Chain Function<T, R>


This example chains the Function with andThen().

package com.mkyong;

import java.util.function.Function;

public class Java8Function2 {

public static void main(String[] args) {

Function<String, Integer> func = x -> x.length();

Function<Integer, Integer> func2 = x -> x * 2;


Integer result = func.andThen(func2).apply("mkyong"); // 12

System.out.println(result);

In Java 8, Consumer is a functional interface; it takes an argument and returns


nothing.

@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}

package com.mkyong.java8;

import java.util.function.Consumer;

public class Java8Consumer1 {

public static void main(String[] args) {

Consumer<String> print = x -> System.out.println(x);


print.accept("java"); // java

In Java 8, Supplier is a functional interface; it takes no arguments and returns a


result.

Supplier.java

@FunctionalInterface
public interface Supplier<T> {
T get();
}

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.function.Supplier;

public class Java8Supplier1 {

private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-


MM-dd HH:mm:ss");

public static void main(String[] args) {

Supplier<LocalDateTime> s = () -> LocalDateTime.now();


LocalDateTime time = s.get();

System.out.println(time);

Supplier<String> s1 = () -> dtf.format(LocalDateTime.now());


String time2 = s1.get();

System.out.println(time2);

Using distinct()
Create a List of Strings and call the stream() method to return a Stream of our
elements.

Call the distinct() method that returns a stream of the elements without
duplicates.

Collect the elements to a List by calling the Collectors.toList() in the collect()


method.

package com.Java2Code;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class FindDuplicateElementsUsingStream {


public static void main(String[] args){
List<String> cars = new ArrayList<>(
List.of(
"Mercedes",
"Toyota",
"Nissan",
"Volkswagen",
"Ford",
"Maclaren",
"Mercedes",
"Nissan",
"Ford"
)
);

List<String> distinctCars = cars.stream()


.distinct()
.collect(Collectors.toList());

for (String distinctCar : distinctCars) {


cars.remove(distinctCar);
}
cars.forEach(System.out::println);
}
}

import java.util.*;
import java.util.stream.Collectors;

public class FindDuplicateElementsUsingStream {


public static void main(String[] args){
List<String> languages = List.of(
"english",
"chinese",
"french",
"spanish",
"hindi",
"english",
"french"
);
Set<String> uniqueLanguages = new HashSet<>();
Set<String> duplicateLanguages = languages.stream()
.filter(language -> !uniqueLanguages.add(language))
.collect(Collectors.toSet());

duplicateLanguages.forEach(System.out::println);
}
}

Using Collectors.toMap()
The Collectors.toMap() method returns a Map, and we can find the duplicate elements
by counting the number of occurrences of the input arguments and storing them as
values in the Map.

package com.Java2Code;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FindDuplicateElementsUsingStream {


public static void main(String[] args){
List<String> computers = List.of(
"Dell",
"HP",
"IBM",
"Apple",
"HP",
"Apple"
);

Map<String, Integer> computerOccurrences = computers.stream()


.collect(Collectors
.toMap(Function.identity(), computer -> 1, Integer::sum));
System.out.println(computerOccurrences);
}
}

Using Collectors.groupingBy()
The Collectors.groupingBy() method groups elements based on a classification
function and returns the result in a Map.

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FindDuplicateElementsUsingStream {


public static void main(String[] args){
List<Employee> employees = List.of(
new Employee(1,"john","doe"),
new Employee(2,"peter","parker"),
new Employee(3,"mary","public"),
new Employee(4,"charles","darwin"),
new Employee(1,"john","doe"),
new Employee(3,"mary","public")
);

Set<Employee> duplicateEmployees= employees.stream()


.collect(Collectors
.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.filter(employee -> employee.getValue() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());

duplicateEmployees.forEach(System.out::println);
}
}

Stream Operations
Creating Streams
concat()
empty()
generate()
iterate()
of()

Intermediate Operations
filter()
map()
flatMap()
distinct()
sorted()
peek()
limit()
skip()

Stream.filter(): The Java Stream filter() method is one of the significant


operations under intermediate operations.
The filter() method accepts a Predicate to separate all components of the stream.
It is under intermediate operations because it enables the users to call another
stream operation (for example - Stream.forEach() method) on the result.
The predicate should declare true if the component is to be introduced in the final
Stream, and the Predicate will reflect false
if the component should not be included in the final stream.

Stream.map(): The intermediate operation Stream.map(), with the help of the given
function, transforms each component in the stream into some other object.
In simple words, the Stream.map() operation converts the element of a stream into
something else.
It takes the given function and applies that function to every element of the
stream, which at the end returns a stream of the values that are produced by the
parameter function.
Stream.map() also supports the user to create a calculation on the data inside a
Java stream. For example, if a user has a list of strings, the user can transform
each string from the given list to uppercase, lowercase, or to a substring of the
original string and something entirely else.

Stream.sorted(): The Java Stream sorted() method is also an intermediate operation


or method.
This sorted() operation returns a classified (or we can say the sorted) view of the
stream.
The components in the stream are sorted in a usual manner unless the user passes or
uses a custom Comparator
if they want to sort the stream in a different way.

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

Some of the Terminal operations which are used commonly in the Java programming
language are:

Stream.forEach(): The Java Stream forEach() method or operation is one of the


terminal operations in which starts the internal iteration of the components in the
stream. In simple words, the Java Stream forEach() method helps in repeating over
all of the components of a stream and execute some process on each of them. The
forEach() method returns nothing, or we can say void. The process to be performed
on the elements of the stream is transferred as the Java lambda expression.

Stream.collect(): The Java Stream.collect() method is practiced to take elements


from a stream and save all of them in a group. Stream collect() is a method to get
away from the environment of streams and receive a solid combination of values,
like an array list or a list. The Java Stream collect() method is a terminal
operation that starts the internal iteration of elements and collects the elements
in the stream in a collection or object of some kind.
Stream anyMatch(): The anyMatch() method of Java stream is also one of the terminal
operations that inputs a single Predicate or condition as a parameter and starts
the internal iteration of the Stream. The anyMatch() method implements the
Predicate parameter to every component of the Stream. If the given Predicate
reflects true for any of the components of the stream, the anyMatch() method yields
true. If no elements match the Predicate, anyMatch() will return false.

Stream allMatch(): The allMatch() method of Java stream is also one of the terminal
operations that inputs a single Predicate or condition as a parameter and starts
the internal iteration of the Stream. The allMatch() method implements the
Predicate parameter to every component of the Stream. If the given Predicate
reflects true for all of the components of the stream, the allMatch() method yields
true. If not all the elements match the Predicate, the allMatch() will return
false.

Stream noneMatch(): The noneMatch() method of Java stream is also one of the
terminal operations that inputs a single Predicate or condition as a parameter and
starts the internal iteration of the Stream. The noneMatch() method implements the
Predicate parameter to every component of the Stream. The noneMatch() method will
return true if no elements are matched by the Predicate and will return false if
one or more elements are matched with the predicate.

Stream.count(): The Java Stream count() method is also a terminal operation that
reflects the number of components present in the stream. The number of elements
present in the stream is produced and returned in the form of a long return type.
In simple words, the Java Stream count() method starts the internal iteration of
the elements in the Stream and counts the elements present in it.

Stream.reduce(): The Java Stream reduce() method is also a terminal operation that
helps in reducing all the components of the stream to only a single component. The
reduce() method performs a reduction on the components of the stream with the
provided function. The result of the reduce() method is an Optional (Optional is a
process of restoring a nullable T reference with a non-null value), which holds the
reduced value of the stream.

Java8DateTime.java

import java.util.*;
public class Java8DateTime {
public static void main(String[] args) {
System.out.println("Current Local Date: " + java.time.LocalDate.now());
//Used LocalDate API to get the date
System.out.println("Current Local Time: " + java.time.LocalTime.now());
//Used LocalTime API to get the time
System.out.println("Current Local Date and Time: " +
java.time.LocalDateTime.now());
//Used LocalDateTime API to get both date and time
}
}

Explain with example, LocalDate, LocalTime, and LocalDateTime APIs.


LocalDate

Date with no time component


Default format - yyyy-MM-dd (2020-02-20)
LocalDate today = LocalDate.now(); // gives today's date
LocalDate aDate = LocalDate.of(2011, 12, 30); //(year, month, date)
LocalTime
Time with no date with nanosecond precision
Default format - hh:mm:ss:zzz (12:06:03.015) nanosecond is optional
LocalTime now = LocalTime.now(); // gives time now
LocalTime aTime2 = LocalTime.of(18, 20, 30); // (hours, min, sec)
LocalDateTime

Holds both Date and Time


Default format - yyyy-MM-dd-HH-mm-ss.zzz (2020-02-20T12:06:03.015)
LocalDateTime timestamp = LocalDateTime.now(); // gives timestamp now
//(year, month, date, hours, min, sec)
LocalDateTime dt1 = LocalDateTime.of(2011, 12, 30, 18, 20, 30);

Java 8 has launched a unique class, Optional in java.util package. It can assist in
drafting a clean code without practicing multiple null tests. By working with
Optional, we can define substitute values to restore or alternate code to run. This
makes the code more understandable because the actions which were deceived are now
obvious to the developer.

Optional can also be defined as an object of container which might contains or not
contain a non-null value. You need to import the java.util package to run this
class. If the situation exists, isPresent () will return true and get () will
return the value. Additional methods based on the presence or absence of a value
obtained are introduced, such as orElse (), which provides the default value when
the value is not present, and ifPresent (), which creates a chunk of code when the
value is present. This is the category based on the number, that is, their cases:

Final and immutable (though may include references to mutable objects).


Acknowledged even individually based on equals(), not based on reference
equation(==).
Do not have available constructors.
Example

OptionalDemo.java

import java.util.Optional;
public class OptionalDemo{
public static void main(String[] args) {
String[] words = new String[15];
Optional<String> checkNull =
Optional.ofNullable(words[5]);
if (checkNull.isPresent()) {
String word = words[5].toLowerCase();
System.out.print(word);
} else
System.out.println("word is null");
}
}
Output:

word is null
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.
public class StreamBuilders
{
public static void main(String[] args)
{
Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9);
stream.forEach(p -> System.out.println(p));
}
}

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.

public class StreamBuilders


{
public static void main(String[] args)
{
Stream<Integer> stream = Stream.of( new Integer[]{1,2,3,4,5,6,7,8,9} );
stream.forEach(p -> System.out.println(p));
}
}

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

public class StreamBuilders


{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<Integer>();

for(int i = 1; i< 10; i++){


list.add(i);
}

Stream<Integer> stream = list.stream();


stream.forEach(p -> System.out.println(p));
}
}

Collect Stream elements to a List

public class StreamBuilders


{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<Integer>();

for(int i = 1; i< 10; i++){


list.add(i);
}

Stream<Integer> stream = list.stream();


List<Integer> evenNumbersList = stream.filter(i -> i%2 == 0)
.collect(Collectors.toList());
System.out.print(evenNumbersList);
}
}

Collect Stream elements to an Array

public class StreamBuilders


{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<Integer>();

for(int i = 1; i< 10; i++){


list.add(i);
}

Stream<Integer> stream = list.stream();


Integer[] evenNumbersArr = stream.filter(i -> i%2 ==
0).toArray(Integer[]::new);
System.out.print(evenNumbersArr);
}
}

Intermediate Operations

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

memberNames.stream().filter((s) -> s.startsWith("A"))


.forEach(System.out::println);

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.

memberNames.stream().filter((s) -> s.startsWith("A"))


.map(String::toUpperCase)
.forEach(System.out::println);

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.

memberNames.stream().sorted()
.map(String::toUpperCase)
.forEach(System.out::println)

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

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

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

List<String> memNamesInUppercase = memberNames.stream().sorted()


.map(String::toUpperCase)
.collect(Collectors.toList());

System.out.print(memNamesInUppercase);

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.

boolean matchedResult = memberNames.stream()


.anyMatch((s) -> s.startsWith("A"));

System.out.println(matchedResult);

matchedResult = memberNames.stream()
.allMatch((s) -> s.startsWith("A"));

System.out.println(matchedResult);

matchedResult = memberNames.stream()
.noneMatch((s) -> s.startsWith("A"));

System.out.println(matchedResult);

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

long totalMatched = memberNames.stream()


.filter((s) -> s.startsWith("A"))
.count();

System.out.println(totalMatched);

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 #.
Optional<String> reduced = memberNames.stream()
.reduce((s1,s2) -> s1 + "#" + s2);

reduced.ifPresent(System.out::println);

Stream Short-circuit Operations

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.

boolean matched = memberNames.stream()


.anyMatch((s) -> s.startsWith("A"));

System.out.println(matched);

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

String firstMatchedName = memberNames.stream()


.filter((s) -> s.startsWith("L"))
.findFirst()
.get();

System.out.println(firstMatchedName);

Streams.findLast()
Streams.findLast() is really neat, readable and provides good performance. It
returns the last element of the specified stream, or Optional.empty() if the stream
is empty.

Streams.findLast() example
Stream<Integer> stream = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)
.stream();

Integer lastElement = Streams.findLast(stream2).orElse(-1);

System.out.println(lastElement); // Prints 9
3. Infinite streams

What are the types of method references in Java

Java SE 8 allows a total of three types of method references. These are:

Static Method Reference: It is used to refer to static methods from a class.

Syntax of static method reference:

ClassName:: StaticMethodName
Reference to an Instance Method: In this type of method reference in Java, we can
refer to an instance method using a reference to the provided object and by
anonymous object also. We can also refer to methods by class object and
unidentified object.

The syntax of object instance method reference is:

ObjectName:: methodName
Reference to a Constructor: In this type of method reference in Java, we can refer
to a constructor using the new keyword. It references to a constructor can also be
done with the assistance of a functional interface.

The syntax of a reference to a constructor in method references in Java is:

className::new

Given a list of employees, you need to filter all the employee whose age is greater
than 20 and print the employee names.(Java 8 APIs only)

List<String> employeeFilteredList = employeeList.stream()


.filter(e->e.getAge()>20)
.map(Employee::getName)
.collect(Collectors.toList());

Given the list of employees, count number of employees with age 25?

List<Employee> employeeList = createEmployeeList();


long count = employeeList.stream()
.filter(e->e.getAge()>25)
.count();
System.out.println("Number of employees with age 25 are : "+count);

Given the list of employees, find the employee with name “Mary”.
Answer:
It is again very simple logic, change the main function in above class as
following.
List<Employee> employeeList = createEmployeeList();
Optional<Employee> e1 = employeeList.stream()
.filter(e->e.getName().equalsIgnoreCase("Mary")).findAny();

if(e1.isPresent())
System.out.println(e1.get());

Given a list of employee, find maximum age of employee?


Answer:
It is again very simple logic, change the main function in above class as
following.

List<Employee> employeeList = createEmployeeList();


OptionalInt max = employeeList.stream().
mapToInt(Employee::getAge).max();

if(max.isPresent())
System.out.println("Maximum age of Employee: "+max.getAsInt())
Given a list of employees, sort all the employee on the basis of age? Use java 8
APIs only
You can simply use sort method of list to sort the list of employees.

List<Employee> employeeList = createEmployeeList();


employeeList.sort((e1,e2)->e1.getAge()-e2.getAge());
employeeList.forEach(System.out::println)

Join the all employee names with “,” using java 8?


Answer:

List<Employee> employeeList = createEmployeeList();


List<String> employeeNames = employeeList
.stream()
.map(Employee::getName)
.collect(Collectors.toList());
String employeeNamesStr = String.join(",", employeeNames);
System.out.println("Employees are: "+employeeNamesStr);

Given the list of employee, group them by employee name?


Answer:
You can use Collections.groupBy() to group list of employees by employee name.

package org.arpit.java2blog;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MaximumUsingStreamMain {


public static void main(String args[])
{
List<Employee> employeeList = createEmployeeList();
Map<String, List<Employee>> map = employeeList.stream()
.collect(Collectors.groupingBy(Employ
ee::getName));
map.forEach((name,employeeListTemp)->System.out.println("Name: "+name+"
==>"+employeeListTemp));
}

public static List<Employee> createEmployeeList()


{
List<Employee> employeeList=new ArrayList<>();

Employee e1=new Employee("John",21);


Employee e2=new Employee("Martin",19);
Employee e3=new Employee("Mary",31);
Employee e4=new Employee("Mary",18);
Employee e5=new Employee("John",26);

employeeList.add(e1);
employeeList.add(e2);
employeeList.add(e3);
employeeList.add(e4);
employeeList.add(e5);

return employeeList;
}
}

Output:

Name: John ==>[Employee Name: John age: 21, Employee Name: John age: 26] Name:
Martin ==>[Employee Name: Martin age: 19] Name: Mary ==>[Employee Name: Mary age:
31, Employee Name: Mary age: 18]

23) Difference between Intermediate and terminal operations in Stream?


Answer:
Java 8 Stream supports both intermediate and terminal operation.

Intermediate operations are lazy in nature and do not get executed immediately.
Terminal operations are not lazy, they are executed as soon as encountered.
Intermediate operation is memorized and is called when terminal operation is
called.

All Intermediate operations return stream as it just transforms stream into another
and terminal operation don’t.

Example of Intermediate operations are:

filter(Predicate)
map(Function)
flatmap(Function)
sorted(Comparator)
distinct()
limit(long n)
skip(long n)
Example of terminal operations are :

forEach
toArray
reduce
collect
min
max
count
anyMatch
allMatch
noneMatch
findFirst
findAny

24) Given the list of numbers, remove the duplicate elements from the list.
Answer:
You can simply use stream and then collect it to set using Collections.toSet()
method.

package org.arpit.java2blog;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class RemoveDuplicatesFromListMain {


public static void main(String[] args)
{
Integer[] arr=new Integer[]{1,2,3,4,3,2,4,2};
List<Integer> listWithDuplicates = Arrays.asList(arr);

Set<Integer> setWithoutDups =
listWithDuplicates.stream().collect(Collectors.toSet());
setWithoutDups.forEach((i)->System.out.print(" "+i));
}
}

You can use distinct as well to avoid duplicates as following.


change main method of above program as below.

Integer[] arr=new Integer[]{1,2,3,4,3,2,4,2};


List<Integer> listWithDuplicates = Arrays.asList(arr);
List<Integer> listWithoutDups =
listWithDuplicates.stream().distinct().collect(Collectors.toList());
listWithoutDups.forEach((i)->System.out.print(" "+i));

25) Difference between Stream’s findFirst() and findAny()?


findFirst will always return the first element from the stream whereas findAny is
allowed to choose any element from the stream.
findFirst has deterministic behavior whereas findAny is nondeterministic behavior.

26) Given a list of numbers, square them and filter the numbers which are greater
10000 and then find average of them.( Java 8 APIs only)
Answer:
You can use the map function to square the number and then filter to avoid numbers
which are less than 10000.We will use average as terminating function in this case.

package org.arpit.java2blog;

import java.util.Arrays;
import java.util.List;
import java.util.OptionalDouble;

public class RemoveDuplicatesFromListMain {


public static void main(String[] args)
{
Integer[] arr=new Integer[]{100,24,13,44,114,200,40,112};
List<Integer> list = Arrays.asList(arr);
OptionalDouble average = list.stream()
.mapToInt(n->n*n)
.filter(n->n>10000)
.average();

if(average.isPresent())
System.out.println(average.getAsDouble());
}
}

output:

21846.666666666668

public class Main


{
public static void main(String[] args)
{
long count = Stream.of("how","to","do","in","java")
.collect(Collectors.counting());
System.out.printf("There are %d words in the stream %n", count);

count = Stream.of(1,2,3,4,5,6,7,8,9)
.collect(Collectors.counting());
System.out.printf("There are %d integers in the stream %n", count);

count = Stream.of(1,2,3,4,5,6,7,8,9)
.filter(i -> i%2 == 0)
.collect(Collectors.counting());
System.out.printf("There are %d even numbers in the stream %n", count);
}
}

public class Main


{
public static void main(String[] args)
{
long count = Stream.of("how","to","do","in","java")
.count();
System.out.printf("There are %d words in the stream %n", count);

count = IntStream.of(1,2,3,4,5,6,7,8,9)
.count();
System.out.printf("There are %d integers in the stream %n", count);

count = LongStream.of(1,2,3,4,5,6,7,8,9)
.filter(i -> i%2 == 0)
.count();
System.out.printf("There are %d even numbers in the stream %n", count);
}
}

Stream.distinct() to remove duplicates


The distinct() method returns a stream consisting of the distinct elements of given
stream. The element equality is checked according to element’s equals() method.

Stream.distinct() example
// ArrayList with duplicate elements
ArrayList<Integer> numbersList
= new ArrayList<>(Arrays.asList(1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 6, 7, 8));

List<Integer> listWithoutDuplicates = numbersList.stream()


.distinct()
.collect(Collectors.toList());

System.out.println(listWithoutDuplicates);

Collectors.toSet() to remove duplicates


Another simple and very useful way is to store all the elements in a Set. Sets, by
definition, store only distinct elements.

Collectors.toSet() example
// ArrayList with duplicate elements
ArrayList<Integer> numbersList
= new ArrayList<>(Arrays.asList(1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 6, 7, 8));

Set<Integer> setWithoutDuplicates = numbersList.stream()


.collect(Collectors.toSet());

System.out.println(setWithoutDuplicates);
Program output:

Console
[1, 2, 3, 4, 5, 6, 7, 8]
3. Collectors.toMap() to count occurances
Sometimes, we are interested in finding out that which all elements are duplicates
and how many times they appeared in the original list. We can use a Map to store
this information.

We have to iterate over the list, put element as the map key, and all its
occurrences in the map value field.

Collectors.toSet() example
// ArrayList with duplicate elements
ArrayList<Integer> numbersList
= new ArrayList<>(Arrays.asList(1, 1, 2, 3, 3, 3, 4, 5, 6, 6, 6, 7, 8));

Map<Integer, Long> elementCountMap = numbersList.stream()


.collect(Collectors.toMap(Function.identity(), v -> 1L, Long::sum));

System.out.println(elementCountMap);
Program output:

Console
{1=2, 2=1, 3=3, 4=1, 5=1, 6=3, 7=1, 8=1}

Creating IntStream
There are several ways of creating an IntStream.

1.1. IntStream.of()
This function returns a sequential ordered stream whose elements are the specified
values.

It comes in two versions i.e. single element stream and multiple values stream

IntStream of(int t) – Returns stream containing a single specified element.


IntStream of(int... values) – Returns stream containing specified all elements.
IntStream.of(10); //10
IntStream.of(1, 2, 3); //1,2,3
1.2. IntStream.range() and IntStream.rangeClosed()
These functions are discussed in more detail in later section (3). In this method,
we provide a range of values (start and end of range) and then the function returns
all int values from start value to end value.

IntStream.range(1, 5); //1,2,3,4,5


1.3. IntStream.iterate()
The iterator() function is useful for creating infinite streams. Also, we can use
this method to produce streams where values are increment by any other value than
1.

Given example produces first 10 even numbers starting from 0.

IntStream.iterate(0, i -> i + 2).limit(10);

//0,2,4,6,8,10,12,14,16,18
1.4. IntStream.generate()
generate() looks a lot like iterator(), but differ by not calculating the int
values by increment the previous value. Rather a IntSupplier is provided which is a
functional interface is used to generate an infinite sequential unordered stream of
int values.

Following example create stream of 10 random numbers and then print them in
console.

IntStream stream = IntStream.generate(()


-> { return (int)(Math.random() * 10000); });

stream.limit(10).forEach(System.out::println);

2. Foreach loop
To loop through the elements, stream support the forEach() operation. To replace
simple for-loop using IntStream, follow the same approach.

ForEachExample.java
import java.util.stream.IntStream;

public class ForEachExample


{
public static void main(String[] args)
{
//Simple for-loop

for(int i=0; i < 5; i++)


{
doSomething(i);
}

//IntStream forEach

IntStream.rangeClosed(0, 4)
.forEach( ForEachExample::doSomething );
}

private static void doSomething(int i) {


System.out.println(i);
}
}

3. IntStream range
The IntStream produced by range() methods is a sequential ordered stream of int
values which is equivalent sequence of increasing int values in a for-loop and
value incremented by 1. This class supports two methods.

range(int startInclusive, int endExclusive) – Returns a sequential ordered int


stream from startInclusive (inclusive) to endExclusive (exclusive) by an
incremental step of 1.
rangeClosed(int startInclusive, int endInclusive) – Returns a sequential ordered
int stream from startInclusive (inclusive) to endInclusive (inclusive) by an
incremental step of 1.
IntStream range and closed range
import java.util.stream.IntStream;

public class RangeExample


{
public static void main(String[] args)
{
//Range
IntStream stream = IntStream.range(5, 10);
stream.forEach( System.out::println ); //5,6,7,8,9

//Closed Range
IntStream closedRangeStream = IntStream.rangeClosed(5, 10);
closedRangeStream.forEach( System.out::println ); //5,6,7,8,9,10
}
}

4. Filter operation
We can apply filtering on int values produced by stream and use them in another
function or collect them for further processing.

For example, we can iterate over int values and filter/collect all prime numbers
upto a certain limit.

Prime number example


import java.util.List;
import java.util.function.IntPredicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class FilterExample


{
public static void main(String[] args)
{
IntStream stream = IntStream.range(1, 100);

List<Integer> primes = stream.filter(FilterExample::isPrime)


.boxed()
.collect(Collectors.toList());

System.out.println(primes);
}

public static boolean isPrime(int i)


{
IntPredicate isDivisible = index -> i % index == 0;
return i > 1 && IntStream.range(2, i).noneMatch(isDivisible);
}
}
Program output.
Console
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

5. IntStream to array
Use IntStream.toArray() method to convert from int stream to array.

IntStream to array
int[] intArray = IntStream.of(1, 2, 3, 4, 5).toArray();

System.out.println(Arrays.toString(intArray));

Output:

[1, 2, 3, 4, 5]

6. IntStream to list
Collections in Java can not store the primitive values directly. They can store
only instances/objects.

Using boxed() method of IntStream, we can get stream of wrapper objects which can
be collected by Collectors methods.

IntStream to list
List<Integer> ints = IntStream.of(1,2,3,4,5)
.boxed()
.collect(Collectors.toList());

System.out.println(ints);

Output:

[1, 2, 3, 4, 5]

Distinct by multiple fields – distinctByKeys() function


Below given is a function which accepts varargs parameter and we can pass multiple
key extractors (fields on which we want to filter the duplicates).

This function creates a key as List where list contains the values of fields to
check distinct combinations. The list keys are inserted into a ConcurrentHashMap
which stores only unique and distinct keys.

distinctByKeys() function
private static <T> Predicate<T> distinctByKeys(Function<? super T, ?>...
keyExtractors)
{
final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();

return t ->
{
final List<?> keys = Arrays.stream(keyExtractors)
.map(ke -> ke.apply(t))
.collect(Collectors.toList());

return seen.putIfAbsent(keys, Boolean.TRUE) == null;


};
}
In given example, we are finding all records having distinct ids and name. We
should have only 3 records as output.

Main.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@SuppressWarnings("unchecked")
public class Main
{
public static void main(String[] args)
{
List<Record> recordsList = getRecords();

List<Record> list = recordsList


.stream()
.filter(distinctByKeys(Record::getId, Record::getName))
.collect(Collectors.toList());

System.out.println(list);
}

private static <T> Predicate<T> distinctByKeys(Function<? super T, ?>...


keyExtractors)
{
final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();

return t ->
{
final List<?> keys = Arrays.stream(keyExtractors)
.map(ke -> ke.apply(t))
.collect(Collectors.toList());

return seen.putIfAbsent(keys, Boolean.TRUE) == null;


};
}

private static ArrayList<Record> getRecords()


{
ArrayList<Record> records = new ArrayList<>();

records.add(new Record(1l, 10l, "record1", "[email protected]", "India"));


records.add(new Record(1l, 20l, "record1", "[email protected]", "India"));
records.add(new Record(2l, 30l, "record2", "[email protected]", "India"));
records.add(new Record(2l, 40l, "record2", "[email protected]", "India"));
records.add(new Record(3l, 50l, "record3", "[email protected]", "India"));

return records;
}
}
Program output.

Console
[
Record [id=1, count=10, name=record1, [email protected], location=India],
Record [id=2, count=30, name=record2, [email protected], location=India],
Record [id=3, count=50, name=record3, [email protected], location=India]
]
2. Distinct by multiple properties – Custom key class
Another possible approach is to have a custom class which represent the distinct
key for the POJO class. In our case, we have created a class CustomKey which can
have as many fields as we like, and distinct elements from a list will be taken
based on the distinct combination of values for all these fields.

In given example, again, we are finding all records having unique keys and name.

CustomKey.java
public class CustomKey
{
private long id;
private String name;

public CustomKey(final Record record)


{
this.id = record.getId();
this.name = record.getName();
}

//Getters and setters

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CustomKey other = (CustomKey) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Lets see how this custom key is used for filtering the distinct elements from the
list based on given multiple fields.

Main.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@SuppressWarnings("unchecked")
public class Main
{
public static void main(String[] args)
{
List<Record> recordsList = getRecords();

List<Record> list = recordsList.stream()


.filter(distinctByKey(CustomKey::new))
.collect(Collectors.toList());

System.out.println(list);
}

public static <T> Predicate<T> distinctByKey(Function<? super T, Object>


keyExtractor)
{
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}

private static ArrayList<Record> getRecords()


{
ArrayList<Record> records = new ArrayList<>();

records.add(new Record(1l, 10l, "record1", "[email protected]", "India"));


records.add(new Record(1l, 20l, "record1", "[email protected]", "India"));
records.add(new Record(2l, 30l, "record2", "[email protected]", "India"));
records.add(new Record(2l, 40l, "record2", "[email protected]", "India"));
records.add(new Record(3l, 50l, "record3", "[email protected]", "India"));

return records;
}
}
Program output.

Console
[
Record [id=1, count=10, name=record1, [email protected], location=India],
Record [id=3, count=30, name=record2, [email protected], location=India],
Record [id=5, count=50, name=record3, [email protected], location=India]
]
For the reference, we have used Record class as given below.

Record.java
public class Record
{
private long id;
private long count;
private String name;
private String email;
private String location;

public Record(long id, long count, String name,


String email, String location) {
super();
this.id = id;
this.count = count;
this.name = name;
this.email = email;
this.location = location;
}

//Getters and setters

@Override
public String toString() {
return "Record [id=" + id + ", count=" + count + ", name=" + name +
", email=" + email + ", location="
+ location + "]";
}
}

Stream Elements with unique map keys – Collectors.toMap()


If the stream elements have the unique map key field then we can use
Collectors.toMap() to collect elements to map in Map<keyObj, Element> format
easily.

For example, we can collect a list of Employee objects to map in where employee ids
are unique fields and used a key to map entries.

Java 8 example to convert list to map using stream APIs.

Unique map keys


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Main


{
public static void main(String[] args)
{
List<Employee> employeeList = new ArrayList<>(Arrays.asList(
new Employee(1, "A", 100),
new Employee(2, "A", 200),
new Employee(3, "B", 300),
new Employee(4, "B", 400),
new Employee(5, "C", 500),
new Employee(6, "C", 600)));

Map<Long, Employee> employeesMap = employeeList.stream()


.collect( Collectors.toMap(Employee::getId,
Function.identity()) );

System.out.println(employeesMap);
}
}
Program output.

Console
{1=Employee [id=1, name=A, salary=100.0],
2=Employee [id=2, name=A, salary=200.0],
3=Employee [id=3, name=B, salary=300.0],
4=Employee [id=4, name=B, salary=400.0],
5=Employee [id=5, name=C, salary=500.0],
6=Employee [id=6, name=C, salary=600.0]}
2. Stream Elements with duplicate map keys – Collectors.groupingBy()
If the stream elements have elements where map keys are duplicate the we can use
Collectors.groupingBy() to collect elements to map in Map<keyObj, List<Element>>
format. Here for each map key, we will store all elements in a list as map value.

For example, we can collect a list of Employee objects to map in where employee
names may be duplicate fields for some stream elements. In such case, all employees
with same name will be stored in a list, and list will be stored as map value
field.

Java 8 example to convert list to map of lists using stream APIs.

Duplicate map keys


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main


{
public static void main(String[] args)
{
List<Employee> employeeList = new ArrayList<>(Arrays.asList(
new Employee(1, "A", 100),
new Employee(2, "A", 200),
new Employee(3, "B", 300),
new Employee(4, "B", 400),
new Employee(5, "C", 500),
new Employee(6, "C", 600)));

Map<String, List<Employee>> employeesMap = employeeList.stream()


.collect(Collectors.groupingBy(Employee::getName));

System.out.println(employeesMap);
}
}
Program output.

Console
{A=[Employee [id=1, name=A, salary=100.0], Employee [id=2, name=A, salary=200.0]],
B=[Employee [id=3, name=B, salary=300.0], Employee [id=4, name=B, salary=400.0]],
C=[Employee [id=5, name=C, salary=500.0], Employee [id=6, name=C, salary=600.0]]}

You might also like