0% found this document useful (0 votes)
2 views

AJAVAUnit 3

The document provides an overview of the Java Collection Framework, detailing its structure, advantages, and various interfaces such as Collection, List, and Set. It explains the importance of generics in Java for code reusability and type safety, along with examples of implementing collections and generics. Additionally, it covers concepts like bounded types and wildcards to enhance understanding of generic programming in Java.

Uploaded by

solankiaryamann2
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

AJAVAUnit 3

The document provides an overview of the Java Collection Framework, detailing its structure, advantages, and various interfaces such as Collection, List, and Set. It explains the importance of generics in Java for code reusability and type safety, along with examples of implementing collections and generics. Additionally, it covers concepts like bounded types and wildcards to enhance understanding of generic programming in Java.

Uploaded by

solankiaryamann2
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Unit III

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.

Following are the advantages of the collection framework.


1 Consistent API: The API has a basic set of interfaces like Collection, Set, List, or Map, all the classes
(ArrayList, LinkedList, Vector, etc) that implement these interfaces have some common set of methods.
2 Reduces programming effort: A programmer doesn’t have to worry about the design of the Collection but
rather he can focus on its best use in his program. Therefore, the basic concept of Object-oriented programming
(i.e.) abstraction has been successfully implemented.
3 Increases program speed and quality: Increases performance by providing high-performance
implementations of useful data structures and algorithms because in this case, the programmer need not think of
the best implementation of a specific data structure. He can simply use the best implementation to drastically boost
the performance of his algorithm/program.

Note: All these collections can be imported using:

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.

hasNext(): Returns true if the iteration has more elements.

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.

boolean addAll(Collection c):Adds all the elements of c to the invoking collection.

void clear( ):Removes all elements from the invoking collection

boolean contains(Object obj):Returns true if obj is an element of the invoking collection.

boolean isEmpty( ):Returns true if the invoking collection is empty.

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);

// use add() method to add elements in the list


list1.add(15);
list1.add(20);
list1.add(25);

// prints all the elements available in list


for (Integer number : list1) {
System.out.println("Number = " + number);
}

// Creating an empty ArrayList


Collection<Integer> list2 = new ArrayList<Integer>();

// Appending the collection to the list


list2.addAll(list1);

// displaying the modified ArrayList


System.out.println("The new ArrayList is: " + list2);

}
}
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");

System.out.println("Elements are: "+vec);


}
}

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

empty() boolean The method checks the stack is empty or not.

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:

Is the stack empty? true


Elements in Stack: [78, 113, 90, 120]
Is the stack empty? false

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);
}
}

Difference between List and Set


The list implementation allows us to add the same or duplicate elements. The set implementation doesn't allow us to
add the same or duplicate elements.
Example Combined
import java.util.*;
public class ListSet {
public static void main(String[] args){
// ArrayList
List <String>a1 = new ArrayList<String>();
a1.add("Zara");
a1.add("Mahnaz");
a1.add("Ayan");
a1.add("Ayan");
System.out.println(" ArrayList Elements");
System.out.print("\t" + a1);
// LinkedList
List <String>l1 = new LinkedList<String>();
l1.add("Zara");
l1.add("Mahnaz");
l1.add("Ayan");
System.out.println();
System.out.println(" LinkedList Elements");
System.out.print("\t" + l1);
//Set
Set<Integer> set = new HashSet< Integer >();
//add integer values in this collection
set.add(34);
set.add(12);
set.add(45);
set.add(45);
System.out.print("\nThe elements in Set ");
System.out.println("\n"+set);

}
}

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,

// creating a string type ArrayList


ArrayList<String> list1 = new ArrayList<>();

// creating a integer type ArrayList


ArrayList<Integer> list2 = new ArrayList<>();
In the above example, we have used the same ArrayList class to work with different types of data.
Creating Generics Method

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

Creating Generics Class


// create a generics class
class GenClass<T>
{
private T data;
public GenClass(T dt) {
data = dt;
}

// method that return T type variable


public T getData() {
return data;
}
}
class MainGenClass {
public static void main(String[] args)
{
GenClass<Integer> intObj = new GenClass<>(15);
System.out.println("Generic Class returns: " + intObj.getData());
GenClass<String> stringObj = new GenClass<>("hello hari");
System.out.println("Generic Class returns: " + stringObj.getData());
}
}
F:\HariJavaPrograms>java MainGenClass
Generic Class returns: 15
Generic Class returns: hello hari
Java Type Inference

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.

Java provides improved version of type inference in Java 8

Here, we are creating arraylist by mentioning integer type explicitly at both side. The following approach is used
earlier versions of Java.

List<Integer> list = new ArrayList<Integer>();


In the following declaration, we are mentioning type of arraylist at one side. This approach was introduce in Java 7.
Here, you can left second side as blank diamond and compiler will infer type of it by type of reference variable.
List<Integer> list2 = new ArrayList<>();

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:

The syntax for defining a bounded type parameter is as follows:

class MyClass<T extends MyClassType> {


// ...
}
In the above example, T is the type parameter, and MyClassType is the upper bound. It means that any type T used
as a parameter must either be MyClassType or its subclass.

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:

// Here, T is bounded by Object i.e. java.lang.Object


class A<T> {
// Here, T will be replaced by default i.e. Object
T obj;

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;
}
}

// Here, T is bounded by Object i.e. java.lang.Object


class A<T extends String> {
// Here, T will be replaced by String i.e. java.lang.String
T str;
A(T o)
{
str = o;
}
T getob()
{
return str;
}
}
After compilation, the code is replaced by String like the below:
class A
{
//Here, T will be replaced by String i.e. java.lang.String
String str;
A(String o)
{
str=o;
}
String getob()
{
return str;
}
}
Restrictions on Generics
In Java, Generics are the parameterized types that allow us to create classes, interfaces, and methods in which the type of d ata they are dealing
with will be specified as a parameter. This ensures the type safety at the compilation time.
1 You cannot create an instance of a type parameter. For example, the following code causes a compile-time error:

public static <E> void append(List<E> list) {


E elem = new E(); // compile-time error
list.add(elem);
}
2 Cannot Declare Static Fields Whose Types are Type Parameters
A class's static field is a class-level variable shared by all non-static objects of the class. Hence, static fields of type parameters are not allowed.
Consider the following class:
public class GenType<T> {
private static T os;

// ...
}
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

4 Cannot Create, Catch, or Throw Objects of Parameterized Types


A generic class cannot extend the Throwable class directly or indirectly. For example, the following classes will not compile:
// Extends Throwable indirectly
class MathException<T> extends Exception { /* ... */ } // compile-time error
It will generate following compile time error
error: a generic class may not extend java.lang.Throwable

// Extends Throwable directly


class QueueFullException<T> extends Throwable { /* ... */ // compile-time error
error: a generic class may not extend java.lang.Throwable

You might also like