I started my career with Java and right now I’m preparing for interviews by revising both Java basics and advanced topics, along with learning Spring Boot. Along with that, I’m also focusing on Data Structures and Algorithms and System Design. I’ve been making notes and writing code examples as I learn, so I can refer back to them anytime.
- List item
_ __ ____ ______ ______ _____
/ | / // __ \/_ __// ____// ___/
/ |/ // / / / / / / __/ \__ \
/ /| // /_/ / / / / /___ ___/ /
/_/ |_/ \____/ /_/ /_____/ /____/
Class is the blueprint or template from which objects are created. It defines the properties (fields/attributes) and behaviors (methods) of an object.
An instance of a class. It contains actual values for the fields and can execute methods defined in the class.
Imagine you want to design a car. Class is like the blueprint for a car. It describes all the components and features of a car (like engine, wheels, speed, color, etc.), but it doesn't represent an actual car until you create an object from that blueprint.
Method is a block of code that performs a any specific task. When we call a method it performs its task and return result (if return type is given only then!). Methods helps in making code reusable and organized.
accessModifier returnType methodName(parameterList) {
// method body
}
Access Modifier: This defines from where methods are accessible. (eg: public, private, protected).
Return Type: This defines what type of method will return (eg, int, String, void).
Method Name: This is defined by us (user-defined).
Parameters: This is optional! But if your method requires any input, then params can be given.
User defined Methods: We define this methods based on our own requirements. Standard Library Methods: These are pre defined methods that are available in java libraries.
Code: MethodsExample.java
Stack is a fixed-size memory which stores data for a short amount of time. It’s used to store method calls, local variables, and reference variables.
-
LIFO (Last In First Out): Stack follows this(LIFO) order. The last thing that goes into the stack will be the first thing to come out(LIFO).
-
Method Execution: Whenever a method is called, a stack frame is created which stores local variables of that method.
-
Automatic Memory Management: As soon as method gets executed stack frame automatically removes from memory so that you don't have clean manually.
-
Fast Access: Stack is very fast because of its ability access sequentially. 1→2→3→4…
public class Main { public static void main(String[] args) { int x = 10; // Local variable stored in stack int y = 20; // Local variable stored in stack int result = sum(x, y); // Method call creates new stack frame } public static int sum(int a, int b) { return a + b; // Local variables 'a' and 'b' are stored in stack } }
If too many method calls are made (deep recursion), it leads to a StackOverflowError
(Stack memory overflow). This happens when stack limit is crossed.
Heap memory is used to store objects and instance variables. Unlike stack memory, heap is dynamic and its size changes as per program needs.
-
Global Access: Objects stored in heap memory are globally accessible until they are no longer referenced.
-
Dynamic Memory Allocation: When you create object with
new
keyword use that object allocates in heap memory. -
Garbage Collection: Java automatically manages heap memory via Garbage Collection. If an object is no longer referenced by any part of the program, Java automatically cleans it up.
-
Slower Access: Heap access is slower in comparison to stack access, because heap memory is scattered and needs more management.
public class Main { public static void main(String[] args) { Person p1 = new Person("Farhan", 25); // Object created in heap Person p2 = new Person("Ahmed", 30); // Object created in heap } class Person { String name; // Instance variable stored in heap; global var int age; // Instance variable stored in heap public Person(String name, int age) { this.name = name; this.age = age; } }
Array is a collection of fixed size elements in which all elements belong to same data type. For example, if you wanna store group of integers you gotta use int[].
- Fixed Size: Once array size has been initialized, it cant be changed.
- Same Data type: Elements in array should belong to same data type.
- Indexing: Index in Array starts with 0. Which means the index value of first element in array is 0 and 2nd element value is 1 and it goes on.
- Random Access: You can access any element of the Array based on its index value.
int[] numbers; // Declaration of an integer array
String[] fruits; // Declaration of a String array
int[] numbers = new int[5]; // Array of 5 integers
int[] numbers = {10, 20, 30, 40, 50}; // Array with direct initialization=
int[] numbers = new int[] {1, 2, 3, 4, 5};
Code: ArraysExamples.java and ArraysExample.java
Code: StringExample.java
Java Collection API is a set of classes and interfaces framework in which you can implement data structures and manipulate data. With this we can use operations like searching, sorting, inserting, deleting) on data storage to efficiently handle.
Through the use of Collection framework you can implement multiple data structures like List, Set, Queue, Map etc., Lets understand collection api in a better way.
So, basically collection is a root interface in which it defines almost all data structures in java. Inside this root interface we have sub interfaces like - List, Set and Queue.
List is a ordered collection and it allows duplicate elements. Lets say, when you wanna store elements in indexed form(maybe like student list), you gotta use Lists. There are few lists like ArrayList, LinkedList, Vector.
Set is a unordered collection and it doesn't allow duplicate elements. Lets say, when you wanna store unique values like email IDs or Product IDs, you use Set. Few sets are Hashset, LinkedHashSet, TreeSet.
Queue is a ordered collection and it manages elements in FIFO(First In, First Out) order. Lets say, when you wanna process tasks sequentially like ticket booking system or request raise as ticket. Queues examples are PriorityQueue, LinkedList(as a queue).
Map interface stores data as key-value pairs where key is unique all the time. You may use Maps when you want to store data as key-value pairs like userid and name. Where id cant be duplicated but name can have duplicates. Types of Maps are HashMap, TreeMap, LinkedHashMap.
ArrayList is a class in Java Collection Framework which implements resizable array. ArrayList is a dynamic array where it uses array internally to store the data but unlike array it is not restricted by size rather it grows its size if array is full. Basically it creates a new array internally larger size than previous full array and then copy elements from previous array to the larger array which has more space.
- Dynamic Size: ArrayList size automatically grow and shrink as per requirements
- Index-Based Access: You can directly access elements of list based on its index.
- Maintain Insertion Order: ArrayLists elements are stored in added order. Basically, the order which was added is the same order for storing elements. Therefore it maintains insertion order.
- Allowing Dups: Duplicate elements are allowed in ArrayList. You can store same element multiple times and it will be stored.
- Null Values: ArrayList allows null values.
- add(element): To add new element to the list.
- get(index): Element returns based on its index.
- remove(index): Removes element based on index or element.
- size(): Returns size of list
- clear(): Clears/Removes entire elements. contains(element): Verifies if given element is available in the list or not.
ArrayList access time is constant (O(1)) because elements in ArryaList are accessed based on index. But insertion and removal operation takes (O(n)) when you add or remove any element from ArrayList because next elements has to be shifted.
Code: ArrayListExample.java
LinkedList is a linear data structure where elements are stored sequentially. Every Node(element) with its data consists reference or pointer of next Node. If its a doubly LinkedList then it has reference or pointer of previous Node. In java, LinkedList can be imported from pkg called java.util.LinkedList. This can implement List and Dequeue interfaces. Therefore, doubly ended operations are handled efficiently.
One more thing about LinkedList is unlike array memory locations are not continuous even though sequentially stored. Thats why!!! they use references of prev and next node.
- Dynamic Size: Size of LinkedList dynamically grows when elements are inserted and deleted.
- Insertion and Deletion: Operations like insertion and deletion in LinkedList are efficient, especially at the beginning and middle, because you dont have the need to shift elements. In arrays, you do need to shift.
- Sequential Access: Elements in LinkedList are traversed sequentially. You gotta start from first Node and travel sequentially to the next Nodes.
- No Index-Based Access: You cannot access elements directly in LinkedList like Array does. You have to do sequential traversal.
- Doubly LinkedList: Basically in Java's Linkedlist is Doubly LinkedList. You have references of Prev and Next Node.
Data: Every Node has data to store. Next: Holds pointer of a Next Node reference. Prev(doubly LinkedList): Holds pointer of a Prev Node reference.
Prev <-> Data <-> Next
- add(element): Add element at the end of the list.
- addFirst(element): Add element at the start of the list.
- addLast(element): Add element at the end of the list. (Alternative for
add(element)
). - removeFirst(): Removes the first element of the list.
- removeLast(): Removes the last element of the list.
- getFirst(): Returns the first element of the list without removing.
- getLast(): Returns the last element of the list without removing.
Insertion and Deletion: Operations like insertion and deletion in LinkedList are efficient, especially at the beginning and middle. Because all you gotta do is update references. Access Time: LinkedList is not efficient for random access. Because you have to sequentially traverse elements. Array have constant time (O(1)) but LinkedList has (O(n)).
Map is a interface and its part of Java collection framework. Map stores data in Key-Value pairs where key is the unique identifier and value is part of that key.
- Key-Value Pairs: Every element is made up of a key and a value. Key is unique and value is associated with it.
- Unique Keys: Duplicate Keys are not allowed but duplicate Values are allowed.
- No Specific Order: In HashMap like implementations elements are not in specific order. But in LinkedHashMap maintains insertion order.
- Null Keys and Values: Depending on implementations Null Keys and Null Values can be allowed (HashMap allows only one Null Key and multiple Null Values.
- HashMap
- LinkedHashMap
- TreeMap
- Hashtable
HashMap is a class and part of Java Collection Framework which implements Map interface. HashMap stores data as key-value pairs where key is unique identifier and corresponding to that key there is a value.
- Key-Value Pairs
- Unique Keys: HashMap doesnt allow duplicate keys. If you enter a new value with a existing key, it overrides the previous value.
- One Null Key and Multiple Null Values.
- No Ordering.
- Fast Performance: Main advantage of HashMap is Fast Access. You can retrieve any value quickly based on its key. It retrieves in constant time (O(1)).
Hashing: When you insert a key-value pair HashMap generates Hashcode of the Key. Based on that Hashcode, value are stored in a bucket(memory location). Collision Handling: If hashcode of two different keys are same(btw, its rare) then collision happens!!! HashMap uses a balanced tree (red-black tree, introduced in Java 8) to store multiple entries in a single bucket. Load Factor: HashMap load factor default value is 8 (Java 8) When HashMap crosses the threshold, internally it rehashes its buckets and doubles the size so that there should not be any performance degrade.