Java Collections: Exploring the Frontier of Data Structures
In this blog post, I aim to provide an introduction to collections and their usage. However, before delving deeper, it is important to establish a basic understanding of the topic.
- What is meant by Primitive data types and Wrapper classes?
- what is Object class?
- When should we use them?
Java has 8 Primitive data types — byte, short, int, long, float, double, boolean, and char.
- It can also be referred to as Literals.
- varies in its size and the way in which it is stored.
- statically typed means all variables must first be declared before they can be used and All other variables in java are object reference types.
int a;
float f;// primitive data type
- They have default values if they are not initialized. Generally, the default value will be zero, and for a boolean it is false.
- A wrapper class is an object that encapsulates a primitive type.
- Each primitive type has a corresponding wrapper:
byte, short, int, long, float, double, boolean, char — primitive type
Byte, Short, Integer, Long, Float, Double, Boolean, Character — wrapper class
- Each wrapper class has an Object as a superclass.
each wrapper class can implement the methods of the Object Class such as hashCode(), equals(Object obj), clone(), toString(), wait(), and finalize().
- Class Object is the root of the class hierarchy.
- Autoboxing means converting primitive to wrapper type.
- Unboxing means converting the wrapper to primitive.
- Wrapper classes are also immutable ie, Once an object of any of these classes is created, its value cannot be changed.
When to Use Primitive Types
Primitive types are faster — in terms of large amounts of calculations.
When we want the variable to be able to be zero.
When we don’t want the default value to be zero.
If the method must return a value.
When to Use Wrapper Class
When we are using Collections or Generics — it is required
If we want the MIN_SIZE or MAX_SIZE of a type.
When we want the variable to be null.
When we want to default value to be null.
If sometimes the method can return a null value.
What is a collection? why do we need to go for a collection framework?
Are you still using arrays, vectors, and hash tables to group objects?
Well, before JDK 1.2, we did too!
But let’s face it, they don’t share a common interface, making programming a bit of a hassle.
The collection represents a group of objects as a single unit or group of data ( integer, string, or any mixture of data types) and the framework contains a set of classes and interfaces as a whole architecture.
- That’s why we switched to a collection framework, which not only provides a common interface but also reduces programming effort and improves performance.
- Why not give it a try and see how it can simplify your programming tasks? It helps in storing and processing data efficiently.
- java. util — utility package contains all the classes and interfaces that are required by the collection framework.
- It contains an interface named an iterable interface which provides the iterator to iterate through all the collections.
- Iterable acts as a root for the collection framework.
- The interface tells us what to do but not how to do it which means the declaration will be there but there will not be the definition.
- It can’t be instantiated which means we can’t create the object for the interface.
List- Interface
The List interface in Java provides a way to store the ordered collection.
Array List — class
why do we need to go for an array list?
package collection;
import java.util.*;// utility package contains all the classes and interfaces
public class sample_collection {
public static void main(String[] args){
//int a[]= new int[10];// array has fixed size.
/* if we need to increase the size, we have add and
then compile once again.
In the above example, in that array has a fixed size if we need to increase the size, we have to add and then compile once again.
public static void main(String[] args){
ArrayList<Integer> list=new ArrayList<Integer>();/*we haven't defined the size.
so add, delete, insert is easier, which ,eans it is flexible.*/
list.add(10);// add any number of size
public static void main(String[] args){
ArrayList<Integer> list=new ArrayList<Integer>();
//list.add(10);// add any number of size or we can use loop instead
for(int i =0;i<=10;i++)
list.add(i);
System.out.println(list);
}
output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Process finished with exit code
- In this above example, we can also add any number of lists and we can use String or any wrapper class.
In fact, we can add objects to the class and if we haven’t mentioned the wrapper class it will automatically take its type.
- Let’s walk around with some more examples.
list.add(100);
list.add(50);
ArrayList<String> slist=new ArrayList<String>();
slist.add("Hello");
System.out.println(slist);
output:
[Hello]
Process finished with exit code 0
ArrayList alist=new ArrayList();
alist.add(15);
alist.add('C');
alist.add("Collect");
System.out.println(alist);
output:
[15, C, Collect]
Process finished with exit code 0
ArrayList blist=new ArrayList();
blist.add(15);
blist.add(15);// which means redundancy is possible
System.out.println(blist);
output:
[15, 15]
Process finished with exit code 0
Array list is implemented with arrays so it also has an index.
- We can also update the list using a set( index of, value) and remove the element from the list.
we can use clear () to clear the array list
contains() to check the element contains in the list
clone() to clone the object
lastIndexOf to get the last index of the element.
- Methods: There are multiple ways to iterate through the List. The most famous ways are by using the basic for loop in combination with a get() method to get the element at a specific index.
ArrayList<Integer> list=new ArrayList<Integer>();
for(int i =0;i<=10;i++)
list.add(i);
System.out.println(list);
System.out.println(list.get(4));// 4 is the index of
output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
4
Process finished with exit code 0
System.out.println(list.get(4));// updating the list
list.set(4,40);// index,value
System.out.println(list);
output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
4
[0, 1, 2, 3, 40, 5, 6, 7, 8, 9, 10]
Process finished with exit code 0
list.remove(6);//removing the data from list with index of 6
System.out.println(list);
output:
[0, 1, 2, 3, 40, 5, 6, 7, 8, 9, 10]
[0, 1, 2, 3, 40, 5, 7, 8, 9, 10]
Process finished with exit code 0
list.contains(5);
System.out.println(list.contains(5));//object of
output:
true
Process finished with exit code 0
for(int i:list)// for each loop
System.out.println(i);
output:
0
1
2
3
40
5
6
7
8
9
10
Process finished with exit code 0
Iterator i = list.iterator();
System.out.println("with the usage of iterator");
System.out.println(i.next());// prints first object in the list
output:
with the usage of iterator
0
In case further information is required, I utilize the IntelliJ IDE.
- right-click ArrayList → go to →Declaration or Usages.
Array list is considered generic programming.
- It will be stored as continuous memory allocation or in sequence.
- one thing we need to remember is if we know the size, then we should array because it is better in performance in case we are not fixed with the size switch to the array list.
Linked List- class
- It is implemented using a linked list data structure.
- if we want to delete/ add the data in the middle of the array list we have shifted the data But in a linked list we can achieve this by just pointing the address where ever required.
- similarly, in an Array list, we can perform the same action in a linked list.
Linked list methods: addFirst(),addLast(),removeFirst(),removeLast(),getFirst()getLast();
// Declaring the List with initial size n
List<Integer> ll = new LinkedList<Integer>();
ll.add(25);
for (int j = 1; j <= 5; j++)
ll.add(j);
System.out.println(ll);
output:
[25, 1, 2, 3, 4, 5]
Process finished with exit code 0
Queue- Interface
First In First Out — Insertion of elements happens at the end of the list, and the removal of elements occurs at the beginning of the list.
Most used Queue methods
poll()//Retrieves and removes the head of this queue or returns null if this queue is empty.
remove()//Retrieves and removes the head of this queue.
peek()//Retrieves, but does not remove, the head of this queue or returns null if this queue is empty.
package collection;
import java.util.Queue;
import java.util.LinkedList;
public class Q {
public static void main(String[] args){
Queue<Integer> q= new LinkedList<Integer>();
q.add(8);
q.add(6);
q.add(9);
q.add(7);
System.out.println(q);
System.out.println(q.peek());//head
System.out.println(q.poll());//removes head and return the value
System.out.println(q.peek());// next head
}
output:
[8, 6, 9, 7]
8
8
6
Process finished with exit code 0
PriorityQueue<Integer> qu= new PriorityQueue<Integer>();// only for sort
Set- Interface
- It is mainly focused on reducing redundancy which means no duplicate elements because it stores unique elements.
- The set interface allows the users to perform the basic mathematical operation on the set. for example,
Set<Integer> s = newHashSet<Integer>();/* as set is interface
we cant create object for interface so we use class in right side */
- Hash set is actually an object which means data is stored in a unique allocation.
- The objects are inserted based on their hashcode in the hash table.
- for example, let’s take the hash code as key % n — the key is the object and n is the total value to be added.
import java.util.HashSet;
public class set {
public static void main(String[] args) {
HashSet<String> hash=new HashSet<String>();
hash.add("Array");
hash.add("List");
hash.add("Arraylist");
hash.add("LinkedList");
hash.add("Queue");
hash.add("Set");
hash.add("Array");
System.out.println(hash);
}
}
Output:
[Array, Set, Arraylist, List, Queue, LinkedList]
Process finished with exit code 0
//to maintain the order we can go for linkedhashset
LinkedHashSet<String> hash=new LinkedHashSet<String>();
hash.add("Array");
hash.add("List");
hash.add("Arraylist");
hash.add("LinkedList");
hash.add("Queue");
hash.add("Set");
hash.add("Array");
System.out.println(hash);
Output:
[Array, List, Arraylist, LinkedList, Queue, Set]
Process finished with exit code 0
//incase we want to sort we can go for treeset we can use any wrapper class
TreeSet<String> hash=new TreeSet<>();
hash.add("Array");
hash.add("List");
hash.add("Arraylist");
hash.add("LinkedList");
hash.add("Queue");
hash.add("Set");
hash.add("Array");
System.out.println(hash);
output:
[Array, Arraylist, LinkedList, List, Queue, Set]
Process finished with exit code 0
Map- Interface
- It is an object that maps keys to values. It cannot contain duplicate keys. Each key can map to at most one value.
- Similar to the set, the map also has a Hash map, Treemap, and Linkedhashmap.
Hash Map -Points to remember
Hash map stores items in “key/value” pairs.
it works on Hashing mechanism.
- Adding or changing an element to the map, we can use the put() method and to remove an element we use remove();
- There are multiple ways to iterate through an interface. The most famous way is to use a for-each loop and get(Key) or getValueof();
When we retrieve the object, we use the get() method and again pass the key object. This time again key objects generate the same hash code, that’s why HashMap keys are immutable.
- In Java, there are several built-in classes that are immutable, meaning their state cannot be changed once they are created. e.g. String, wrapper class.
- A null key can be used to store a value, and a null value can be associated with a key.
HashMap allows duplicate values, but not duplicate keys.
Two unequal objects in Java can have the same hashcode.
I hope to cover the significant concepts of collections in Java, with potential examples.
References
Happy Learning! Never try to explore!!