Java Collections and JDK8 Features Complete Notes
Java Collections and JDK8 Features Complete Notes
(Simplified)
SRINIVAS GARAPATI
Contents
S No Topic Page Num
01 Introduction to Collection Framework 02
02 Wrapper classes 05
03 Generics 06
04 ArrayList 07
05 For-each loop 14
06 Iterator 16
07 ListIterator 17
08 List of Objects (Parameterized constructor approach) 18
09 List of Objects (POJO class approach) 25
10 ArrayList – Case Studies 27
11 ArrayList Operations – Menu driven approach 34
12 ArrayList Employee CRUD – Menu Driven 37
13 Vector 40
14 Stack 43
15 LinkedList 45
16 Set Interface 47
17 Map Interface 49
18 Comparator 57
19 Java8 Comparator 59
20 Java8 features 61
21 Static and Default methods 64
22 Functional Interface 65
23 Lambda Expression 66
24 Method References 69
25 forEach() method 70
26 Stream API 74
27 Map() and Filter() 75
28 Collectors Class 78
29 Parallel Streaming 81
30 Optional Class 83
31 Predicates 85
32 Date and Time API 88
33 Interview Questions 93
34 Practice sheets 99
Collection Framework
Introduction:
• Programming languages and Technologies are used to develop applications.
• Applications are used in communication.
• Applications store and process information.
Linear Data Structures: arrange the data sequentially in which elements are connected to its
previous and next adjacent.
Non-Linear Data Structures: in which one element connected to multiple elements and the
elements arranged in two-dimensional or multi-dimensional format.
Define Collection?
• Collection is a group of objects.
• Examples, List, Set, Queue, Map etc.
Collection Hierarchy: The following diagram represents interfaces and classes available in java
Collection Framework
2. Vector:
a. Accessing elements much faster.
b. Insertions and Deletions are slower – shifting elements takes time.
3. Stack:
a. Stack follows Last In First Out (LIFO) rule.
b. Inserting and removing elements from one end called TOP.
4. LinkedList:
a. Accessing element slower, nodes-based access.
b. Insertions and Deletions are faster – No shifting of elements.
Wrapper classes:
• Collection stores only objects (not primitive data).
• Wrapper classes providing functionality to perform conversions like
o Primitive -> Object (Boxing)
o Object -> Primitive (Un boxing)
• These conversions become automated since JDK5
Generics
Generics:
• As we know, collection only store objects.
• Generics introduced in JDK5.
• Generics are used to specify what type of objects allowed to store into Collection.
For Example,
Collection<Object> c = new Collection<Object>();
c.add(10);
Downcast to Integer:
Integer x = c.get(0);
ArrayList Collection
ArrayList:
• ArrayList is an ordered collection and allow duplicates.
• ArrayList is index based.
• Processing elements much faster (index based)
• Insertions and Deletions are slower (shifting of elements takes time)
Methods:
Name Description
int size() Returns the number of elements in this list.
boolean add(E e) Appends the specified element to the end of this list
Object remove(int index) Removes the element at the specified position in this list
void clear() Removes all of the elements from this list
void add(int index, E element) Inserts element at the specified position in this list
Object get(int index) Returns the element at the specified position in this list
boolean isEmpty() Returns true if this list contains no elements
Object set(int index, E element) Replaces the element at the specified position in this list
with the specified element
boolean contains(Object o) Returns true if this list contains the specified element
int indexOf(Object o) Returns the index of the first occurrence of the specified
element, or -1 if this list does not contain the element.
Iterator<Object> iterator() Returns an iterator over the elements in this list
boolean addAll(Collection c) Appends all of the elements in the specified collection to
the end of this list
Object clone() Returns a shallow copy of this ArrayList instance
ListIterator listIterator(int index) Returns a list iterator over the elements in this list (in
proper sequence), starting at the specified position in
the list.
Object[] toArray() Returns an array containing all of the elements in this list
in proper sequence (from first to last element).
Insert element into specified index: add(int index, E e) method is used to insert element into
specified index.
Instructions to code:
• Create ArrayList with 5 elements 10, 20, 30, 40, 50
• Read index to insert.
• Check whether the index is present or not
• If the index is present, then read the value and insert.
• If the index is not present, display Error message.
import java.util.*;
class Code
{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
System.out.println("List is : " + list);
System.out.print("Enter index to insert : ");
int loc = sc.nextInt();
if(loc>=0 && loc<list.size()){
System.out.print("Enter element to insert : ");
int ele = sc.nextInt();
list.add(loc, ele);
System.out.println("List is : " + list);
}
else{
System.out.println("Invalid index");
}
}
}
Program to remove all elements from the list: clear() method removes all elements from the
list.
Instructions to code:
• Create list with 5 elements.
• Display – List is not empty
• Remove all elements using clear() method
• Display – List is empty.
import java.util.*;
class Code
{
public static void main(String[] args){
List<Integer> list = new ArrayList<Integer>();
for(int i=1 ; i<=5 ; i++)
list.add(i);
list.clear();
System.out.println("List is : " + list);
if(list.isEmpty())
System.out.println("List is empty");
else
System.out.println("List is not empty");
}
}
Program to remove index element: remove(int index) method removes element of specified
index.
Instructions to code:
• Create list with elements
• Read index value.
• If the index is valid – remove the element and display list
• If the index is not valid – display error message.
import java.util.*;
class Code
{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<Integer> list = new ArrayList<Integer>();
for(int i=1 ; i<=5 ; i++){
list.add(i);
}
System.out.println("List is : " + list);
System.out.print("Enter index to remove : ");
int loc = sc.nextInt();
if(loc>=0 && loc<list.size()){
list.remove(loc);
System.out.println("List is : " + list);
}
else{
System.out.println("Error : No such index to remove");
}
}
}
Program to check whether the list contains element or not: contains() method returns true if
the list has specified element.
import java.util.*;
class Code
{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
List<Integer> list = new ArrayList<Integer>();
for(int i=1 ; i<=5 ; i++)
list.add(i);
System.out.println("List is : " + list);
System.out.print("Enter element to check in list : ");
int ele = sc.nextInt();
if(list.contains(ele))
System.out.println("Yes element is present in list");
else
System.out.println("No such element in list");
}
}
Program display the index value of element: indexOf() method returns index of specified
element. It returns -1 if no such element in the list.
import java.util.*;
class Code
{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<Integer> list = new ArrayList<Integer>();
for(int i=1 ; i<=5 ; i++)
list.add(i);
System.out.println("List is : " + list);
System.out.print("Enter element to find index value : ");
int ele = sc.nextInt();
int index = list.indexOf(ele);
if(index!=-1)
System.out.println("Index value is : " + index);
else
System.out.println("No such element in list");
}
}
Program to replace the existing value: set(int index, E e) method replace the index element
with specified element.
Instructions to code:
• Create ArrayList with elements.
• Read the element to replace
• Check the element is present or not in the list using contains() method.
• If the element is present,
o Read the new element to replace with.
• If the element is not present,
o Display error message.
import java.util.*;
class Code
{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<Integer> list = new ArrayList<Integer>();
for(int i=1 ; i<=5 ; i++){
list.add(i);
}
System.out.println("List is : " + list);
System.out.print("Enter element to replace : ");
int x = sc.nextInt();
if(list.contains(x)) {
System.out.print("Enter new element : ");
int y = sc.nextInt();
For-each loop:
• It is also called enhanced for loop.
• It is since JDK5
• For-each loop provides easy syntax to process elements of Array or Collection.
Limitations:
• For-each loop can process elements only in forward direction.
• For-each loop can process elements one by one only.
Syntax:
for (datatype var : Array/Collection ) {
statements ;
}
System.out.println("List is : ");
for(Integer x : list)
System.out.println(x);
}
}
Display ArrayList element by element using for-loop: get(int index) method is used to
retrieve each element using its index.
import java.util.*;
class Code {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
for(int i=1 ; i<=5 ; i++)
list.add(i*5);
System.out.println("List is : ");
for(int i=0 ; i<=list.size()-1 ; i++)
System.out.println(list.get(i));
}
}
System.out.println("List is : ");
for(int i=list.size()-1 ; i>=0 ; i--)
System.out.println(list.get(i));
}
}
a1.addAll(a2);
System.out.println("a1 list after merge : " + a1);
}
}
Iterator:
• It is an interface.
• Iterator providing methods to iterator any collection.
• iterator() method returns Iterator object of any collection.
Methods:
1. boolean hasNext(): checks the next element is present or not to iterate.
2. Object next(): returns the next element of iterator object.
ListIterator:
• It is an interface
• listIterator() method returns ListIterator object.
• Using ListIterator, we can iterate elements,
o In Forward direction
o In Backward direction
o From specified index value
Main.java:
• Create 3 Employee objects and add to List
• Display details using for-each loop
import java.util.*;
class Main {
public static void main(String[] args) {
List<Employee> list = new ArrayList<Employee>();
Employee.java:
• Create Employee class with instance variables id, name, salary
• Define parameterized constructor to initialize the object.
class Employee
{
int id;
String name;
double salary;
Employee(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
}
Main.java:
• Collect values from Arrays to create Employee objects.
• Display details using for-each loop
import java.util.*;
class Main
{
public static void main(String[] args) {
int[] ids = {101, 102, 103, 104, 105};
String[] names = {"Amar", "Annie", "Harini", "Satya", "Jai"};
double[] salaries = {23000, 56000, 43000, 48000, 16000};
Main.java: Read and Add employee details until end user quits.
import java.util.*;
class Main
{
public static void main(String[] args)
{
List<Employee> list = new ArrayList<Employee>();
Scanner sc = new Scanner(System.in);
while(true)
{
System.out.println("Enter Emp details to add : ");
int id = sc.nextInt();
String name = sc.next();
double salary = sc.nextDouble();
Employee e = new Employee(id, name, salary);
list.add(e);
Main.java: Read and Add employee details until end user quits using BufferedReader.
import java.util.*;
import java.io.*;
class Main
{
public static void main(String[] args) throws Exception {
List<Employee> list = new ArrayList<Employee>();
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
System.out.println("Enter Emp details to add : ");
int id = Integer.parseInt(br.readLine());
String name = br.readLine();
double salary = Double.parseDouble(br.readLine());
Employee e = new Employee(id, name, salary);
list.add(e);
Main.java:
Construct objects by reading using Scanner)
import java.util.*;
class Main
{
public static void main(String[] args) {
List<Employee> list = new ArrayList<Employee>();
Scanner sc = new Scanner(System.in);
while(true)
{
System.out.println("Enter Emp details : ");
int id = sc.nextInt();
String name = sc.next();
double salary = sc.nextDouble();
list.add(e);
Main.java:
import java.util.*;
class Main {
public static void main(String[] args) {
int[] ids = {101, 102, 103, 104, 105, 106};
String[] names = {"Amar", "Hareen", "Sathya", "Annie", "Raji", "Harsha"};
double[] salaries = {30000, 35000, 40000, 45000, 42000, 50000};
int[] depts = {20, 10, 20, 20, 30, 10};
String[] locations = {"Hyderabad", "Chennai", "Bangalore", "Hyderabad",
"Pune", "Bangalore"};
if(e.getLocation().equals("Hyderabad"))
{
System.out.println(e.getId() + " ," + e.getName() + " , " + e.getSalary() + " , " +
e.getDept() + " , " + e.getLocation());
count++;
}
}
if(count==0)
{
System.out.println("No employee belongs to Hyderabad");
}
}
}
if(count==0)
{
System.out.println("No employee records founds");
}
Count how many employees working in both Hyderabad and Bangalore locations:
int count=0;
for(Employee e : list)
{
String loc = e.getLocation();
if(loc.equals("Hyderabad") || loc.equals("Bangalore"))
{
count++;
}
}
System.out.println("Count is : " + count);
{
System.out.println(e.getId() + " , " + e.getName() + " , " + e.getSalary() + " , " +
e.getDept() + " , " + e.getLocation());
count++;
}
}
if(count==0)
{
System.out.println("No employee found");
}
Display details whose salary below 40000 and not belongs to Hyderabad:
int count=0;
for(Employee e : list)
{
if(e.getSalary()<40000 && !(e.getLocation().equals("Hyderabad")))
{
System.out.println(e.getId() + " , " + e.getName() + " , " + e.getSalary() + " , " +
e.getDept() + " , " + e.getLocation());
count++;
}
}
if(count==0)
{
System.out.println("No employee found");
}
Following program explains how to perform ArrayList operations such as Append, Insert,
Replace, Update, Remove, Sort, Reverse and Display:
import java.util.*;
class Main
{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<Integer>();
Scanner sc = new Scanner(System.in);
while(true)
{
System.out.println("1.Append");
System.out.println("2.Insert");
System.out.println("3.Replace");
System.out.println("4.Remove");
System.out.println("5.Display");
System.out.println("6.Sort");
System.out.println("7.Reverse");
System.out.println("8.Quit");
if(list.contains(ele)){
int index = list.indexOf(ele);
System.out.print("Enter new element : ");
int x = sc.nextInt();
list.set(index, x);
System.out.println("Element replaced");
}
else
System.out.println("No such element in list");
}
else if(ch==4)
{
System.out.print("Enter element to remove : ");
int ele = sc.nextInt();
if(list.contains(ele)){
int index = list.indexOf(ele);
list.remove(index);
System.out.println("Element removed");
}
else
System.out.println("No such element to remove");
}
else if(ch==5)
{
if(list.isEmpty())
System.out.println("Empty list");
else
System.out.println("List is : " + list);
}
else if(ch==6)
{
Collections.sort(list);
System.out.println("List sorted");
}
else if(ch==7)
{
Collections.reverse(list);
System.out.println("List reversed");
}
else if(ch==8)
{
System.out.println("End");
System.exit(1);
}
else
System.out.println("Invalid choice");
}
}
}
This program explains how to add employee details, display details of specific ID, remove
employee and update the details of employee:
import java.util.*;
class Main
{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
List<Employee> list = new ArrayList<Employee>();
while(true){
System.out.println("1.Add Record");
System.out.println("2.Display Record");
System.out.println("3.Display All");
System.out.println("4.Update Record");
System.out.println("5.Delete Record");
System.out.println("6.Exit");
if(ch==1){
System.out.println("Enter details :");
int id = sc.nextInt();
String name = sc.next();
double salary = sc.nextDouble();
boolean found=false;
for(Employee e : list){
if(e.id == id){
System.out.println("Name : " + e.name);
System.out.println("Salary : " + e.salary);
found = true;
break;
}
}
if(!found)
System.out.println("Invalid ID");
}
}
else if(ch==3){
if(list.isEmpty()){
System.out.println("Empty list");
}
else{
System.out.println("Details : ");
for(Employee e : list){
System.out.println("Name : " + e.name);
System.out.println("Salary : " + e.salary);
}
}
}
else if(ch==4){
if(list.isEmpty()){
System.out.println("Empty list");
}
else{
System.out.print("Enter id : ");
int id = sc.nextInt();
boolean found=false;
for(Employee e : list){
if(e.id == id){
System.out.print("Enter sal to update: ");
double salary = sc.nextDouble();
e.salary = salary;
System.out.println("Record updated");
found = true;
break;
}
}
if(!found)
System.out.println("Invalid ID");
}
}
else if(ch==5){
if(list.isEmpty()){
System.out.println("Empty list");
}
else
{
System.out.print("Enter id : ");
int id = sc.nextInt();
boolean found=false;
for(Employee e : list)
{
if(e.id == id){
int index = list.indexOf(e);
list.remove(index);
System.out.println("Removed");
found = true;
break;
}
}
if(!found)
System.out.println("Invalid ID");
}
}
else if(ch==6){
System.out.println("End");
System.exit(1);
}
else
System.out.println("Invalid choice");
}
}
}
Vector Collection
Vector:
• Vector implements List.
• Vector allow duplicates and follow insertion order.
• Vector is synchronized by default.
import java.util.*;
class Code {
public static void main(String[] args)
{
Vector<Integer> v = new Vector<Integer>();
for (int i=1 ; i<=5 ; i++){
v.add(i*5);
}
System.out.println("Vector : " + v);
}
}
Enumeration:
• Vector is legacy(old) class since first version of JDK.
• Enumeration interface used to process vector element by element.
• elements() method of Vector class returns Enumeration-interface.
Methods of Enumeration:
1. hasMoreElements(): is used to check the element is present or not in Enumeration
2. nextElement(): returns the next element in the enumeration.
import java.util.*;
class Code {
public static void main(String[] args)
{
Vector<Integer> v = new Vector<Integer>();
for (int i=1 ; i<=5 ; i++){
v.add(i*5);
}
System.out.println("Vector : ");
Enumeration<Integer> en = v.elements();
while(en.hasMoreElements())
{
Integer x = en.nextElement();
System.out.println(x);
}
}
}
ArrayList is not synchronized: We get odd results when we try to add elements into ArrayList
from multiple threads.
import java.util.*;
class Test
{
static ArrayList<Integer> list = new ArrayList<Integer>();
}
class First extends Thread
{
public void run(){
for (int i=1 ; i<=100000 ; i++)
{
Test.list.add(i);
}
}
}
class Second extends Thread
{
public void run(){
for (int i=1 ; i<=100000 ; i++)
{
Test.list.add(i);
}
}
}
class Code
{
public static void main(String[] args) throws Exception {
First f = new First();
Second s = new Second();
f.start();
s.start();
f.join();
s.join();
System.out.println("List size is : " + Test.list.size());
}
}
Vector is synchronized by default: Vector is thread safe, hence we get perfect results when we
try to add elements from multiple threads
import java.util.*;
class Test
{
static Vector<Integer> list = new Vector<Integer>();
}
class First extends Thread
{
public void run(){
for (int i=1 ; i<=100000 ; i++)
{
Test.list.add(i);
}
}
}
class Second extends Thread
{
public void run(){
for (int i=1 ; i<=100000 ; i++)
{
Test.list.add(i);
}
}
}
class Code
{
public static void main(String[] args) throws Exception
{
First f = new First();
Second s = new Second();
f.start();
s.start();
f.join();
s.join();
System.out.println("Vector size is : " + Test.list.size());
}
}
Stack - Collection
Stack:
• Stack is an extension of Vector class.
• It follows LIFO – Last In First Out Rule
Methods are:
1. boolean empty() : Tests the stack is empty or not
2. Object peek(): returns the top element of stack but not remove
3. Object pop(): returns the top element of stack and removes
4. void push(Object e): push element on to the stack
import java.util.*;
class Code
{
public static void main(String[] args) throws Exception {
Stack<Integer> stk = new Stack<Integer>();
stk.push(10);
stk.push(20);
stk.push(30);
stk.push(40);
System.out.println("Stack is : " + stk);
stk.push(50);
stk.push(60);
System.out.println("Stack is : " + stk);
Linked List
LinkedList:
• LinkedList implements List
• LinkedList allow duplicates and ordered collection.
• Linked List store elements in the form of nodes and connect with links.
Methods are:
boolean add(E e) Appends the specified element to the end of this list.
void add(int index, E element) Inserts the specified element at the specified position
void addFirst(E e) Inserts the specified element at the beginning of this list.
void addLast(E e) Appends the specified element to the end of this list.
void clear() Removes all of the elements from this list.
boolean contains(Object o) Returns true if this list contains the specified element.
E get(int index) Returns the element at the specified position in this list.
E getFirst() Returns the first element in this list.
E getLast() Returns the last element in this list.
Iterator descendingIterator() Returns an iterator over the elements in this reverse.
int indexOf(Object o) Returns element index or else -1
ListIterator listIterator(int index) Create iterator from specified index.
E remove(int index) Removes the element at the specified position in this list.
E removeFirst() Removes and returns the first element from this list.
E removeLast() Removes and returns the last element from this list.
E set(int index, E element) Replace index element with specified element.
int size() Returns the number of elements in this list.
import java.util.LinkedList;
class Demo{
public static void main(String[] args){
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("Apple");
linkedList.add("Banana");
linkedList.add("Orange");
linkedList.addFirst("Mango");
linkedList.addLast("Grapes");
System.out.println("LinkedList: " + linkedList);
// Retrieving
String first = linkedList.getFirst();
String last = linkedList.getLast();
System.out.println("First: " + first);
System.out.println("Last: " + last);
// Searching
boolean containsBanana = linkedList.contains("Banana");
System.out.println("Contains Banana: " + containsBanana);
linkedList.removeFirst();
linkedList.removeLast();
System.out.println("Removing first and last elements: " + linkedList);
linkedList.remove(1);
System.out.println("LinkedList after removing : " + linkedList);
linkedList.clear();
System.out.println("LinkedList after clearing all elements: " + linkedList);
}
}
Set Interface
Set:
• Set doesn’t allow duplicates.
• Set is not index based.
HashSet Methods are:
boolean add(E e) Adds the specified element to this set if it is not already present.
void clear() Removes all of the elements from this set.
Object clone() Returns a shallow copy: the elements themselves are not cloned.
boolean contains(Object o) Returns true if this set contains the specified element.
boolean isEmpty() Returns true if this set contains no elements.
Iterator<E> iterator() Returns an iterator over the elements in this set.
boolean remove(Object o) Removes the specified element from this set if it is present.
int size() Returns the number of elements in this set (its cardinality).
set.add(30);
set.add(20);
set.add(10);
System.out.println("Set : " + set);
}
}
Output: 50, 40, 30, 20, 10
Map Interface
Map:
• Store values using keys
Map = {key=value, key=value, key=value ….}
• Keys must be unique in Map
• Values can be duplicated.
• For example, book names(unique) with prices(duplicates)
o Books = {C=300.0 , C++=300.0, Java=350.0, Python=330.0};
Methods are:
Method Description
put(K key, V value) store value using key.
V get(Object key) return value of specified key.
boolean isEmpty() Returns true if this map contains key-values.
void clear() Removes all elements.
boolean containsKey(Object key) Returns true if map contains specified key.
Set<K> keySet() Returns a Set of keys contained in this map.
remove(Object key) Removes key-value of specified key.
replace(K key, V value) Replace the value of specified key with given value.
int size() Returns the number of key-values in map.
Collection<V> values() Returns Collection of values in this map.
Implementations of Map:
1. HashMap: doesn’t maintain insertion order. Allows only one null key
2. LinkedHashMap: maintains insertion order. Allows only one null key
3. TreeMap: maintains sorted order of keys. It doesn’t allow null key.
4. Hashtable: It is call legacy class. It maintains sorted order. It doesn’t allow null key.
import java.util.*;
class Code
{
public static void main(String[] args)
{
//Map<Integer,String> map = new LinkedHashMap<Integer,String>();
Map<Integer,String> map = new TreeMap<Integer,String>();
map.put(50, "Fifty");
map.put(40, "Fourty");
map.put(30, "Thirty");
map.put(20, "Twenty");
map.put(10, "Ten");
System.out.println("Map : " + map);
}
}
Set<K> keySet():
• We cannot iterate the map object either by using Iterator or using for-each loop.
• First we need to collect all keys of map using keySet() method.
• We iterate keys set and get values by specifying each key.
import java.util.*;
class Code
{
public static void main(String[] args) throws Exception
{
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(10, "Ten");
map.put(20, "Twenty");
map.put(30, "Thirty");
map.put(40, "Fourty");
System.out.println("Map is : ");
Set<Integer> keys = map.keySet();
for(Integer key : keys)
{
System.out.println("Map is : ");
Set<String> keys = map.keySet();
Iterator<String> itr = keys.iterator();
while(itr.hasNext())
{
String key = itr.next();
Double value = map.get(key);
System.out.println(key + " = " + value);
}
}
}
if(ch==1)
{
System.out.print("Enter Book Name : ");
String name = sc.next();
if(map.containsKey(name))
{
System.out.println("Book already exists");
}
else
{
System.out.print("Enter Price : ");
double price = sc.nextDouble();
map.put(name, price);
System.out.println("Book added");
}
}
else if(ch==2)
{
System.out.print("Enter Book Name : ");
String name = sc.next();
if(map.containsKey(name))
{
System.out.print("Enter Price : ");
double price = sc.nextDouble();
map.replace(name, price);
System.out.println("Book updated");
}
else
System.out.println("Error : Invalid Book Name");
}
else if(ch==3)
{
System.out.print("Enter Book Name : ");
String name = sc.next();
if(map.containsKey(name))
{
System.out.println("Price : " + map.get(name));
}
else
System.out.println("Error : Invalid Book Name");
}
else if(ch==4)
{
System.out.print("Enter Book Name : ");
String name = sc.next();
if(map.containsKey(name))
{
map.remove(name);
System.out.println("Book removed");
}
else
System.out.println("Error : Invalid Book Name");
}
else if(ch==5)
{
System.out.println("End");
System.exit(1);
}
else
System.out.println("Invalid choice");
}
}
}
Main.java:
import java.util.*;
class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
Map<Integer, Account> map = new HashMap<Integer, Account>();
while(true)
{
System.out.println("1. Add Account");
System.out.println("2. Update Location");
System.out.println("3. Display Account");
System.out.println("4. Remove Account");
System.out.println("5. Quit");
if(ch==1)
{
System.out.print("Enter Account Number : ");
Integer number = sc.nextInt();
if(map.containsKey(number))
{
System.out.println("Account already exists");
}
else
{
System.out.print("Enter Name :");
String name = sc.next();
System.out.print("Enter Balance :");
double balance = sc.nextDouble();
System.out.print("Enter Location :");
String location = sc.next();
map.put(number, acc);
System.out.println("Account added");
}
}
else if(ch==2)
{
System.out.print("Enter Account Number : ");
int number = sc.nextInt();
if(map.containsKey(number))
{
System.out.print("Enter location : ");
String location = sc.next();
Account acc = map.get(number);
acc.setLocation(location);
System.out.println("Location updated");
}
else
System.out.println("Error : Invalid acc-number");
}
else if(ch==3)
{
System.out.print("Enter Account Number : ");
int number = sc.nextInt();
if(map.containsKey(number))
{
Account acc = map.get(number);
System.out.println("Details : " + acc.getName() + ", " +
acc.getBalance() + ", " + acc.getLocation());
}
else
System.out.println("Error : Invalid Account");
}
else if(ch==4)
{
System.out.print("Enter Account Number : ");
int number = sc.nextInt();
if(map.containsKey(number))
{
map.remove(number);
System.out.println("Account removed");
}
else
System.out.println("Error : Invalid Account");
}
else if(ch==5)
{
System.out.println("End");
System.exit(1);
}
else
System.out.println("Invalid choice");
}
}
}
Comparator interface
Comparator:
• Comparator is used to order the objects of a user-defined class.
• Comparator provides multiple sorting sequences hence we can sort the elements based
on different data members, for example, rollno, name, age or anything else.
Method Description
public int compare(Object o1, Object o2) Compares first and second object in the list.
public boolean equals(Object obj) Compares this object with specified object.
Main.java:
import java.util.*;
import java.io.*;
class Main
{
public static void main(String args[]){
ArrayList<Student> list=new ArrayList<Student>();
list.add(new Student(101,"Vijay",23));
list.add(new Student(106,"Ajay",27));
list.add(new Student(105,"Jai",21));
list.add(new Student(103, "Amar", 13));
System.out.println("Sort by age");
Collections.sort(list,new AgeComparator());
System.out.println("After Sort : ");
for(Student st : list){
System.out.println(st.rollno+" , "+st.name+" , "+st.age);
}
}
}
}
Main.java:
import java.util.*;
public class Code
{
public static void main(String args[])
{
ArrayList<Student> al=new ArrayList<Student>();
int nums[] = {101, 102, 103, 104};
String names[] = {"Amar", "Swathi", "Sathya", "Harin"};
int ages[] = {23, 30, 17, 25};
Comparator<Student> cm1=Comparator.comparing(Student::getName);
Collections.sort(al,cm1);
System.out.println("Sorting by Name");
for(Student st: al)
{
System.out.println(st.getRollno()+" , "+st.getName()+" , "+st.getAge());
}
Comparator<Student> cm2=Comparator.comparing(Student::getAge);
Collections.sort(al,cm2);
System.out.println("Sorting by Age");
for(Student st: al)
{
System.out.println(st.getRollno()+" , "+st.getName()+" , "+st.getAge());
}
}
}
Java-8 Features
Features are:
• Static Methods in Interface (JDK7)
• Default Methods in interface
• Functional Interface
• Lambda expression
• Method references
• forEach() method
• Stream API
• Parallel Streams
• Optional Class
• Data and Time API
• Predicates
Purpose of JDK-8:
• Using java technology, application development became easy. Billions of applications
developed under java. Day by day the data increasing rapidly with the use of these
applications and data processing become complex.
• JDK8 features are the solution to implement data processing techniques easily. Data
processing important – for quick results
Simplifying code: JDK 8 features such as lambda expressions, method references, and default
methods help reduce boilerplate code, making Java code more readable and maintainable.
Improved error handling: The Optional class was introduced to provide a more explicit way to
handle null values and reduce the occurrence of NullPointerExceptions, improving code
robustness.
Modernizing date and time handling: The new Date and Time API in JDK 8 was introduced to
address the shortcomings of the older java.util.Date and java.util.Calendar classes, providing a
more intuitive and flexible approach to date and time manipulation.
Note: The object address of implemented class assign to Interface type reference variable.
InterfaceName obj = new ImplementedClass();
interface Test
{
void m1(); // public abstract
}
class Demo implements Test {
public void m1() {
System.out.println("m1...");
}
}
class Main {
public static void main(String[] args) {
Test obj = new Demo(); // up-casting
obj.m1();
}
}
interface Code
{
int a = 10; // public static final
}
class Main {
public static void main(String[] args) {
System.out.println("a value : " + Code.a);
Code.a = 20 ; // Error : final variable cannot be modified
}
}
Note: Static methods are used to define the common functionality of objects which are
implemented from that interface.
interface CreditCard {
String cartType = "VISA-Platinum";
static void benefits(){
System.out.println("Benefits on Flying, Dining and more");
}
}
Default Methods:
• Defining a method with default keyword.
• We can access Default methods through object reference.
Note: Default methods allow the interfaces to have methods with implementation without
affecting the classes that implement the interface.
interface Vehicle{
default String airBags(){
return "Two airbags";
}
default String alarmOn(){
return "at speed of 100";
}
int maxSpeed();
}
class Alto implements Vehicle{
public int maxSpeed(){
return 160;
}
}
class Swift implements Vehicle{
public int maxSpeed(){
return 220;
}
}
Functional Interface:
• Interface that accepts only one abstract method.
• We must define with annotation @FunctionalInterface.
• Functional Interface allow static and default methods.
@FunctionalInterface
interface Test
{
void m1();
void m2(); // Error :
}
Lambda Expressions
2. Through Anonymous inner class: Defining a class without identity is called Anonymous
inner class. We always define anonymous class inside a method.
interface Test {
void fun();
}
class Main {
public static void main(String[] args) {
Test obj = new Test() {
public void fun() {
System.out.println("Anonymous fun");
}
};
obj.fun();
}
}
Lambda expression with return values: Lambda expression automatically returns the value
which is evaluated in expression. We need to specify the return type in Functional Interface
specification.
@FunctionalInterface
interface Calc
{
int add(int x, int y);
}
class Main
{
public static void main(String[] args)
{
Calc obj = (x, y) -> x+y;
Method references:
• It is JDK8 feature.
• It is used to refer any method of functional interface easily.
• Any method definition can be assigned to functional interface method identity and
access the using its identity.
forEach() method
forEach() method:
• forEach() introduced in JDK8 to iterate the collection easily.
• forEach() defined in both Iterable interface and in Stream interface.
• forEach() method is a Default method.
Iterating List
Defining a List:
List<String> names = Arrays.asList("C", "Java", "Python");
Iterating Set
Defining a Set:
Set<String> uniqueNames = new HashSet<>(Arrays.asList("C", "C++", "Java"));
Iterating Map
Defining a Map:
Map<Integer, String> namesMap = new HashMap<>();
namesMap.put(1, "Java");
namesMap.put(2, "JDBC");
namesMap.put(3, "JSP");
Iterate map:
namesMap.forEach((key, value) -> System.out.println(key + " " + value));
Iterate List:
import java.util.*;
import java.util.*;
class Main
{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>(Arrays.asList(10,20,30,40,50));
list.forEach(x->System.out.println(x));
}
}
Iterate Set:
import java.util.*;
import java.util.*;
class Main
{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>(Arrays.asList(10,20,30,40,50));
Set<Integer> set = new HashSet<>(list);
set.forEach(x->System.out.println(x));
}
}
Iterate Map:
import java.util.*;
import java.util.*;
class Main
{
public static void main(String[] args)
{
Map<Integer,String> map = new HashMap<>();
map.put(1, "Java");
map.put(2, "Servlets");
map.put(3, "JSP");
map.forEach((k, v)->System.out.println(k + " = " + v));
}
}
Stream API
Stream API:
• Stream is a flow of data.
• Stream API providing pre-defined functionality by which we can filter the data easily.
• We always create Streams to Collection objects and filter the data stored in collections.
Note: Stream is a not a data structure hence it will not hold any information. Stream will not
change the collection object. It just processes the elements of object by without modifying it.
Creating Stream to List: stream() method returns the stream of any collection object
Stream<Integer> st = list.stream();
Creating a Stream:
List<Integer> myList = new ArrayList<Integer>();
myList.add(1);
myList.add(5);
myList.add(8);
Stream<Integer> myStream = myList.stream();
Practice Programs
filter():
• filter() method takes lambda expression as input and return boolean value.
• If filter() method returns true, then the element enter into resultant stream.
• filter() method returns stream after filtering the data.
Stream<String> st = list.stream();
Stream<String> res = st.filter(s->s.startsWith("S"));
res.forEach(System.out::println);
}
}
list.stream().filter(s->s.length()==4).forEach(System.out::println);
}
}
Program to display only even numbers in the list using stream api:
import java.util.*;
import java.util.stream.*;
class Main {
public static void main(String[] args) {
int[] arr = {5, 2, 8, 9, 3, 7, 1, 4, 6};
List<Integer> list = new ArrayList<Integer>();
for(int x : arr)
list.add(x);
System.out.println("List is : " + list);
System.out.println("Even numbers list is : ");
list.stream().filter(s->s%2==0).forEach(System.out::println);
}
}
Collectors Class
Collectors: Collectors is a final class. It provides methods to collect filtered elements into various
collections, and performing operations on collected data such as counting elements, reverse,
sort etc.
output: [1,4,9,16,25,36,36]
output: [1,4,9,16,25,36]
output: [3,4,5,6,6]
Counting elements:
List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
Long collect = integers
.stream()
.filter(x -> x <4)
.collect(Collectors.counting());
Output: 3
Output: 1
Filter and map a list of strings to their lengths, then find the maximum length:
List<String> words = Arrays.asList("apple", "banana", "orange", "grapes");
int maxLength = words.stream()
.filter(s -> s.length() > 5)
.mapToInt(String::length)
.max()
.orElse(0);
System.out.println(maxLength);
Filter and map a list of strings to their uppercase versions, then sort them:
List<String> words = Arrays.asList("apple", "banana", "orange", "grapes");
List<String> sortedUpperCaseWords = words.stream()
.filter(s -> !s.isEmpty())
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
System.out.println(sortedUpperCaseWords);
Parallel Streaming
Parallel Streaming: Parallel streaming is a feature introduced in Java 8 as part of the Stream
API. It allows you to perform stream operations concurrently on multi-core processors,
effectively dividing the data into smaller chunks and processing them in parallel threads.
import java.util.LinkedList;
import java.util.List;
public class Demo
{
public static void main(String[] args)
{
List<String> colors = new LinkedList<>();
colors.add("Red");
colors.add("Green");
colors.add("Blue");
colors.add("Yellow");
colors.add("Purple");
colors.parallelStream()
.forEach(System.out::println);
}
}
map.entrySet().parallelStream()
.forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
}
}
forEachOrdered():
import java.util.*;
public class Demo
{
public static void main(String[] args)
{
List<Integer> list = Arrays.asList(2, 4, 6, 8, 10);
list.stream().parallel().forEach( System.out::println );
list.stream().parallel().forEachOrdered( System.out::println );
}
}
Optional Class
Optional class:
• In Java 8, the concept of Optional was introduced to handle the case where a method
might return a non-null value or a null value.
• Optional is a container object that may or may not contain a non-null value.
• It helps to avoid null pointer exceptions and allows developers to write more concise and
expressive code.
Display the default value in place of String if the string value is NULL:
import java.util.Optional;
public class Code
{
public static void main(String[] args)
{
String value = null;
Optional<String> optionalValue = Optional.ofNullable(value);
System.out.println(optionalValue.orElse("Default")); // Output: Default
}
}
Predicates
Predicates in Java 8 are an essential part of the java.util.function package, designed to handle
functional-style operations. Here are 10 simple points to understand Predicates in Java 8:
Functional Interface: It is a functional interface that takes an argument of a specific type and
returns a boolean value (true or false).
Single Abstract Method (SAM): As a functional interface, Predicate has a single abstract
method named test(T t), where T is the type of the input argument.
Test Condition: The test(T t) method is responsible for evaluating the condition specified by the
Predicate. If the condition is met for the input t, the method returns true; otherwise, it returns
false.
Filtering Collections: Predicates are commonly used to filter elements from collections. By
passing a Predicate to the filter() method of Java 8 streams or collections, you can selectively
retain elements that satisfy the condition.
Chaining Predicates: Predicates can be combined using logical operators like and(), or(), and
negate() to create more complex conditions for filtering.
Default Methods: The Predicate interface provides default methods like and(), or(), and negate()
to enable easy composition of predicates without requiring manual implementation.
Avoiding Null Checks: Predicates can be used to check for null values or other conditions that
could cause null pointer exceptions, providing a safer and more readable alternative to
traditional null checks.
Java Collections API: Java 8 introduced several methods in the Collections API that accept
Predicate as an argument, such as removeIf(), making it easier to perform conditional element
removal from collections.
Lambda Expressions: Predicates can be defined using lambda expressions, allowing for concise
and expressive code when dealing with conditional checks.
{
double[] numbers = { 1.2, -3.4, 5.6, -7.8, 9.0 };
Predicate<Double> isPositive = num -> num > 0;
Arrays.stream(numbers).filter(isPositive).forEach(System.out::println);
}
}
numbers.stream().filter(isEven.and(isGreaterThan5)).forEach(System.out::println);
}
}
Summary
Functional Interfaces:
• Functional interfaces have only one abstract method and are used to enable lambda
expressions and method references.
• JDK 8 introduced the @FunctionalInterface annotation to indicate that an interface is
intended to be used as a functional interface.
• Common functional interfaces like Predicate, Function, Consumer, and Supplier are
available in the java.util.function package.
Lambda Expressions:
• They provide a concise way to define single-method interfaces (functional interfaces).
Default Methods:
• Default methods are methods defined in interfaces with a default implementation.
• They were introduced to support backward compatibility when adding new methods to
existing interfaces.
• Default methods allow developers to add new functionality to interfaces without
breaking the implementations of existing classes.
forEach()
• forEach() is a terminal operation in Java 8 streams used to perform an action on each
element of the stream.
• It accepts a lambda expression or method reference that defines the action to be
executed for each element.
• forEach() does not return any value; it is mainly used for performing side effects.
forEachOrdered()
• forEachOrdered() is similar to forEach(), but it guarantees that the elements are
processed in the order they appear in the stream.
• It is mainly useful for parallel streams when you want to ensure ordered processing
regardless of parallelization.
Stream()
• Stream is an interface introduced in Java 8 that represents a sequence of elements that
can be processed in a functional-style manner.
Stream API:
• The Stream API is a powerful addition to JDK 8, allowing functional-style operations on
collections and arrays.
• The Stream API includes operations like map(), filter(), reduce(), forEach(), and collect().
• Parallel streams leverage multiple threads to enhance performance when processing
large datasets.
map():
• map() is an intermediate operation that transforms each element of a stream into
another object using the provided function.
• It takes a Function as an argument, which defines the mapping from one object to
another.
filter():
• filter() is an intermediate operation used to eliminate elements from a stream based on a
specified condition.
• It takes a Predicate as an argument, which defines the condition for filtering the
elements.
• The result of the filter() operation is a new stream containing only the elements that
satisfy the given condition.
reduce():
• reduce() is a terminal operation that aggregates the elements of a stream into a single
result.
• It takes two arguments: an identity value and a BinaryOperator, which combines two
elements into a single result.
Predicate():
• Predicate is a functional interface from the java.util.function package that represents a
boolean-valued function of one argument.
• It is often used in streams to define conditions for filtering elements.
Optional:
• Optional is a container object that may or may not contain a non-null value.
• It was introduced to help handle the problem of null references and avoid null pointer
exceptions.
• Optional provides methods like isPresent(), orElse(), and ifPresent() to work with possibly
absent values in a more explicit and safer way.
2. Define Array?
• Array: Is a set of similar data elements
long[] accNums;
3. Define Object?
• Object is a set of dis-similar data elements. For example, Student details,
Employee details, Customer details etc.
4. Define Collection?
• Collection is set of Objects. Set of Student details, Employee details.
7. Define List:
• List is ordered
• List allow duplicates
• List is index based
8. Define Set:
9. Define Map:
• Map store elements using keys
• Keys must be unique
• Values can be duplicated.
18. How to collect sorted elements into list using stream api?
• list.stream().sorted().collect(Collectors.toList());
19. Collect the sorted elements into List through streaming and display list?
• list.stream().sorted().collect(Collectors.toList()).forEach(System.out::println);
22. How to display the elements greater than 5 in a List using filter() method?
• list.stream().filter(n->n>5).forEach(System.out::println);
23. How to collect the elements greater than 5 in List using filter() method?
• List<Integer> res = list.stream().filter(n->n>5).collect(Collectors.toList());
26. How can we create Predicate that display only integers greater than 5?
• Predicate<E> pr = n -> n>5;
27. How to filter list elements which are greater than 5 using predicate?
• Predicate<Integer> pr = n -> n>5;
• list.stream().filter(pr).forEach(System.out::println);
28. How to filter list of strings starts with ‘A’ using predicate and parallel stream and
please guarantee about the order of elements?
• Predicate<String> pr = s->s.startsWith(“A”);
• List.stream().parallel().filter(pr).forEachOrdered(System.out::println);
Which provides better performance for the insertion and removal from the middle of the list?
Vector ArrayList
LinkedList All of these
The collection
extends Collections class extends Iterable interface
implements Serializable interface implements Traversable interface
Which interface provides the capability to store objects using a key-value pair?
Java.util.Map Java.util.Set
Java.util.List Java.util.Collection
Which collection class allows you to associate its elements with key values, and allows you to
retrieve objects in FIFO (first-in, first-out) sequence?
java.util.ArrayList java.util.LinkedHashMap
java.util.HashMap java.util.TreeMap
How do you get the number of elements in an ArrayList called "list" in Java?
list.size(); list.count();
list.length(); list.getSize();
What is the list nums if it is initially [5, 3, 1] and the following code is executed?
nums.add(6);
nums.add(0, 4);
nums.remove(1);
[4, 3, 1, 6] [5, 3, 1, 6]
[4, 3, 6] [4, 5, 3, 6]
Given the nums ArrayList with the values [5, 4, 3, 2], what statement below removes the value 3
from the list?
nums.remove(2) nums.remove(3)
nums.get(2) = null nums.remove(1)
Which provides better performance for the insertion and removal from the middle of the list?
Vector ArrayList
LinkedList (All of these)
What should we use when add and remove operations are more frequent than get operations?
LinkedList ArrayList
Vector All
Consider the list = [13, 22, 96, 23, 13, 76, 22, 45]
1. Display all values of list
7. Find the sum of elements in the list which are divisible by 2 but not with 3.
8. Find the sum of even numbers and odd number of given list
Display employee details belongs to Hyderabad and salary is greater than 35000
In Java 8, which interface represents a supplier of results and does not take any
argument?
Function Runnable
Consumer Supplier
Which of the following is NOT a new Date and Time API class introduced in JDK 8?
LocalDate LocalTime
DateTime LocalDateTime
Which method is used to sort the elements of a stream using a custom comparator in
Jdk8?
sort() sorted()
order() arrange()
Which method is used to combine multiple predicates into a single predicate in Java 8?
test() and()
combine() merge()
Which method is used to calculate the sum of elements in a stream of integers in Java 8?
collect() sum()
reduce() aggregate()
In the context of parallel streams, how can you ensure the order of elements in the
output?
• Use the unordered() method before the terminal operation.
• Use the forEachOrdered() method after the terminal operation.
• Use the sequential() method before the terminal operation.
• Use the parallel() method before the terminal operation.
What is the return type of the map() method in the Stream API?
List Set
Stream Map
Which method is used to combine the elements of a stream into a single value in Java?
collect() reduce()
combine() aggregate()
Which method is used to remove elements from a stream based on a given predicate?
remove() delete()
filter() exclude()
What is the return type of the collect() method in the Stream API when used to collect
elements into a List?
Set Map
List Collection
Which method is used to apply a function to each element of a stream and collect the
results in a collection?
forEach() map()
collect() process()
Which method is used to perform an action on each element of the stream and return
void?
forEach() collect()
map() reduce()
In the context of parallel programming with streams, how can you ensure the order of
elements in the output?
• By using the parallel() method before the terminal operation.
• By using the sequential() method before the terminal operation.
• By using the unordered() method before the terminal operation.
• By using the forEachOrdered() method after the terminal operation.