Oopjava Unit 2
Oopjava Unit 2
Neelima
Arrays: Arrays are used to store multiple values in a single variable, instead of declaring
separate variables for each value.
Declaration of Arrays
To declare an array, you need to specify the type of elements it will hold, followed by square
brackets []. There are two ways to declare an array in Java:
int[] numbers;
int numbers[];
Both syntaxes are valid, but the first one (int[] numbers;) is more commonly used.
Initialization of Arrays
Once an array is declared, it must be initialized before it can be used. Initialization can be
done in a few different ways.
This method allocates memory for a specific number of elements, but does not assign
values:
In this case, the array numbers has 5 elements, each initialized to the default value for the
data type (0 for integers).
You can also initialize an array with a set of values at the time of declaration:
This creates an array with the specified elements, and the size of the array is automatically
determined by the number of elements provided.
Alternatively, you can initialize an array using the new keyword along with specific values:
Example:1
Output:
33
3
4
5
Example:2
Output:
Enter Array Elements:
33
3
4
5
Array Elements are:
33
3
4
5
arrayRefVar=new datatype[size];
Multidimensional Array
So, if the base address of numbers is 1000, the elements would be stored as follows:
Since array elements are stored contiguously, accessing an element is very efficient. If you
know the base address (starting address) of the array, you can compute the memory
address of any element using the formula:
For example, to access the third element (numbers[2]), the address would be:
Address of numbers[2]=1000+(2×4)=1008
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
In memory, this 2D array is stored in a flattened form, where elements of the first row are
stored first, followed by elements of the second row, and so on:
For higher-dimensional arrays (e.g., 3D arrays), the storage principle is the same. The
elements are laid out in memory in a row-major order (or column-major, depending on the
language), but the calculations for the memory address become more complex.
For a 3D array arr[x][y][z], the address of an element at position (i, j, k) can be computed
using:
Example:
Output:
First element: 10
Third element: 30
Example:
Example:
public class Main
{
public static void main(String[] args)
{
// Declare and initialize a 2D array
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Example:
Output:
Modified element at matrix[1][2]:10
Consider an example of a 2-D array with 2 rows, here each row can have a different number
of columns, i.e, elements. They don't need to be equal in length.
It is important to understand that 2-D arrays have the same number of columns in each
row. Whereas in jagged arrays, the rows have different numbers of columns.
Syntax
In order to declare a jagged array, we need to write its name preceded by its data type. The
new keyword is used to create the object. Then we specify the number of rows and leave
the column empty.
There are other ways to declare and initialize jagged arrays. Let us take a look at the other
ways.
Example
int arr[][] = new int[][]
{
new int[] { 1, 2, 3, 4 },
new int[] { 4, 5},
new int[] { 6, 7, 8},
};
Another way to declare and initialize a jagged array can be omitting the first new keyword.
int arr[][] ={
new int[] { 1, 2, 3, 4 },
new int[] { 4, 5},
new int[] { 6, 7, 8},
};
Apart from the above methods, we can omit all the new keywords and initialize the value
inside a jagged array.
int arr[][] ={
{ 1, 2, 3, 4 },
{ 4, 5},
{ 6, 7, 8},
};
int[][] Jagged_arr = {
{ 99, 18, 1, 77 },
{ 43, 8 },
{ 17,101,2 } };
So, this array has 3 rows, and each row has a variable number of columns. They can be
visualized in the following way.
The jagged array is stored in heap memory and each individual element of this jagged array
is a one-dimensional array. Each 1-D array has a different size. This is what a jagged array
is.
Let us look at an example where we will create a 2-D jagged array. Here the zeroth row has
1 element, the first row has 2 elements, so on such that the nth row has n+1 elements.
We will do this by using a for loop. Hence a new array with the given size will be created.
import [Link].*;
import [Link].*;
public class Main
{
public static void main(String[] args)
{
Scanner scn=new Scanner([Link]);
//We are creating a jagged array where the 0th row has 1 element,
//1st row has 2 elements
//such that nth row has n+1 elements
for (int i = 0; i < [Link]; i++)
arr[i] = new int[i + 1];
// Initializing array
int temp = 0;
for (int i = 0; i < [Link]; i++)
for (int j = 0; j < arr[i].length; j++)
arr[i][j] = temp++;
import [Link].*;
import [Link].*;
public class Main
{
Strings in Java:
In Java, the String class is used to represent sequences of characters. Strings are one of the
most commonly used data types in Java and are essential for handling textual data. Unlike
primitive data types (like int, float, etc.), String is an object that comes with a variety of
methods for manipulating and querying strings.
Characteristics of Strings
• Immutable: Strings in Java are immutable, which means once a String object is created,
it cannot be changed. Any operation that modifies a string results in the creation of a
new String object.
• String Pool: Java optimizes memory usage for strings by maintaining a pool of string
literals. When a string is created using a literal, the JVM checks the string pool first. If
the string already exists, it returns the reference; otherwise, it creates a new string in
the pool.
Creating Strings
This explicitly creates a new String object, even if the same string exists in the string
pool.
Java's String class provides a wide range of methods for manipulating strings. Here are
some of the most commonly used methods:
length()
Returns the length of the string (i.e., the number of characters).
int len = [Link](); // len is 13
charAt(int index)
Returns the character at the specified index (0-based index).
substring(int beginIndex)
Returns a substring starting from the specified index to the end of the string.
equals(Object another)
Compares two strings for content equality (case-sensitive).
equalsIgnoreCase(String another)
Compares two strings, ignoring case differences.
compareTo(String another)
Compares two strings lexicographically.
• Returns 0 if the strings are equal.
• Returns a negative number if the current string is lexicographically less than the
other string.
• Returns a positive number if the current string is greater.
toUpperCase()
Converts all characters in the string to uppercase.
toLowerCase()
Converts all characters in the string to lowercase.
split(String regex)
Splits the string based on the specified regular expression and returns an array of
substrings.
concat(String str)
Concatenates the specified string to the end of the current string.
String newStr = [Link](“ How are you?”); // newStr is “Hello, World! How are you?”
The String Constant Pool (also known as the String Intern Pool) is a special memory region
in Java where String literals are stored. This optimization feature helps save memory and
improve performance when handling strings.
1. String Literals:
• When you create a string using a literal, like "Hello", Java checks the String
Constant Pool to see if an identical string already exists.
• If it does, Java returns a reference to the existing string in the pool instead of
creating a new object.
• If the string does not exist in the pool, Java adds it to the pool and then returns a
reference to it.
String str1 = "Hello"; // This creates a string literal "Hello" and stores it in the pool.
String str2 = "Hello"; // This does not create a new string; str2 points to the same
"Hello" in the pool.
In the example above, both str1 and str2 refer to the same object in the String Constant
Pool. Thus, str1 == str2 would return true.
String str3 = new String("Hello"); // Creates a new String object in the heap.
In this case, str3 does not refer to the string in the String Constant Pool but rather a separate
String object in the heap. Therefore, str3 == str1 would return false, but [Link](str1)
would return true.
3. Interning Strings:
• The intern() method can be used on a string object to add it to the String Constant
Pool or get its reference if it already exists in the pool.
String str4 = new String("Hello").intern(); // Forces str4 to refer to the "Hello" in the
pool.
After calling intern(), str4 now refers to the pooled string, so str4 == str1 would return true.
1. Memory Efficiency:
• By reusing immutable string objects, the String Constant Pool reduces the
number of strings in memory, thus saving space.
2. Performance Improvement:
• Since strings are frequently used in Java applications, having a shared pool can
reduce the overhead of creating and garbage collecting string objects.
Example:
Important Points:
Java StringBuffer class is used to create mutable (modifiable) String objects. The
StringBuffer class in Java is the same as String class except it is mutable i.e. it can be
changed.
Note: Java StringBuffer class is thread-safe i.e. multiple threads cannot access it
simultaneously. So it is safe and will result in an order.
Constructor Description
StringBuffer() It creates an empty String buffer with the initial
capacity of 16.
StringBuffer(String str) It creates a String buffer with the specified string..
StringBuffer(int capacity) It creates an empty String buffer with the specified
capacity as length.
A String that can be modified or changed is known as mutable String. StringBuffer and
StringBuilder classes are used for creating mutable strings.
The append() method concatenates the given argument with this String.
class StringBufferExample
{
public static void main(String args[])
{
StringBuffer sb=new StringBuffer("Hello ");
[Link]("Java");//now original string is changed
[Link](sb);//prints Hello Java
}
}
Output:
Hello Java
The insert() method inserts the given String with this string at the given position.
class StringBufferExample2
{
public static void main(String args[])
{
StringBuffer sb=new StringBuffer("Hello ");
[Link](1,"Java");//now original string is changed
[Link](sb);//prints HJavaello
}
}
Output:
HJavaello
The replace() method replaces the given String from the specified beginIndex and
endIndex.
class StringBufferExample3
{
public static void main(String args[])
{
StringBuffer sb=new StringBuffer("Hello");
[Link](1,3,"Java");
[Link](sb);//prints HJavalo
}
}
Output:
HJavalo
The delete() method of the StringBuffer class deletes the String from the specified
beginIndex to endIndex-1.
class StringBufferExample4
{
public static void main(String args[])
{
StringBuffer sb=new StringBuffer("Hello");
[Link](1,3);
[Link](sb);//prints Hlo
}
}
Output:
Hlo
The reverse() method of the StringBuilder class reverses the current String.
class StringBufferExample5
{
public static void main(String args[])
{
StringBuffer sb=new StringBuffer("Hello");
[Link]();
[Link](sb);//prints olleH
}
}
Output:
olleH
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 character increases from its current
capacity, it increases the capacity by (oldcapacity*2)+2. For example if your current
capacity is 16, it will be (16*2)+2=34.
class StringBufferExample6
{
public static void main(String args[])
{
StringBuffer sb=new StringBuffer();
[Link]([Link]());//default 16
[Link]("Hello");
[Link]([Link]());//now 16
[Link]("java is my favourite language");
[Link]([Link]());//now (16*2)+2=34 i.e (oldcapacity*2)+2
}
}
Output:
16
16
34
The ensureCapacity() method of the StringBuffer class ensures that the given capacity is the
minimum to the current capacity. If it is greater than the current capacity, it increases the
capacity by (oldcapacity*2)+2. For example if your current capacity is 16, it will be
(16*2)+2=34.
class StringBufferExample7
{
public static void main(String args[])
{
StringBuffer sb=new StringBuffer();
[Link]([Link]());//default 16
[Link]("Hello");
[Link]([Link]());//now 16
[Link]("java is my favourite language");
[Link]([Link]());//now (16*2)+2=34 i.e (oldcapacity*2)+2
[Link](10);//now no change
[Link]([Link]());//now 34
[Link](50);//now (34*2)+2
[Link]([Link]());//now 70
}
}
Output:
16
16
34
34
70
Wrapper classes
In Java, wrapper classes provide a way to use primitive data types (like int, char, boolean,
etc.) as objects. Each primitive type has a corresponding wrapper class:
Example Usage:
Type Conversion
Type conversion in Java refers to the process of converting a value from one data type to
another. Java supports two main types of conversions: implicit (automatic) type conversion
and explicit (manual) type conversion, also known as casting.
Example:
In this example, an int value 100 is implicitly converted to a double because double is
a larger data type than int.
Example:
}
}
In this example, a double value 100.99 is explicitly converted to an int. This conversion
truncates the decimal part, resulting in a loss of data.
Example:
public class StringToPrimitiveExample
{
public static void main(String[] args)
{
String strInt = "100";
String strDouble = "10.5";
String strBoolean = "true";
Example:
public class PrimitiveToStringExample
{
public static void main(String[] args)
{
int num = 100;
double doubleNum = 10.5;
boolean boolValue = true;
[Link]("String from int: " + strInt); // Output: String from int: 100
[Link]("String from double: " + strDouble); // Output: String from
double: 10.5
[Link]("String from boolean: " + strBoolean);// Output: String from
boolean: true
}
}
Collections in Java:
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).
Java Collections can achieve all the operations that you perform on a data such as searching,
sorting, insertion, manipulation, and deletion.
Interfaces: The main interfaces that define different types of collections are:
• Map: Not a true collection but a framework part. It maps keys to values, with unique
keys. Example implementations: HashMap, TreeMap, LinkedHashMap.
Algorithms: The framework provides several utility methods for working with collections,
such as sorting, searching, and shuffling. These are available through the Collections class.
Let us see the hierarchy of Collection framework. The [Link] package contains all the
classes and interfaces for the Collection framework.
Iterator interface
Iterator interface provides the facility of iterating the elements in a forward direction only.
Iterable Interface
The Iterable interface is the root interface for all the collection classes. The Collection
interface extends the Iterable interface and therefore all the subclasses of Collection
interface also implement the Iterable interface.
Iterator<T> iterator()
Collection Interface
The Collection interface is the interface which is implemented by all the classes in the
collections 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
collections framework depends.
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.
There are various methods in List interface that can be used to insert, delete, and access the
elements from the list.
One of the class that implement the List interface are ArrayList.
ArrayList
Java ArrayList class uses a dynamic array for storing the elements. It is like an array, but
there is no size limit. We can add or remove elements anytime. So, it is much more flexible
than the traditional array. It is found in the [Link] package. The elements of ArrayList are
organized as an array internally. The default size of an ArrayList is 10.
The ArrayList in Java can have the duplicate elements also. It implements the List interface
so we can use all the methods of the List interface here. The ArrayList maintains the
insertion order internally. The elements stored in the ArrayList class can be randomly
accessed.
We cannot create an array list of the primitive types, such as int, float, char, etc. It is required
to use the required wrapper class in such cases.
Key Points:
• The ArrayList is a child class of AbstractList
• The ArrayList implements interfaces like List, Serializable, Cloneable,
and RandomAccess.
• The ArrayList allows to store duplicate data values.
• The ArrayList allows to access elements randomly using index-based accessing.
• The ArrayList maintains the order of insertion.
import [Link].*;
class TestJavaCollection1
{
public static void main(String args[])
{
Method Description
Example:
import [Link].*;
// 1. add(E element)
[Link]("Apple");
[Link]("Banana");
[Link]("After add(): " + list);
// 2. addAll(Collection c)
ArrayList<String> newItems = new ArrayList<>([Link]("Cherry", "Dates"));
[Link](newItems);
[Link]("After addAll(): " + list);
// 5. get(int index)
[Link]("Element at index 2: " + [Link](2));
// 7. indexOf(E element)
[Link]("Index of 'Banana': " + [Link]("Banana"));
// 8. lastIndexOf(E element)
[Link]("Apple");
[Link]("Last index of 'Apple': " + [Link]("Apple"));
// 10. replaceAll(UnaryOperator e)
[Link](String::toUpperCase);
[Link]("After replaceAll(toUpperCase): " + list);
// 13. removeAll(Collection c)
ArrayList<String> removeItems = new ArrayList<>([Link]("DATES",
"GRAPES"));
[Link](removeItems);
[Link]("After removeAll(): " + list);
// 14. retainAll(Collection c)
ArrayList<String> retainItems = new ArrayList<>([Link]("BANANA",
"BLACKBERRY"));
[Link](retainItems);
[Link]("After retainAll(): " + list);
// 16. clear()
[Link]();
[Link]("After clear(): " + list);
// 17. size()
[Link]("Size of list: " + [Link]());
// 18. isEmpty()
[Link]("Is list empty? " + [Link]());
// 20. sort(Comparator c)
[Link]([Link]());
[Link]("After sort(): " + list);
// 21. clone()
ArrayList<String> clonedList = (ArrayList<String>) [Link]();
[Link]("Cloned list: " + clonedList);
// 22. toArray()
Object[] array = [Link]();
[Link]("Array from list: " + [Link](array));
// 23. spliterator()
[Link]().forEachRemaining([Link]::println);
// 24. trimToSize()
[Link]();
[Link]("After trimToSize(): " + list);
}
}
Output:
After add(): [Apple, Banana]
After addAll(): [Apple, Banana, Cherry, Dates]
After add(int index, E element): [Apple, Blueberry, Banana, Cherry, Dates]
After addAll(int index, Collection c): [Apple, Blueberry, Orange, Grapes, Banana,
Cherry, Dates]
Element at index 2: Orange
SubList (1, 4): [Blueberry, Orange, Grapes]
Index of 'Banana': 4
Last index of 'Apple': 7
After set(1, 'Blackberry'): [Apple, Blackberry, Orange, Grapes, Banana, Cherry, Dates,
Apple]
After replaceAll(toUpperCase): [APPLE, BLACKBERRY, ORANGE, GRAPES, BANANA,
CHERRY, DATES, APPLE]
After remove(2): [APPLE, BLACKBERRY, GRAPES, BANANA, CHERRY, DATES, APPLE]
After remove('APPLE'): [BLACKBERRY, GRAPES, BANANA, CHERRY, DATES, APPLE]
After removeAll(): [BLACKBERRY, BANANA, CHERRY, APPLE]
After retainAll(): [BLACKBERRY, BANANA]
After removeIf(starts with 'B'): []
After clear(): []
After adding the list is: [Apple, Cherry, Banana]
Size of list: 3
Is list empty? false
Does list contain 'Banana'? true
After sort(): [Apple, Banana, Cherry]
Cloned list: [Apple, Banana, Cherry]
Array from list: [Apple, Banana, Cherry]
Apple
Banana
Cherry
After trimToSize(): [Apple, Banana, Cherry]
HashSet
The elements of HashSet are organized using a mechanism called hashing. The HashSet is
used to create hash table for storing set of elements.
The HashSet class is used to create a collection that uses a hash table for storing set of
elements.
• The HashSet is a child class of AbstractSet
• The HashSet implements interfaces like Set, Cloneable, and Serializable.
• The HashSet does not allows to store duplicate data values, but null values are
allowed.
• The HashSet does not maintains the order of insertion.
• The HashSet initial capacity is 16 elements.
• The HashSet is best suitable for search operations.
• HashSet( ) - Creates an empty HashSet with the default initial capacity (16).
• HashSet(Collection c) - Creates a HashSet with given collection of elements.
• HashSet(int initialCapacity) - Creates an empty HashSet with the specified initial
capacity.
• HashSet(int initialCapacity, float loadFactor) - Creates an empty HashSet with the
Example
Example:
import [Link].*;
Output:
After add(): [Apple, Cherry, Banana]
After clear(): []
Cloned HashSet: [Cherry, Apple, Banana]
Does set contain 'Apple'? true
Is the set empty? false
Elements using iterator(): Apple Cherry Banana
After remove('Banana'): [Apple, Cherry]
Size of the set: 2
Spliterator elements:
Apple
Cherry
HashMap
HashMap class implements the Map interface which allows us to store key and value pair,
where keys should be unique. If you try to insert the duplicate key, it will replace the
element of the corresponding key. It is easy to perform operations using the key index like
updation, deletion, etc. HashMap class is found in the [Link] package. It inherits the
AbstractMap class and implements the Map interface.
Constructor Description
HashMap() It is used to construct a default HashMap.
HashMap(Map<? extends K,? extends It is used to initialize the hash map by using the
V> m) elements of the given Map object m.
HashMap(int capacity) It is used to initializes the capacity of the hash
map to the given integer value, capacity.
HashMap(int capacity, float It is used to initialize both the capacity and load
loadFactor) factor of the hash map by using its arguments.
Method Description
void clear() It is used to remove all of the mappings
from this map.
boolean isEmpty() It is used to return true if this map contains
no key-value mappings.
Object clone() It is used to return a shallow copy of this
HashMap instance: the keys and values
themselves are not cloned.
Set entrySet() It is used to return a collection view of the
mappings contained in this map.
Set keySet() It is used to return a set view of the keys
contained in this map.
V put(Object key, Object value) It is used to insert an entry in the map.
void putAll(Map map) It is used to insert the specified map in the
map.
V putIfAbsent(K key, V value) It inserts the specified value with the
specified key in the map only if it is not
already specified.
V remove(Object key) It is used to delete an entry for the specified
key.
boolean remove(Object key, Object value) It removes the specified values with the
associated specified keys from the map.
V compute(K key, BiFunction<? super K,? It is used to compute a mapping for the
super V,? extends V> remappingFunction) specified key and its current mapped value
(or null if there is no current mapping).
V computeIfAbsent(K key, Function<? It is used to compute its value using the
super K,? extends V> mappingFunction) given mapping function, if the specified key
is not already associated with a value (or is
mapped to null), and enters it into this map
unless null.
V computeIfPresent(K key, BiFunction<? It is used to compute a new mapping given
super K,? super V,? extends V> the key and its current mapped value if the
remappingFunction) value for the specified key is present and
non-null.
boolean containsValue(Object value) This method returns true if some value
equal to the value exists within the map,
else return false.
boolean containsKey(Object key) This method returns true if some key equal
to the key exists within the map, else return
false.
boolean equals(Object o) It is used to compare the specified Object
with the Map.
void forEach(BiConsumer<? super K,? It performs the given action for each entry
super V> action) in the map until all entries have been
processed or the action throws an
exception.
V get(Object key) This method returns the object that
contains the value associated with the key.
V getOrDefault(Object key, V defaultValue) It returns the value to which the specified
key is mapped, or defaultValue if the map
contains no mapping for the key.
boolean isEmpty() This method returns true if the map is
empty; returns false if it contains at least
one key.
Example:
import [Link].*;
Output:
Initial HashMap: {1=John, 2=Alice, 3=Bob, 4=Emma}
Student with ID 2: Alice
Has key 3: true
Has value 'Emma': true
HashMap after removal: {2=Alice, 3=Bob, 4=Emma}
Keys in HashMap: [2, 3, 4]
Values in HashMap: [Alice, Bob, Emma]
HashMap after replacing value for key 3: {2=Alice, 3=Charlie, 4=Emma}
Size of the HashMap: 3
HashMap after clearing: {}
************