0% found this document useful (0 votes)
11 views52 pages

Unit Iii - Strings, Collections, and Java 8 Features

This document covers Java Strings, StringBuilder, and StringBuffer, detailing their creation, characteristics, and methods. It explains the differences between these classes, including mutability and thread safety, and provides examples of their usage. Additionally, it discusses the storage of strings in Java, including the string pool and memory management in the JVM.

Uploaded by

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

Unit Iii - Strings, Collections, and Java 8 Features

This document covers Java Strings, StringBuilder, and StringBuffer, detailing their creation, characteristics, and methods. It explains the differences between these classes, including mutability and thread safety, and provides examples of their usage. Additionally, it discusses the storage of strings in Java, including the string pool and memory management in the JVM.

Uploaded by

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

Unit – III Strings, Collections & Java 8 Features

Strings, creation, declaration of a string, storage structure of a string and its methods,
StringBuilder, String Buffer, regex , Collection ; Interface , Generics , List, Set, Map
interfaces and classes, Comparable , Comparator , Java lambda expressions , Date & time
Object in java 1.8 and its functions , Streams , Java new features
Strings
In Java, a String is an object that represents a sequence of characters. Java provides a robust
and flexible API for handling strings, allowing for various operations such as concatenation,
comparison, and manipulation.
What are Strings in Java?
Strings are the type of objects that can store the character of values and in Java, every
character is stored in 16 bits i,e using UTF 16-bit encoding. A string acts the same as an array
of characters in Java.
String name = "Geeks";

public class StringExample {


public static void main(String args[])
{
String str = new String("example");
System.out.println(str);
}
}
Output:
Example
Ways of Creating a String
There are two ways to create a string in Java:
String Literal
Using new Keyword
Syntax:
<String_Type> <string_variable> = "<sequence_of_string>";
1. String literal
To make Java more memory efficient (because no new objects are created if it exists already
in the string constant pool).
Example:
String demoString = “This is II EEE”;
2. Using new keyword
String s = new String(“Welcome”);
In such a case, JVM will create a new string object in normal (non-pool) heap memory and
the literal “Welcome” will be placed in the string constant pool. The variable s will refer to
the object in the heap (non-pool)
Example:
String demoString = new String (“GeeksforGeeks”);
Interfaces and Classes in Strings in Java
CharBuffer: This class implements the CharSequence interface. This class is used to allow
character buffers to be used in place of CharSequences. An example of such usage is the
regular-expression package java.util.regex.
String: It is a sequence of characters. In Java, objects of String are immutable which means a
constant and cannot be changed once created.
CharSequence Interface
CharSequence Interface is used for representing the sequence of Characters in Java. Classes
that are implemented using the CharSequence interface are mentioned below and these
provides much of functionality like substring, lastoccurence, first occurence, concatenate ,
toupper, tolower etc.
String
StringBuffer
StringBuilder
1. String
String is an immutable class which means a constant and cannot be changed once created and
if we wish to change, we need to create a new object. It is automatically thread safe.
Example:
String str= "Hello";
or
String str= new String("Hello")
2. StringBuffer
StringBuffer is a peer class of String, it is mutable in nature and it is thread safe class , we can
use it when we have multi threaded environment and shared object of string buffer i.e, used
by mutiple thread. As it is thread safe so there is extra overhead, so it is mainly used for
multithreaded program.
Example:
StringBuffer demoString = new StringBuffer("Hello");
3. StringBuilder
StringBuilder in Java represents an alternative to String and StringBuffer Class, as it creates a
mutable sequence of characters and it is not thread safe. It is used only within the thread, so
there is no extra overhead , so it is mainly used for single threaded program.
Example:
StringBuilder demoString = new StringBuilder();
demoString.append("Hello");
Java String class methods
The java.lang.String class provides many useful methods to perform operations on sequence
of char values.
Storage of String in Java
In Java, we know both Stack and Heap space are part of Java Virtual Machine (JVM).
However, these memory spaces are used for different purposes. Stack space contains specific
values that are short-lived whereas Heap space is by Java Runtime to allocate memory to
objects and JRE classes. In Java, strings are stored in the heap area.
Why are Java strings stored in Heap, not in Stack?
String is a class, and strings in Java are treated as an object, hence the object of String class
will be stored in Heap, not in the stack area.
String Pool
Storage of strings in java is different from other programming languages. We all
know that the reference variables are stored in stack and their values are stored in heap. Same
happens in the case of Strings, the reference variables are stored in stack but their objects
along with given values are stored in a string pool which is a separate memory space inside
the heap.
When we create a string-type object it gets stored in string pool of heap. At this point
string pool is created in heap. Whenever we create a new string with the same value or
without same value the JVM checks whether the given value is already available in string
pool or not. If it is not available then new value is created for that reference variable but in
opposite case, JVM does not recreate new object with given value it simply points the old
value to that reference variable.
Example
Suppose we are creating a string object as
String st4 = “Tutorix”;
Then, it will be stored in string pool.

When we create a new String object


String st5 = “Tutorials”; Then,

But, If we initialize the st5 to “Tutorix” then JVM doesn’t create new object for it. It points
the older value to the ‘st5’.
Program to check Storage of String
We can check whether the two reference variables are pointing to the same object or not
using comparison operator ‘==’. It returns true when two object references refer to the same
instance otherwise false.
Example 1
In this example, we will declare and initialize two string variables ‘st1’ and ‘st2’ with same
value. Then, we will use == operator to check whether they are pointing to same object or
not. The result will be stored in a Boolean variable ‘isSame’.
public class Main {
public static void main(String[] args) {
String st1 = "Tutorix";
String st2 = "Tutorix";
boolean isSame = (st1 == st2);
System.out.print(isSame);
}
}
Output:
True
Example 2
In this example, we will create two string objects using new keyword. When we use the new
keyword JVM creates a new object irrespective of the value of given object. In other words,
JVM will create a new object for given reference variable whether the value is same or not.
public class Main {
public static void main(String[] args) {
String st1 = new String("Tutorix");
String st2 = new String("Tutorix");
boolean isSame = (st1 == st2);
System.out.print(isSame);
}
}
Output:
false
StringBuilder Class in Java
The StringBuilder class in Java represents a String-like character sequence that is
mutable, whereas objects of the String class are immutable. This provides an alternative to
the String class when it’s a requirement to change a character sequence once it is defined.
It is similar to another class, StringBuffer, but it is faster in most circumstances. The
difference between StringBuilder and StringBuffer is that StringBuilder is not thread-
safe. StringBuilder offers no guarantee of synchronization and should not be used across
multiple threads.
Syntax
StringBuilder s1 = new StringBuilder();
StringBuilder s2 = new StringBuilder(capacity);
StringBuilder s3 = new StringBuilder(sequence);
A StringBuilder can be created in the following ways:
 Calling the constructor with no arguments creates a StringBuilder with no contents
and a capacity of 16 characters.
 Calling the constructor with the int argument, capacity, creates a StringBuilder with
no contents and a capacity of capacity characters.
 Calling the constructor with a sequence argument that is either a String or
a CharSequence creates a StringBuilder with contents and capacity equal to the
specified String or CharSequence.
Example program for StringBuilder
import java.util.*;
public class Example {
public static void main(String[] args)
{
StringBuilder str = new StringBuilder("Hello");
System.out.println(str.toString());
str.append(" World!");
System.out.println(str.toString());
}
}
Output:
Hello
Hello World!
StringBuilder
.append()
Appends the string representation of its argument.
.capacity()
Returns the current space available for characters in the StringBuilder.
.delete()
Removes a substring from the contents of a StringBuilder and returns the modified
object.
.deleteCharAt()
Removes the character at the specified index from the contents of a StringBuilder and
returns the modified object.
.indexOf()
Returns the index of the first occurrence of a substring in the StringBuilder or -1 if
none are found.
.insert()
Places a sequence of characters into a StringBuilder and returns a reference to the
object.
.lastIndexOf()
Returns the index of the last (rightmost) occurrence of a substring in the StringBuilder
or -1 if no substring is found.
.length()
Returns the number of characters currently in the StringBuilder.
.replace()
Switches a substring in a StringBuilder with a specified String and returns the
modified object.
.reverse()
Returns a modified StringBuilder object with its character sequence rearranged in the
opposite order.
.substring()
Returns a String object representing a substring of the character sequence currently in
a given StringBuilder.
.toString()
Returns a String representation of the character sequence currently in a given
StringBuilder.
StringBuffer class in Java
StringBuffer is a class in Java that represents a mutable sequence of characters. It provides an
alternative to the immutable String class, allowing you to modify the contents of a string
without creating a new object every time.
Here are some important features and methods of the StringBuffer class:
StringBuffer objects are mutable, meaning that we can change the contents of the buffer
without creating a new object.
The initial capacity of a StringBuffer can be specified when it is created, or it can be set later
with the ensureCapacity() method.
The append() method is used to add characters, strings, or other objects to the end of the
buffer.
The insert() method is used to insert characters, strings, or other objects at a specified
position in the buffer.
The delete() method is used to remove characters from the buffer.
The reverse() method is used to reverse the order of the characters in the buffer.
Example program for using StringBuffer to concatenate two strings:
public class StringBufferExample {
public static void main(String[] args)
{
StringBuffer sb = new StringBuffer();
sb.append("Hello");
sb.append(" ");
sb.append("world");
String message = sb.toString();
System.out.println(message);
}
}
Output:
Hello world
There are several advantages of using StringBuffer over regular String objects in Java:
Mutable: StringBuffer objects are mutable, which means that we can modify the contents of
the object after it has been created. In contrast, String objects are immutable, which means
that we cannot change the contents of a String once it has been created.
Efficient: Because StringBuffer objects are mutable, they are more efficient than creating
new String objects each time we need to modify a string. This is especially true if we need to
modify a string multiple times, as each modification to a String object creates a new object
and discards the old one.
StringBuffer is a peer class of String that provides much of the functionality of strings. The
string represents fixed-length, immutable character sequences while StringBuffer represents
growable and writable character sequences. StringBuffer may have characters and substrings
inserted in the middle or appended to the end.
StringBuffer class is used to create mutable (modifiable) strings. The StringBuffer class in
Java is the same as the String class except it is mutable i.e. it can be changed.
Important Constructors of StringBuffer class
StringBuffer(): creates an empty string buffer with an initial capacity of 16.
StringBuffer(String str): creates a string buffer with the specified string.
StringBuffer(int capacity): creates an empty string buffer with the specified capacity as
length.
1. append() method
The append() method concatenates the given argument with this string.
Example:
import java.io.*;
class A {
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Hello ");
sb.append("Java"); // now original string is changed
System.out.println(sb);
}
}
Output:
Hello Java
2. insert() method
The insert() method inserts the given string with this string at the given position.
Example:
import java.io.*;
class A {
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Hello ");
sb.insert(1, "Java");
// Now original string is changed
System.out.println(sb);
}
}
Output
HJavaello
3. replace() method
The replace() method replaces the given string from the specified beginIndex and endIndex-
1.
Example:
import java.io.*;
class A {
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Hello");
sb.replace(1, 3, "Java");
System.out.println(sb);
}
}

Output
HJavalo
4. delete() method
The delete() method of the StringBuffer class deletes the string from the specified beginIndex
to endIndex-1.
Example:
import java.io.*;
class A {
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Hello");
sb.delete(1, 3);
System.out.println(sb);
}
}
Output
Hlo
5. reverse() method
The reverse() method of the StringBuilder class reverses the current string.
Example:
import java.io.* ;
class A {
public static void main(String args[])
{
StringBuffer sb = new StringBuffer("Hello");
sb.reverse();
System.out.println(sb);
}
}
Output
olleH
6. capacity() method
The capacity() method of the StringBuffer class returns the current capacity of the buffer. The
default capacity of the buffer is 16. If the number of characters increases from its current
capacity, it increases the capacity by (oldcapacity*2)+2.
For instance, if your current capacity is 16, it will be (16*2)+2=34.
Example:
import java.io.*;
class A {
public static void main(String args[])
{
StringBuffer sb = new StringBuffer();
System.out.println(sb.capacity()); // default 16
sb.append("Hello");
System.out.println(sb.capacity()); // now 16
sb.append("java is my favourite language");
System.out.println(sb.capacity());
// Now (16*2)+2=34 i.e (oldcapacity*2)+2
}
}
Output
16
16
34
Constructors of StringBuffer class
1. StringBuffer(): It reserves room for 16 characters without reallocation
StringBuffer s = new StringBuffer();
2. StringBuffer( int size): It accepts an integer argument that explicitly sets the size of the
buffer.
StringBuffer s = new StringBuffer(20);
3. StringBuffer(String str): It accepts a string argument that sets the initial contents of the
StringBuffer object and reserves room for 16 more characters without reallocation.

StringBuffer s = new StringBuffer("HelloIIEEE");


Methods of Java StringBuffer class

Methods Action Performed

append() Used to add text at the end of the existing text.

length() The length of a StringBuffer can be found by the length( )


method.

the total allocated capacity can be found by the capacity(


capacity() ) method. By default, a string buffer has a 16 character
capacity.

This method returns the char value in this sequence at the


charAt()
specified index.

Deletes a sequence of characters from the invoking


delete()
object.

deleteCharAt() Deletes the character at the index specified by the loc.

ensureCapacity() Ensures capacity is at least equal to the given minimum.

insert() Inserts text at the specified index position.

length() Returns the length of the string.

reverse() Reverse the characters within a StringBuffer object.

Replace one set of characters with another set inside a


replace()
StringBuffer object.

Example 1: length() and capacity() Methods


// Java Program to Illustrate StringBuffer class via length() and capacity() methods
// Importing I/O classes
import java.io.*;
// Main class
class check {
// main driver method
public static void main(String[] args)
{
// Creating and storing string by creating object of
// StringBuffer
StringBuffer s = new StringBuffer("Hello");
// Getting the length of the string
int p = s.length();
// Getting the capacity of the string
int q = s.capacity();
// Printing the length and capacity of
// above generated input string on console
System.out.println("Length of string Hello="
+ p);
System.out.println(
"Capacity of string Hello=" + q);
}
}
Output
Length of string Hello=5
Capacity of string Hello=21
Example 2: append()
It is used to add text at the end of the existing text.
StringBuffer append(String str)
StringBuffer append(int num)
// Java Program to Illustrate StringBuffer class via append() method
// Importing required classes
import java.io.*;
// Main class
class demo{
// Main driver method
public static void main(String[] args)
{
// Creating an object of StringBuffer class and
// passing random string
StringBuffer s = new StringBuffer("HelloIIEEE");
// Usage of append() method
s.append("How are you?");
// Returns How are you?
System.out.println(s);
s.append(1);
// Returns How are you?1
System.out.println(s);
}
}
Output
HelloIIEEEHow are you?
HelloIIEEEHow are you?1
Example 3: insert()
It is used to insert text at the specified index position.
Syntax:
StringBuffer insert(int index, String str)
StringBuffer insert(int index, char ch)
Here, the index specifies the index at which point the string will be inserted into the invoking
StringBuffer object.
// Java Program to Illustrate StringBuffer class via insert() method
// Importing required I/O classes
import java.io.*;
// Main class
class GFG {
public static void main(String[] args)
{
// Creating an object of StringBuffer class
StringBuffer s = new StringBuffer("GeeksGeeks");
// Inserting element and position as an arguments
s.insert(5, "for");
// Returns GeeksforGeeks
System.out.println(s);
s.insert(0, 5);
// Returns 5GeeksforGeeks
System.out.println(s);
s.insert(3, true);
// Returns 5GetrueeksforGeeks
System.out.println(s);
s.insert(5, 41.35d);
// Returns 5Getr41.35ueeksforGeeks
System.out.println(s);
s.insert(8, 41.35f);
// Returns 5Getr41.41.3535ueeksforGeeks
System.out.println(s);
// Declaring and initializing character array
char geeks_arr[] = { 'p', 'a', 'w', 'a', 'n' };
// Inserting character array at offset 9
s.insert(2, geeks_arr);
// Returns 5Gpawanetr41.41.3535ueeksforGeeks
System.out.println(s);
}
}
Output
GeeksforGeeks
5GeeksforGeeks
5GetrueeksforGeeks
5Getr41.35ueeksforGeeks
5Getr41.41.3535ueeksforGeeks
5Gpawanetr41.41.3535ueeksforGeeks
Example 4: reverse( )
It can reverse the characters within a StringBuffer object using reverse( ). This method
returns the reversed object on which it was called.
// Java Program to Illustrate StringBuffer class via reverse() method
// Importing I/O classes
import java.io.*;
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Creating a string via creating
// object of StringBuffer class
StringBuffer s = new StringBuffer("GeeksGeeks");
// Invoking reverse() method
s.reverse();
// Returns "skeeGrofskeeG"
System.out.println(s);
}
}
Output
skeeGskeeG
Example 5: delete( ) and deleteCharAt()
It can delete characters within a StringBuffer by using the methods delete( ) and
deleteCharAt( ).The delete( ) method deletes a sequence of characters from the invoking
object. Here, the start Index specifies the index of the first character to remove, and the end
Index specifies an index one past the last character to remove. Thus, the substring deleted
runs from start Index to endIndex–1. The resulting StringBuffer object is returned. The
deleteCharAt( ) method deletes the character at the index specified by loc. It returns the
resulting StringBuffer object.
Syntax:
StringBuffer delete(int startIndex, int endIndex)
StringBuffer deleteCharAt(int loc)
// Java Program to Illustrate StringBuffer class
// via delete() and deleteCharAt() Methods
// Importing I/O classes
import java.io.*;
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
StringBuffer s = new StringBuffer("GeeksforGeeks");
s.delete(0, 5);
// Returns forGeeks
System.out.println(s);
s.deleteCharAt(7);
// Returns forGeek
System.out.println(s);
}
}
Output
forGeeks
forGeek
Example 6: replace()
It can replace one set of characters with another set inside a StringBuffer object by calling
replace( ). The substring being replaced is specified by the indexes start Index and endIndex.
Thus, the substring at start Index through endIndex–1 is replaced. The replacement string is
passed in str. The resulting StringBuffer object is returned.
Syntax:
StringBuffer replace(int startIndex, int endIndex, String str)
Example
// Java Program to Illustrate StringBuffer class via replace() method
import java.io.*;
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
StringBuffer s = new StringBuffer("GeeksforGeeks");
s.replace(5, 8, "are");
System.out.println(s);
}
}
Output
GeeksareGeeks
Regular Expressions in Java
A regular expression is a sequence of characters that forms a search pattern. When we
search for data in a text, we can use this search pattern to describe what we are searching for.
A regular expression can be a single character, or a more complicated pattern. Regular
expressions can be used to perform all types of text search and text replace operations.
In Java, Regular Expressions or Regex (in short) in Java is an API for defining String
patterns that can be used for searching, manipulating, and editing a string in Java. Email
validation and passwords are a few areas of strings where Regex is widely used to define the
constraints. Regular Expressions in Java are provided under java.util.regex package. This
consists of 3 classes and 1 interface. The java.util.regex package primarily consists of the
following three classes as depicted below:
Regex Classes and Interfaces
Regex in Java provides 3 classes and 1 interface which are as follows:
1. Pattern Class
2. Matcher Class
3. PatternSyntaxException Class
4. MatchResult Interface

S. No. Class/Interface Description

1. Pattern Class Used for defining patterns

Used for performing match operations on text


2. Matcher Class
using patterns

PatternSyntaxException Used for indicating syntax error in a regular


3.
Class expression pattern

Used for representing the result of a match


4. MatchResult Interface
operation

Example Program:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("w3schools", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher("Visit W3Schools!");
boolean matchFound = matcher.find();
if(matchFound) {
System.out.println("Match found");
} else {
System.out.println("Match not found");
}
}
}
Output:
Match found
Collections in Java
The Collection in Java is a framework that provides an architecture to store and manipulate
the group of objects.
Java Collections can achieve all the operations that you perform on a data such as searching,
sorting, insertion, manipulation, and deletion.
Java Collection means a single unit of objects. Java Collection framework provides many
interfaces (Set, List, Queue, Deque) and classes (ArrayList, Vector, LinkedList,
PriorityQueue, HashSet, LinkedHashSet, TreeSet).
What is Collection in Java?
A Collection represents a single unit of objects, i.e., a group.
What is a framework in Java
 It provides readymade architecture.
 It represents a set of classes and interfaces.
 It is optional.
What is Collection framework?
The Collection framework represents a unified architecture for storing and manipulating a
group of objects. It has:
1. Interfaces and its implementations, i.e., classes
2. Algorithm
3. ArrayList
4. The ArrayList class implements the List interface. It uses a dynamic array to store the
duplicate element of different data types. The ArrayList class maintains the insertion order
and is non-synchronized. The elements stored in the ArrayList class can be randomly
accessed.
Hierarchy of Collection Framework

Collection Interface
The Collection interface is the interface which is implemented by all the classes in the
collection framework. It declares the methods that every collection will have. In other words,
we can say that the Collection interface builds the foundation on which the collection
framework depends.
Some of the methods of Collection interface are Boolean add ( Object obj), Boolean addAll (
Collection c), void clear(), etc. which are implemented by all the subclasses of Collection
interface.
Generics
Generics means parameterized types. The idea is to allow a type (like Integer, String,
etc., or user-defined types) to be a parameter to methods, classes, and interfaces. Using
Generics, it is possible to create classes that work with different data types. An entity such as
a class, interface, or method that operates on a parameterized type is a generic entity.
Why Generics?
The Object is the superclass of all other classes, and Object reference can refer to any
object. These features lack type safety. Generics add that type of safety feature. Generics in
Java are similar to templates in C++. For example, classes like HashSet, ArrayList,
HashMap, etc., use generics very well. There are some fundamental differences between the
two approaches to generic types.
Generics provide a way to create reusable code components in Java, improving type
safety and readability. If you’re looking to master generics, the Java Programming Course
offers detailed lessons and real-world examples to help you apply generics effectively.
Types of Java Generics
Generic Method: Generic Java method takes a parameter and returns some value after
performing a task. It is exactly like a normal function, however, a generic method has type
parameters that are cited by actual type. This allows the generic method to be used in a more
general way. The compiler takes care of the type of safety which enables programmers to
code easily since they do not have to perform long, individual type castings.
Generic Classes: A generic class is implemented exactly like a non-generic class. The only
difference is that it contains a type parameter section. There can be more than one type of
parameter, separated by a comma. The classes, which accept one or more parameters are
known as parameterized classes or parameterized types.
Generic Class
Like C++, we use <> to specify parameter types in generic class creation. To create
objects of a generic class, we use the following syntax.
// To create an instance of generic class
BaseType <Type> obj = new BaseType <Type>()
Example program:
// Java program to show working of user defined Generic classes

// We use < > to specify Parameter type


class Test<T> {
// An object of type T is declared
T obj;
Test(T obj) { this.obj = obj; } // constructor
public T getObject() { return this.obj; }
}
// Driver class to test above
class Main {
public static void main(String[] args)
{
// instance of Integer type
Test<Integer> iObj = new Test<Integer>(15);
System.out.println(iObj.getObject());
// instance of String type
Test<String> sObj
= new Test<String>("Hello");
System.out.println(sObj.getObject());
}
}
Output:
15
Hello
Generic Functions:
We can also write generic functions that can be called with different types of
arguments based on the type of arguments passed to the generic method. The compiler
handles each method.
Example Program:
// Java program to show working of user defined Generic functions
class Test {
// A Generic method example
static <T> void genericDisplay(T element)
{
System.out.println(element.getClass().getName()
+ " = " + element);
}
// Driver method
public static void main(String[] args)
{
// Calling generic method with Integer argument
genericDisplay(11);
// Calling generic method with String argument
genericDisplay("Hello");
// Calling generic method with double argument
genericDisplay(1.0);
}
}
Output:
java.lang.Integer = 11
java.lang.String = Hello
java.lang.Double = 1.0
Advantages of Generics

 Code Reusability: We can write a method, class, or interface once and use it with any
type.
 Type Safety: Generics ensure that errors are detected at compile time rather than
runtime, promoting safer code.
 No Need for Type Casting: The compiler automatically handles casting, removing the
need for explicit type casting when retrieving data.
 Code Readability and Maintenance: By specifying types, code becomes easier to read
and maintain.
 Generic Algorithms: Generics allow for the implementation of algorithms that work
across various types, promoting efficient coding practices.
Disadvantages of Generics

 Complexity
 Performance Overhead
 No Support for Primitive Types
 Limited Reflection
List Interface
List interface is the child interface of Collection interface. It inhibits a list type data structure
in which we can store the ordered collection of objects. It can have duplicate values.
List interface is implemented by the classes ArrayList, LinkedList, Vector, and Stack.
To instantiate the List interface, we must use :
1. List <data-type> list1= new ArrayList();
2. List <data-type> list2 = new LinkedList();
3. List <data-type> list3 = new Vector();
4. List <data-type> list4 = new Stack();
ArrayList
The ArrayList class implements the List interface. It uses a dynamic array to store the
duplicate element of different data types. The ArrayList class maintains the insertion order
and is non-synchronized. The elements stored in the ArrayList class can be randomly
accessed. Consider the following example.
import java.util.*;
class TestJavaCollection1{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Ravi");//Adding object in arraylist
list.add("Vijay");
list.add("Ravi");
list.add("Ajay");
//Traversing list through Iterator
Iterator itr=list.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output:
Ravi
Vijay
Ravi
Ajay
LinkedList
LinkedList implements the Collection interface. It uses a doubly linked list internally to store
the elements. It can store the duplicate elements. It maintains the insertion order and is not
synchronized. In LinkedList, the manipulation is fast because no shifting is required.
Consider the following example.
import java.util.*;
public class TestJavaCollection2{
public static void main(String args[]){
LinkedList<String> al=new LinkedList<String>();
al.add("Ravi");
al.add("Vijay");
al.add("Ravi");
al.add("Ajay");
Iterator<String> itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output:
Ravi
Vijay
Ravi
Ajay
Vector
Vector uses a dynamic array to store the data elements. It is similar to ArrayList. However, It
is synchronized and contains many methods that are not the part of Collection framework.
Consider the following example.
import java.util.*;
public class TestJavaCollection3{
public static void main(String args[]){
Vector<String> v=new Vector<String>();
v.add("Ayush");
v.add("Amit");
v.add("Ashish");
v.add("Garima");
Iterator<String> itr=v.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output:
Ayush
Amit
Ashish
Garima
Set Interface
Set is an interface which is the child interface of Collection interface and grandchild of
Iterable interface. Set is not an index based data structure and all the datas are stored in
accordance with the hashcode values. Duplicate elements cannot be stored in Set. Set allows
only one null value to be stored in it. Set does not follow the order of insertion. Set elements
can be iterated by only Iterator method. The various implemented classes of Set interface are
HashSet,LinkedHashSet and TreeSet where HashSet and LinkedHashSet are child classes of
Set interface and TreeSet is the great grand child class of Set interface. The various child
interfaces associated with Set are SortedSet and Navigation Set where SortedSet is the child
interface of Set, Navigation Set is the grandchild interface of Set.
Since Set is an interface we cannot create Object of Set directly but instead we upcast the
implemented classes of Set like HashSet, LinkedHashSet etc. with Set in order to create an
instance of Set.
Methods of Set interface

Method Name Description

add(Object e) This method is used to add a new element of any datatype into the Set interface.

addAll(Collection c) This method is used to add all elements of different datatypes into the Set interface.

It is used to clear all the elements from the Set interface but it does not clear the Set
clear()
interface.

contains(Object o) This method is used to check the presence of a Collection element in the Set. It returns
‘true’ value if the element is present in Set and ‘false’ value if the element is not present
in the Set.

This method is used to check if the Set contains all the collection elements. It returns
containsAll(Collection
‘true’ value if all the elements are present in Set and ‘false’ value if any one of the
c)
element is not present in the Set.

isEmpty() This method checks if the given Set is empty

iterator() This method is used to iterate sequentially all the Collection elements present in a Set.

remove(Object o) This method is used to remove a specified collection element from the Set.

removeAll(Collection This method removes all those Collection elements from the current Set which are
c) present in another Set.

This method retains all those elements from the current Set which are present in another
retainAll(Collection c) Set and removes those elements which are present in current Set but not in another Set
and vice versa.

This method is used to find out and display the number of Collection elements present
size()
in the Set

toArray() This method is used to convert all collection elements present in a Set into an array.

toString() This method is used to convert all collection elements present in a Set into a String.

This method is used to check if two Sets are equal. It returns ‘true’ value if elements as
well as size of elements present in one Set is equal to the elements and its size present in
equals()
another Set. If the elements and the size of elements present in one Set is not equal to
the elements and its size present in another Set then it returns ‘false’ value.

add(Object e) method in Set interface.


Example Program:
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class SetInterfaceProgram {
public static void main(String[] args) {
Set a1= new HashSet();
a1.add(12);
a1.add("hello");
a1.add('c');
a1.add(3.4f);
a1.add(true);
a1.add(null);
a1.add(3.55);
System.out.println(a1);
}
}
Output: [null, c, 3.4, 3.55, hello, 12, true]
addAll(Collection c) method in Set interface.
Example Program:
import java.util.HashSet;
import java.util.Set;
public class SetInterfaceProgram {
public static void main(String[] args) {
Set a1= new HashSet();
a1.add(12);
a1.add("hello");
a1.add('c');
a1.add(3.4f);
a1.add(true);
a1.add(null);
a1.add(3.55);
a1.add("Hiii");
Set a2= new HashSet();
a2.addAll(a1);
System.out.println(a2);
}
}
Output:
[null, c, 3.4, Hiii, 3.55, hello, 12, true]
clear() method in Set interface.
Example Program:
import java.util.HashSet;
import java.util.Set;
public class SetInterfaceProgram {
public static void main(String[] args) {
Set a1= new HashSet();
a1.add(12);
a1.add("hello");
a1.add('c');
a1.add(3.4f);
a1.add(true);
a1.add(null);
a1.add(3.55);
a1.add("Hiii");
a1.clear();
System.out.println(a1);
}
}
Output: []
Map interface
In Java, Map Interface is present in java.util package represents a mapping between a
key and a value. Java Map interface is not a subtype of the Collection interface. Therefore, it
behaves a bit differently from the rest of the collection types. A map contains unique keys.
The Map interface allows for efficient data storage in key-value pairs, making it essential for
many applications.
Maps are perfect to use for key-value association mapping such as dictionaries. The
maps are used to perform lookups by keys or when someone wants to retrieve and update
elements by keys. Some common scenarios are as follows:
A map of error codes and their descriptions.
A map of zip codes and cities.
A map of managers and employees. Each manager (key) is associated with a list of
employees (value) he manages.
A map of classes and students. Each class (key) is associated with a list of students
(value).
Java Map Interface
A map contains values on the basis of key, i.e. key and value pair. Each key and value
pair is known as an entry. A Map contains unique keys. A Map is useful if we have to search,
update or delete elements on the basis of a key.

Class Description

HashMap HashMap is the implementation of Map, but it doesn't maintain any order.

LinkedHashMap is the implementation of Map. It inherits HashMap class. It maintains


LinkedHashMap
insertion order.

TreeMap TreeMap is the implementation of Map and SortedMap. It maintains ascending order.

Characteristics of a Map Interface


 A Map cannot contain duplicate keys and each key can map to at most one value.
 The order of a map depends on the specific implementations. For example, TreeMap
and LinkedHashMap have predictable orders, while HashMap does not.
 There are two interfaces for implementing Map in Java. They are Map and SortedMap,
and three classes: HashMap, TreeMap, and LinkedHashMap.
Methods in Java Map Interface

Method Action Performed

This method is used in Java Map Interface to clear and


clear() remove all of the elements or mappings from a specified
Map collection.

This method is used in Map Interface in Java to check


whether a particular key is being mapped into the Map or
containsKey(Object)
not. It takes the key element as a parameter and returns True
if that element is mapped in the map.

containsValue(Object) This method is used in Map Interface to check whether a


particular value is being mapped by a single or more than
one key in the Map. It takes the value as a parameter and
returns True if that value is mapped by any of the keys in the
map.

This method is used in Map Interface in Java to create a set


out of the same elements contained in the map. It basically
entrySet()
returns a set view of the map or we can create a new set and
store the map elements into them.

This method is used in Java Map Interface to check for


equality between two maps. It verifies whether the elements
equals(Object)
of one map passed as a parameter is equal to the elements of
this map or not.

This method is used to retrieve or fetch the value mapped by


get(Object) a particular key mentioned in the parameter. It returns NULL
when the map contains no such mapping for the key.

This method is used in Map Interface to generate a hashCode


hashCode()
for the given map containing keys and values.

This method is used to check if a map is having any entry for


isEmpty() key and value pairs. If no mapping exists, then this returns
true.

This method is used in Map Interface to return a Set view of


keySet() the keys contained in this map. The set is backed by the map,
so changes to the map are reflected in the set, and vice-versa.

This method is used in Java Map Interface to associate the


put(Object, Object)
specified value with the specified key in this map.
This method is used in Map Interface in Java to copy all of
putAll(Map)
the mappings from the specified map to this map.

This method is used in Map Interface to remove the mapping


remove(Object)
for a key from this map if it is present in the map.

This method is used to return the number of key/value pairs


size()
available in the map.

This method is used in Java Map Interface to create a


values() collection out of the values of the map. It basically returns a
Collection view of the values in the HashMap.

getOrDefault(Object Returns the value to which the specified key is mapped, or


key, V defaultValue) defaultValue if this map contains no mapping for the key.

merge(K key, V value,


If the specified key is not already associated with a value or
BiFunction<? super V,?
is associated with null, associate it with the given non-null
super V,? extends V>
value.
remappingFunction)

If the specified key is not already associated with a value (or


putIfAbsent(K key, V
is mapped to null) associates it with the given value and
value)
returns null, else returns the current associate value.

Example:
import java.util.HashMap;
import java.util.Map;
public class MapCreationExample {
public static void main(String[] args) {
// Create a Map using HashMap
Map<String, Integer> map = new HashMap<>();
//here, we can write all other required operations

// Displaying the Map


System.out.println("Map elements: " + map);
}
}
Output:
Map elements: {}
Example:
// Java Program to Demonstrate working of Map interface
import java.util.*;
class example {
// Main driver method
public static void main(String args[])
{
// Creating an empty HashMap
Map<String, Integer> hm
= new HashMap<String, Integer>();
// Inserting pairs in above Map using put() method
hm.put("a", new Integer(100));
hm.put("b", new Integer(200));
hm.put("c", new Integer(300));
hm.put("d", new Integer(400));
// Traversing through Map using for-each loop
for (Map.Entry<String, Integer> m:
hm.entrySet()) {
// Printing keys
System.out.print(m.getKey() + ":");
System.out.println(m.getValue());
}
}
}
Output:
a:100
b:200
c:300
d:400
Hierarchy of Map Interface in Java
Classes that implement the Map interface are depicted in the below.

1. HashMap
HashMap is a part of Java’s collection since Java 1.2. It provides the basic
implementation of the Map interface of Java. It stores the data in (Key, Value) pairs. To
access a value one must know its key. This class uses a technique called Hashing. Hashing is
a technique of converting a large String to a small String that represents the same String. A
shorter value helps in indexing and faster searches. The following example will create a map
object using this class.
Example:
// Java Program to illustrate the Hashmap Class
import java.util.*;
// Main class
public class check {
// Main driver method
public static void main(String[] args)
{
// Creating an empty HashMap
Map<String, Integer> map = new HashMap<>();
// Inserting entries in the Map using put() method
map.put("vishal", 10);
map.put("sachin", 30);
map.put("vaibhav", 20);

// Iterating over Map


for (Map.Entry<String, Integer> e : map.entrySet())
// Printing key-value pairs
System.out.println(e.getKey() + " "+ e.getValue());
}
}
Output:
vaibhav 20
vishal 10
sachin 30
2. LinkedHashMap
LinkedHashMap is just like HashMap with the additional feature of maintaining an
order of elements inserted into it. HashMap provided the advantage of quick insertion, search,
and deletion but it never maintained the track and order of insertion which the
LinkedHashMap provides where the elements can be accessed in their insertion order.
Example:
// Java Program to Illustrate the LinkedHashmap Class
import java.util.*;
public class example {
public static void main(String[] args)
{
Map<String, Integer> map = new LinkedHashMap<>();
// Inserting pair entries in above Map using put() method
map.put("vishal", 10);
map.put("sachin", 30);
map.put("vaibhav", 20);
// Iterating over Map
for (Map.Entry<String, Integer> e : map.entrySet())
// Printing key-value pairs
System.out.println(e.getKey() + " "
+ e.getValue());
}
}

Output:
vishal 10
sachin 30
vaibhav 20
3. TreeMap
The TreeMap in Java is used to implement the Map interface and NavigableMap
along with the Abstract Class. The map is sorted according to the natural ordering of its keys,
or by a Comparator provided at map creation time, depending on which constructor is used.
This proves to be an efficient way of sorting and storing the key-value pairs. The storing
order maintained by the treemap must be consistent with equals just like any other sorted
map, irrespective of the explicit comparators.
Example:
// Java Program to Illustrate TreeMap Class
import java.util.*;
public class GFG {
public static void main(String[] args)
{
// Creating an empty TreeMap
Map<String, Integer> map = new TreeMap<>();
// Inserting custom elements in the Map using put() method
map.put("vishal", 10);
map.put("sachin", 30);
map.put("vaibhav", 20);
// Iterating over Map using for each loop
for (Map.Entry<String, Integer> e : map.entrySet())
// Printing key-value pairs
System.out.println(e.getKey() + " "
+ e.getValue());
}
}
Output:
sachin 30
vaibhav 20
vishal 10
Comparable vs. Comparator in Java
Java provides two interfaces to sort objects using data members of the class:
Comparable
Comparator

Comparable Comparator

1) Comparable provides a single sorting sequence. The Comparator provides multiple sorting sequences. In
In other words, we can sort the collection on the other words, we can sort the collection on the basis of
basis of a single element such as id, name, and price. multiple elements such as id, name, and price etc.

2) Comparable affects the original class, i.e., the Comparator doesn't affect the original class, i.e., the
actual class is modified. actual class is not modified.

3) Comparable provides compareTo() method to sort


Comparator provides compare() method to sort elements.
elements.

4) Comparable is present in java.lang package. A Comparator is present in the java.util package.

5) We can sort the list elements of Comparable type We can sort the list elements of Comparator type
by Collections.sort(List) method. by Collections.sort(List, Comparator) method.

Using Comparable Interface


A comparable object is capable of comparing itself with another object. The class
itself must implements the java.lang.Comparable interface to compare its instances.
Example:
//Java Program to demonstrate the use of Java Comparable.
//Creating a class which implements Comparable Interface
import java.util.*;
import java.io.*;
class Student implements Comparable<Student>{
int rollno;
String name;
int age;
Student(int rollno,String name,int age){
this.rollno=rollno;
this.name=name;
this.age=age;
}
public int compareTo(Student st){
if(age==st.age)
return 0;
else if(age>st.age)
return 1;
else
return -1;
}
}
//Creating a test class to sort the elements
public class TestSort3{
public static void main(String args[]){
ArrayList<Student> al=new ArrayList<Student>();
al.add(new Student(101,"Vijay",23));
al.add(new Student(106,"Ajay",27));
al.add(new Student(105,"Jai",21));
Collections.sort(al);
for(Student st:al){
System.out.println(st.rollno+" "+st.name+" "+st.age);
}
}
}
Output:
105 Jai 21
101 Vijay 23
106 Ajay 27
Java Comparator Example
//Student.java
class Student{
int rollno;
String name;
int age;
Student(int rollno,String name,int age){
this.rollno=rollno;
this.name=name;
this.age=age;
}
}

//AgeComparator.java
import java.util.*;
class AgeComparator implements Comparator<Student>{
public int compare(Student s1,Student s2){
if(s1.age==s2.age)
return 0;
else if(s1.age>s2.age)
return 1;
else
return -1;
}
}
//NameComparator.java
This class provides comparison logic based on the name. In such case, we are using
the compareTo() method of String class, which internally provides the comparison logic.
import java.util.*;
class NameComparator implements Comparator<Student>{
public int compare(Student s1,Student s2){
return s1.name.compareTo(s2.name);
}
}
TestComparator.java
In this class, we are printing the values of the object by sorting on the basis of name and age.
//Java Program to demonstrate the use of Java Comparator
import java.util.*;
import java.io.*;
class TestComparator{
public static void main(String args[]){
//Creating a list of students
ArrayList<Student> al=new ArrayList<Student>();
al.add(new Student(101,"Vijay",23));
al.add(new Student(106,"Ajay",27));
al.add(new Student(105,"Jai",21));
System.out.println("Sorting by Name");
//Using NameComparator to sort the elements
Collections.sort(al,new NameComparator());
//Traversing the elements of list
for(Student st: al){
System.out.println(st.rollno+" "+st.name+" "+st.age);
}
System.out.println("Sorting by Age");
//Using AgeComparator to sort the elements
Collections.sort(al,new AgeComparator());
//Travering the list again
for(Student st: al){
System.out.println(st.rollno+" "+st.name+" "+st.age);
}
}
}
Output:
Sorting by Name
106 Ajay 27
105 Jai 21
101 Vijay 23
Sorting by Age
105 Jai 21
101 Vijay 23
106 Ajay 27
Java Lambda Expressions
Lambda expression is a new and important feature of Java which was included in Java
SE 8. It provides a clear and concise way to represent one method interface using an
expression. It is very useful in collection library. It helps to iterate, filter and extract data
from collection. The Lambda expression is used to provide the implementation of an interface
which has functional interface. It saves a lot of code. In case of lambda expression, we don't
need to define the method again for providing the implementation. Java lambda expression is
treated as a function, so compiler does not create .class file.
A lambda expression is a short block of code which takes in parameters and returns a
value. Lambda expressions are similar to methods, but they do not need a name and they can
be implemented right in the body of a method.
Syntax
The simplest lambda expression contains a single parameter and an expression:
parameter -> expression
To use more than one parameter, wrap them in parentheses:
(parameter1, parameter2) -> expression
Expressions are limited. They have to immediately return a value, and they cannot
contain variables, assignments or statements such as if or for. In order to do more complex
operations, a code block can be used with curly braces. If the lambda expression needs to
return a value, then the code block should have a return statement.
(parameter1, parameter2) -> {code block}
Using Lambda Expressions
Lambda expressions are usually passed as parameters to a function:
Example:
Use a lambda expression in the ArrayList's forEach() method to print every item in the list:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(5);
numbers.add(9);
numbers.add(8);
numbers.add(1);
numbers.forEach( (n) -> { System.out.println(n); } );
}
}
Output:
5
9
8
1
Lambda expressions can be stored in variables if the variable's type is an interface
which has only one method. The lambda expression should have the same number of
parameters and the same return type as that method. Java has many of these kinds of
interfaces built in, such as the Consumer interface (found in the java.util package) used by
lists.
Example:
Use Java's Consumer interface to store a lambda expression in a variable:
import java.util.ArrayList;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(5);
numbers.add(9);
numbers.add(8);
numbers.add(1);
Consumer<Integer> method = (n) -> { System.out.println(n); };
numbers.forEach( method );
}
}
Output:
5
9
8
1
To use a lambda expression in a method, the method should have a parameter with a
single-method interface as its type. Calling the interface's method will run the lambda
expression:
Example
Create a method which takes a lambda expression as a parameter:
interface StringFunction {
String run(String str);
}
public class Main {
public static void main(String[] args) {
StringFunction exclaim = (s) -> s + "!";
StringFunction ask = (s) -> s + "?";
printFormatted("Hello", exclaim);
printFormatted("Hello", ask);
}
public static void printFormatted(String str, StringFunction format) {
String result = format.run(str);
System.out.println(result);
}
}
Output:
Hello!
Hello?
Date & time Object in java 1.8 and its functions
Java Date and Time
Java Dates
Java does not have a built-in Date class, but we can import the java.time package to
work with the date and time API. The package includes many date and time classes. For
example:
Class Description

LocalDate Represents a date (year, month, day (yyyy-MM-dd))

LocalTime Represents a time (hour, minute, second and nanoseconds (HH-mm-ss-ns))

LocalDateTime Represents both a date and a time (yyyy-MM-dd-HH-mm-ss-ns)

DateTimeFormatter Formatter for displaying and parsing date-time objects

Display Current Date


To display the current date, import the java.time.LocalDate class, and use its now()
method:
Example:
import java.time.LocalDate; // import the LocalDate class
public class Main {
public static void main(String[] args) {
LocalDate myObj = LocalDate.now(); // Create a date object
System.out.println(myObj); // Display the current date
}
}
Output:
2024-10-21
Display Current Time
To display the current time (hour, minute, second, and nanoseconds), import the
java.time.LocalTime class, and use its now() method:
Example:
import java.time.LocalTime; // import the LocalTime class
public class Main {
public static void main(String[] args) {
LocalTime myObj = LocalTime.now();
System.out.println(myObj);
}
}
Output:
07:13:21.656973
Display Current Date and Time
To display the current date and time, import the java.time.LocalDateTime class, and
use its now() method:
Example:
import java.time.LocalDateTime; // import the LocalDateTime class

public class Main {


public static void main(String[] args) {
LocalDateTime myObj = LocalDateTime.now();
System.out.println(myObj);
}
}
Output:
2024-10-21T07:14:18.891615
Formatting Date and Time
The "T" in the example above is used to separate the date from the time. We can use the
DateTimeFormatter class with the ofPattern() method in the same package to format or parse
date-time objects. The following example will remove both the "T" and nanoseconds from
the date-time:
import java.time.LocalDateTime; // Import the LocalDateTime class
import java.time.format.DateTimeFormatter; // Import the DateTimeFormatter class
public class Main {
public static void main(String[] args) {
LocalDateTime myDateObj = LocalDateTime.now();
System.out.println("Before formatting: " + myDateObj);
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("dd-MM-yyyy
HH:mm:ss");
String formattedDate = myDateObj.format(myFormatObj);
System.out.println("After formatting: " + formattedDate);
}
}
Output:
Before Formatting: 2024-10-21T10:37:20.915949
After Formatting: 21-10-2024 10:37:20
Stream in Java
Introduced in Java 8, Stream API is used to process collections of objects. A stream in
Java is a sequence of objects that supports various methods that can be pipelined to produce
the desired result.

Use of Stream in Java:


The uses of Stream in Java are mentioned below:
 Stream API is a way to express and process collections of objects.
 Enable us to perform operations like filtering, mapping, reducing, and sorting.
How to Create Java Stream?
Java Stream Creation is one of the most basic steps before considering the
functionalities of the Java Stream. Below is the syntax given for declaring Java Stream.
Streams in Java make data processing more efficient by supporting functional-style
operations.
Syntax:
Stream<T> stream;
Here T is either a class, object, or data type depending upon the declaration.
Java Stream Features
The features of Java stream are mentioned below:
 A stream is not a data structure instead it takes input from the Collections, Arrays or
I/O channels.
 Streams don’t change the original data structure, they only provide the result as per
the pipelined methods.
 Each intermediate operation is lazily executed and returns a stream as a result, hence
various intermediate operations can be pipelined. Terminal operations mark the end of
the stream and return the result.
Different Operations On Streams
There are two types of Operations in Streams:
1. Intermediate Operations
2. Terminal Operations
Intermediate Operations
1. map()
The map method is used to return a stream consisting of the results of applying the given
function to the elements of this stream.
Syntax:
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
2. filter()
The filter method is used to select elements as per the Predicate passed as an argument.
Syntax:
Stream<T> filter(Predicate<? super T> predicate)
3. sorted()
The sorted method is used to sort the stream.
Syntax:
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
4.flatMap()
The flatMap operation in Java Streams is used to flatten a stream of collections into a single
stream of elements.
Syntax:
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
5. distinct ()
Removes duplicate elements. It returns a stream consisting of the distinct elements (according
to Object.equals(Object)).
Syntax:
Stream<T> distinct()
6. peek()
Performs an action on each element without modifying the stream. It returns a stream
consisting of the elements of this stream, additionally performing the provided action on each
element as elements are consumed from the resulting stream.
Syntax:
Stream<T> peek(Consumer<? super T> action)

Benefit of Java Stream


1. No Storage
2. Pipeline of Functions
3. Laziness
4. Can be infinite
5. Can be parallelized
6. Can be created from collections, arrays, Files Lines, Methods in Stream, IntStream
etc.

Terminal Operations
Terminal Operations are the type of Operations that return the result. These
Operations are not processed further just return a final result value.
There are a few Terminal Operations mentioned below:
1. collect()
The collect method is used to return the result of the intermediate operations performed on
the stream.
Syntax:
<R, A> R collect(Collector<? super T, A, R> collector)
2. forEach()
The forEach method is used to iterate through every element of the stream.
Syntax:
void forEach(Consumer<? super T> action)
3. reduce()
Syntax:
The reduce method is used to reduce the elements of a stream to a single value. The reduce
method takes a BinaryOperator as a parameter.
T reduce(T identity, BinaryOperator<T> accumulator)
Optional<T> reduce(BinaryOperator<T> accumulator)
4. count()
Returns the count of elements in the stream.
Syntax:
long count()
5. findFirst()
Returns the first element of the stream, if present.
Syntax:
Optional<T> findFirst()
6. allMatch()
Checks if all elements of the stream match a given predicate.
Syntax:
boolean allMatch(Predicate<? super T> predicate)
7. anyMatch()
Checks if any element of the stream matches a given predicate.
Syntax:
boolean anyMatch(Predicate<? super T> predicate)
Java 8 Features
Java 8 is the most awaited release of Java programming language development
because, in the entire history of Java, it never released that many major features. It consists of
major features of Java. It is a new version of Java and was released by Oracle on 18 March
2014. Java provided support for functional programming, new Java 8 APIs, a new JavaScript
engine, new Java 8 streaming API, functional interfaces, default methods, date-time API
changes, etc.
Major Java 8 Features Introduced
There are a few major Java 8 features mentioned below:
 Lambda Expressions: Concise functional code using ->.
 Functional Interfaces: Single-method interfaces.
 Introduced and Improved APIs:
1. Stream API: Efficient Data Manipulation.
2. Date/Time API: Robust Date and Time Handling.
3. Collection API Improvements: Enhanced Methods for Collections (e.g., removeIf,
replaceAll).
4. Concurrency API Improvements: New classes for parallel processing (e.g.,
CompletableFuture).
 Optional Class: Handle null values safely.
 forEach() Method in Iterable Interface: Executes an action for each element in
a Collection.
 Default Methods: Evolve interfaces without breaking compatibility.
 Static Methods: Allows adding methods with default implementations to
interfaces.
 Method References: Refer to methods easily.
Java 8 Features
 Lambda Expressions
 Functional Interfaces
 Method Reference
 Streams
 Comparable and Comparator
 Optional Class
 Date/Time API
 Miscellaneous
Lambda Expressions
Lambda Expression basically expresses an instance of the functional interface, in
other words, you can say it provides a clear and concise way to represent a method of the
functional interface using an expression. Lambda Expressions are added in Java 8.
Functional Interfaces
An interface that contains only one abstract method is known as a functional interface,
but there is no restriction, you can have n number of default and static methods inside a
functional interface.
Method Reference
Method reference is a shorthand notation of a lambda expression to call a method.
There are four types of method references that are as follows:
 Static Method Reference
 Instance Method Reference of a particular object
 Instance Method Reference of an arbitrary object of a particular type
 Constructor Reference.
Streams
Stream API is introduced in Java 8 and is used to process collections of objects with
the functional style of coding using the lambda expression.
Comparable and Comparator
Comparable and Comparator are interfaces used to order objects. They are
particularly useful in sorting operations and collections that require natural ordering.
Optional Class
Java 8 has introduced a new class Optional in java.util package. It can help in writing
a neat code without using too many null checks. By using Optional, we can specify alternate
values to return or alternate code to run. This makes the code more readable because the facts
which were hidden are now visible to the developer.
Date/Time API
New date-time API is introduced in Java 8 to overcome the following drawbacks of old date-
time API:
Not thread safe: Unlike old java.util.Date which is not thread safe the new date-time API is
immutable and doesn’t have setter methods.
Less operations: In old API there are only few date operations but the new API provides us
with many date operations.
Java 8 under the package java.time introduced a new date-time API, most important classes
among them are:
Local: Simplified date-time API with no complexity of timezone handling.
Zoned: Specialized date-time API to deal with various timezones.
LocalDate/LocalTime and LocalDateTime API: Use it when time zones are NOT required.
Miscellaneous
Java is a versatile and powerful programming language that encompasses a wide
range of features and tools, enabling developers to build robust, high-performance
applications.

You might also like