Unit Iii - Strings, Collections, and Java 8 Features
Unit Iii - Strings, Collections, and 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";
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.
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
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
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.
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.
Class Description
HashMap HashMap is the implementation of Map, but it doesn't maintain any order.
TreeMap TreeMap is the implementation of Map and SortedMap. It maintains ascending order.
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
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);
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.
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.
//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
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.