AJAVAUnit 3
AJAVAUnit 3
Collection: A group of individual objects that represent a single entity is known as a collection. It is the common
word that you used in your daily life. But if we are discussing Java programming language then it will become
Java Collection Framework.
Collection Framework: To represent a group of objects as a single entity in the Java programming language we
need classes and interfaces defined by the Collection Framework. If are from C++ background that you can
compare Collection with Containers and Collection Framework with STL(Standard Template Library).
Collection Interface: Interfaces specify what a class must do and not how. It is the blueprint of the class. It
defines the most common methods that can be used for any collection objects. Or you can say it represents the
individual object as a single entity.
import java.util.*;
However, single classes can also be imported by replacing * with the class name as shown
import java.util.ArrayList;
import java.util.LinkedList;
Collections Frame Work Hierachy
The Iterable interface provides an iterator() method which implements the Iterator interface. The iterator interface
provides 3 functions(hasNext(), next(), remove()) which are used to iterate through the collection and also remove
elements from the collection. The collection interface extends the iterable interface. Therefore, inherently, all the
interfaces and classes implement this interface. The main functionality of this interface is to provide an iterator for the
collections. Therefore, this interface contains only one abstract method which is the iterator.
next(): Returns the next element in the iteration. It throws NoSuchElementException if no more element is
present.
remove(): Removes the next element in the iteration. This method can be called only once per call to next().
Collection has sub-interfaces like Set, List, and Queue which implements the Collection interface which in turn is
inherited from the Iterable interface
Collection Interface Methods
boolean add(Object obj):Adds obj to the invoking collection.
int size( ):Returns the number of elements held in the invoking collection.
Type Parameter Naming Conventions
By convention, type parameter names are single, uppercase letters. This stands in sharp contrast to the
variable naming conventions that you already know about, and with good reason: Without this convention, it would be
difficult to tell the difference between a type variable and an ordinary class or interface name.
T: is meant to be a Type
E: is meant to be an Element (List<E>: a list of Elements)
K: is Key (in a Map<K,V>)
V: is Value (as a return value or mapped value)
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();
Example1
import java.util.*;
public class CollectionsDemo {
public static void main(String[] args){
ArrayList<String> animals_list = new ArrayList<>();
// Add elements
animals_list.add("Dog");
animals_list.add("Cat");
animals_list.add("Horse");
System.out.println("ArrayList: " + animals_list);
System.out.println("Print with Iterator");
Iterator itr=animals_list.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Example2
import java.util.*;
public class CollectionsDemo1 {
public static void main(String[] args){
ArrayList<Integer> list = new ArrayList<Integer>();
//add integer values in this collection
list.add(34);
list.add(12);
list.add(45);
System.out.print("The elements in Collection : ");
System.out.println(list);
}
}
output:
The elements in Collection : [34, 12, 45]
Example3
import java.util.*;
public class CollectionsDemo1 {
public static void main(String[] args){
List<Integer> list = new ArrayList<Integer>();
//add integer values in this collection
list.add(34);
list.add(12);
list.add(45);
System.out.print("The elements in Collection : ");
System.out.println(list);
}
}
Example4
import java.util.*;
public class CollectionsDemo1 {
public static void main(String[] args){
// create an empty array list with an initial
// capacity
Collection<Integer> list1 = new ArrayList<Integer>(5);
}
}
Java Vector
Vector is like the dynamic array which can grow or shrink its size. Unlike array, we can store n-number of elements
in it as there is no size limit. It is a part of Java Collection framework since Java 1.2. It is found in
the java.util package and implements the List interface, so we can use all the methods of List interface here.
Example1
import java.util.*;
public class VectorExample {
public static void main(String args[]) {
//Create a vector
Vector<String> vec = new Vector<String>();
//Adding elements using add() method of List
vec.add("Tiger");
vec.add("Lion");
vec.add("Dog");
vec.add("Elephant");
//Adding elements using addElement() method of Vector
vec.addElement("Rat");
vec.addElement("Cat");
vec.addElement("Deer");
Stack
The stack is a linear data structure that is used to store the collection of objects. It is based on Last-In-First-
Out (LIFO). Java collection framework provides many interfaces and classes to store the collection of objects. One
of them is the Stack class that provides different operations such as push, pop, search, etc.
Method Modifier and Method Description
Type
push(E item) E The method pushes (insert) an element onto the top of the
stack.
pop() E The method removes an element from the top of the stack
and returns the same element as the value of that function.
peek() E The method looks at the top element of the stack without
removing it.
search(Object int The method searches the specified object and returns the
o) position of the object.
Example1
import java.util.Stack;
public class StackEmptyMethodExample
{
public static void main(String[] args)
{
//creating an instance of Stack class
Stack<Integer> stk= new Stack<>();
// checking stack is empty or not
boolean result = stk.empty();
System.out.println("Is the stack empty? " + result);
// pushing elements into stack
stk.push(78);
stk.push(113);
stk.push(90);
stk.push(120);
//prints elements of the stack
System.out.println("Elements in Stack: " + stk);
result = stk.empty();
System.out.println("Is the stack empty? " + result);
}
}
Output:
Example2
import java.util.Stack;
public class StackExample
{
public static void main(String[] args)
{
//creating an instance of Stack class
Stack<Integer> stk= new Stack<>();
// checking stack is empty or not
boolean result = stk.empty();
System.out.println("Is the stack empty? " + result);
// pushing elements into stack
stk.add(100);
stk.add(100);
stk.push(78);
stk.push(113);
stk.push(90);
stk.push(120);
stk.addElement(130);
//prints elements of the stack
System.out.println("Elements in Stack: " + stk);
result = stk.empty();
System.out.println("Is the stack empty? " + result);
}
}
}
}
F:\HariJavaPrograms>javac ListSet.java
F:\HariJavaPrograms>java ListSet
ArrayList Elements
[Zara, Mahnaz, Ayan, Ayan]
LinkedList Elements
[Zara, Mahnaz, Ayan]
The elements in Set
[34, 12, 45]
Generic Programming
With the help of generic programming developers can create programs that can handle many data types. Generics
are used to create classes and methods with parameters that can operate on different data types along. This feature
was introduced in Java 5.It provides Code reusability and improved performance.
Advantages of Java Generics
1. Code Reusability
With the help of generics in Java, we can write code that will work with different types of data.
For example,
public <T> void genericsMethod(T data) {...}
Here, we have created a generics method. This same method can be used to perform operations on integer data,
string data, and so on
2. Compile-time Type Checking
The type parameter of generics provides information about the type of data used in the generics code.
For example,
// using Generics
GenericsClass<Integer> list = new GenericsClass<>();
Here, we know that GenericsClass is working with Integer data only.
Now, if we try to pass data other than Integer to this class, the program will generate an error at compile time.
3. Used with Collections
The collections framework uses the concept of generics in Java.
For example,
class DemoClass {
// creae a generics method
public <T> void genericsMethod(T data) {
System.out.println("Data Passed: " + data);
}
}
class GenMain {
public static void main(String[] args) {
// initialize the class with Integer data
DemoClass demo = new DemoClass();
// generics method working with String
demo.<String>genericsMethod("Hello");
// generics method working with integer
demo.<Integer>genericsMethod(25);
demo.<Character>genericsMethod('B');
}
}
Output
F:\HariJavaPrograms>javac GenMain.java
F:\HariJavaPrograms>java GenMain
Data Passed: Hello
Data Passed: 25
Data Passed: B
Type inference is a feature of Java which provides ability to compiler to look at each method invocation and
corresponding declaration to determine the type of arguments.
Here, we are creating arraylist by mentioning integer type explicitly at both side. The following approach is used
earlier versions of Java.
Bounded Types
In Java, generic types are widely used to create reusable components. They allow developers to define classes,
interfaces, and methods that can operate on a variety of different types without sacrificing type safety. However, in
some cases, it is necessary to restrict the range of types that can be used as generic arguments. This is where
bounded types come into play.
A bounded type parameter is a generic type that is restricted to a specific subset of types. It can be defined using the
extends keyword followed by the upper bound. The upper bound can be a class or an interface, and it indicates that
the generic type must be a subclass of the specified class or implement the specified interface
Syntax:
Examples:
class A {
public void displayClass() {
System.out.println("Inside super class A");
}
}
class B extends A {
public void displayClass() {
System.out.println("Inside sub class B");
}
}
class C extends A {
public void displayClass() {
System.out.println("Inside sub class C");
}
}
public class BoundedTypeExample<T extends A> {
private T t;
public BoundedTypeExample(T t){
this.t = t;
}
public void doRunTest() {
this.t.displayClass();
}
public static void main(String[] args) {
// Creating object of sub class C and
// passing it to Bound as a type parameter.
BoundedTypeExample<C> bec = new BoundedTypeExample<C>(new C());
bec.doRunTest();
// Creating object of sub class B and
// passing it to Bound as a type parameter.
BoundedTypeExample<B> beb = new BoundedTypeExample<B>(new B());
beb.doRunTest();
// similarly passing super class A
BoundedTypeExample<A> bea = new BoundedTypeExample<A>(new A());
bea.doRunTest();
//BoundedTypeExample<String> stringContainer = new BoundedTypeExample<>(); // Compile-time error
}
}
Output
java BoundedTypeExample
Inside sub class C
Inside sub class B
Inside super class A
Note: you can also use Multiple Bounds <T extends superClassName & Interface>
class Bound<T extends A & B>
Wildcard
In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a
parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).
The syntax for declaring a simple type of wildcard arguments with an unknown type,
GenericType<?>
The arguments which are declared like this can hold any type of objects. For example, Collection<?> or ArrayList<?> can hold any type of objects like String,
Integer, Double etc
Example
import java.util.*;
public class WildCard {
public static void printList(Collection<?> list) {
System.out.println(list);
}
public static void main(String[] args) {
Collection<String> c1 = new ArrayList<>();
c1.add("Hari");
c1.add("Mohan");
printList(c1);
Collection<Integer> c2 = new LinkedList<>();
c2.add(10);
c2.add(20);
printList(c2);
Collection<Character> c3 = new ArrayList<>();
c3.add('A');
c3.add('B');
printList(c3);
}
}
Output:
[Hari, Mohan]
[10, 20]
[A, B]
Type Erasure
Type erasure is the process of replacing the generic type parameters in a generic class or method with their bounding types or the
Object type. This process occurs during the compilation of Generics code, resulting in the removal of all type information related to
Generics at runtime. In simple terms, type erasure ensures that the bytecode generated by the compiler is compatible with pre-
existing code that does not use Generics.
Note: The Object class is the parent class of all the classes in Java by default.
For example, consider the following generic class:
A(T o)
{
obj = o;
}
T getob()
{
return obj;
}
}
After compilation, the code is replaced by default Object like the below:
class A
{
// Here, T will be replaced by default i.e. Object
Object obj;
A(Object o)
{
obj=o;
}
Object getob()
{
return obj;
}
}
// ...
}
3 Cannot Create Arrays of Parameterized Types
You cannot create arrays of parameterized types. For example, the following code does not compile:
List<Integer>[] arrayOfLists = new ArrayList<Integer>(4); // compile-time error