Tuesday, December 9, 2025

Overview of Java ArrayList, HashTable, HashMap, Hashet,LinkedList




ArrayList in Java

ArrayList is a collection API used for storing elements using dynamic array. The dynamic array is an array in which the array size is not fixed in advance. Therefore, we can change the size of an array at run time using the ArrayList class. When we store elements into ArrayList, depending on the number of elements, the memory is allotted and re-allotted to accommodate all the elements. Every instance of the ArrayList class is allowed to store a set of elements in the list.
Some of the important points about ArrayList class shown below :
  • ArrayList is not synchronized.
  • ArrayList supports dynamic array which can grow as needed.
  • Size of ArrayList can be dynamically increased or decreased.
  • ArrayLists are created with initial size.
  • In Java, standard arrays are of fixed length. After arrays are created, they cannot grow or shrink means you must know in advance how many elements an array will hold.
  • ArrayList can contain duplicate elements.
  • ArrayList maintains insertion order of the elements.
  • Retrieval is random access because array works at index basis.
ArrayList class extends AbstractList. It also implements the List interface. It is generic class which has declaration as follows :

class ArrayList<E>

Where, E specifies type of objects to be stored in ArrayList. For example :
ArrayList<String> al=new ArrayList<String> ();
ArrayList has following constructors:
  • ArrayList (): It builds an empty array list.
  • ArrayList (Collection c): It builds an array list which is initialized with elements of the collection c.
  • ArrayList (int capacity): It builds array list which has specified initial capacity used to store the elements. It grows automatically when elements are added to the array list.

ArrayList Class Methods:

ArrayList class has following methods:
MethodDescription
void add(int position, element obj)It inserts specified element at the specified position in the ArrayList.
boolean add(element obj)It appends specified element to the end of the ArrayList.
boolean addAll(Collection c)It appends all the elements of the collection to the end of the ArrayList.
element remove(int position)It removes specified element at the specified position in the ArrayList.
boolean remove(object obj)It removes first occurrence of specified element obj from the ArrayList.
void clear()It removes all the elements from the ArrayList.
boolean contains(Object o)It returns true if ArrayList contains the specified element .
object get(int position)It returns the element at the specified position in the ArrayList.
int indexOf(Object o)It returns first occurrence of the specified element in the list or -1 if element not found in the list.
int lastIndexOf(Object o)It returns the last occurrence of the specified element in the list or -1 if the element is not found in the list.
int size()It returns the number of elements in the list.
Example using ArrayList:
Lisitng 1: ArrayListDemo .java-ArrayList Example
  package mrbool.com;
   
  import java.util.ArrayList;
  import java.util.Iterator;
   
  public class ArrayListDemo {
                  public static void main(String[] args) {
   
                                 ArrayList<String> al = new ArrayList<String>();
                                 al.add("apple");
                                 al.add("mango");
                                 al.add("grapes");
                                 al.add("orange");
   
                                 System.out.println("Contents are:" + al);
   
                                 al.remove(2);
   
                                 System.out.println("After removing contents are:" + al);
                                 System.out.println("size of array list:" + al.size());
   
                                 Iterator<String> itr = al.iterator();
   
                                 while (itr.hasNext()) {
                                                 System.out.println(itr.next());
                                 }
                  }
   
  } 
Output:
Listing 2: Output of ArrayListDemo.java
  Contents are: [apple, mango, grapes, orange]
  After removing, contents are: [apple, mango, orange]
  size of array list:3
  apple
  mango
  orange

HashTable

A HashTable is an array of the list. It was part of the java.util and is extended in the Dictionary class. HashTable was re-engineered to implement the Map interface. HashTable is similar to HashMap which can store elements in the form of key-value pairs and it is synchronized. It contains unique elements and neither the keys nor the values can be null.
We can write HashTable as:

class HashTable<K, V>

Where K specifies type of keys, and V specifies type of values.
We can create HashTable as follows:
HashTable<String, Integer> ht=new HashTable<String, Integer> () ;
The HashTable contains the following constructors.
  • HashTable (): It is the default constructor.
  • HashTable (int size): It creates hash table that has initial size specified by size. (The default size is 11.)
  • HashTable (int size, float fillRatio): It creates hash table that has initial size specified by size and fill ratio specified by fillRatio. This ratio must be between 0.0 and 1.0.
  • HashTable (Map m): It creates hash table that is initialized with elements in m.
HashTable has following methods:
MethodDescription
void clear()It resets and removes all the key value pairs from the HashTable.
Object clone()It returns duplicate of invoking object.
boolean contains (object value)It returns true if the value that is equal to the value parameter exists and returns false if value is not found
boolean containsKey (object key)It returns true if the key that is equal to the key parameter exists and returns false if key is not found
boolean containsValue (object value)It returns true if the value that is equal to value parameter exists and returns false if value is not found
Enumeration elementsIt returns enumeration of the values in hash table./td>
V get(Object key)It returns the object associated with key and it returns null if the key is not in hash table.
boolean isEmpty()It returns true if there are no key value pairs in the hash table.
Enumeration keys()It returns enumeration of the keys in hash table.
V put(K key, V value)It inserts key and value in the hash table.
V remove(Object key)It removes key and corresponding value from hash table. It returns null if key is not in the hash table.
int size()It returns number of key value pairs in the hash table.
String to StringIt returns string equivalent of hash table.
Example using Hashtable:
Listing 3: HashTableDemo.java- Example using Hashtable
  package mrbool.com;
   
  import java.util.Enumeration;
  import java.util.Hashtable;
   
  public class HashTableDemo {
                  public static void main(String[] args) {
                                 Hashtable<String, String> ht = new Hashtable<String, String>();
                                 ht.put("player 1", "sachin");
                                 ht.put("player 2", "sehwag");
                                 ht.put("player 3", "dhoni");
   
                                 Enumeration<String> values = ht.keys();
                                 while (values.hasMoreElements()) {
                                                 String str = (String) values.nextElement();
                                                 System.out.println(str + ":" + ht.get(str));
                                 }
   
                  }
  }
Output:
Listing 4: Output of HashTableDemo.java
  player 3:dhoni
  player 2:sehwag
  player 1:sachin

HashMap

HashMap is a collection which stores key-value pairs, where key is a reference and value is the actual data. HashMap extends AbstractMap and implements the Map interface. It uses hash table to store the map. It contains unique elements. We cannot use duplicate data for keys in the HashMap.
HashMap is a generic class that has the following declaration:

class HashMap<K, V>

Here, K specifies the type of keys and V specifies the type of values.
We can create HashMap as follows:
HashMap<String, Integer > hm=new HashMap<String, Integer> () ;
There are four types of constructors in HashMap as shown below :
  • HashMap (): It is a default hash map.
  • HashMap (Map m): It initializes the hash map by using the elements of m.
  • HashMap (int capacity): It initializes the capacity of the hash map to capacity. The default initial capacity of HashMap will be 16 and the load factor will be 0.75.Load factor represents at what level HashMap should be doubled.
  • HashMap (int capacity, float fillRatio): It initializes both capacity and fill ratio by using its arguments.
HashMap has following methods:
MethodDescription
void clear()It resets and removes all the key value pairs from the HashMap.
Object clone()It returns duplicate copy of HashMap instance.
boolean containsKey (object key)It returns true if map contains mapping for the specified key.
boolean containsValue (object value)It returns true if map maps one or more keys to the specified value.
Set enrtySet()It returns true if collection of mappings found this map.< /td>
Object get(Object key)It returns the value if specified key is mapped or null if it contains no mapping for the value.
boolean isEmpty()It returns true if there are no entries in the hash map.
Set keySetIt returns set of keys in map object.
Object put(Object key, Object value)it stores key-value pairs into the hash map.
putAll(map m)Copy all the mappings to another map.
Object remove(object key)it removes the key and corresponding value from the Hashmap.
int size()It returns number of key value pairs in the hash map.
Collection values()It returns collection view of map values.
Example using HashMap:
Listing 5: HashMapDemo.java- Example using HashMap
  package mrbool.com;
   
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
   
  public class HashMapDemo {
                  public static void main(String[] args) {
   
                                 HashMap<Integer, String> hm = new HashMap<Integer, String>();
                                 hm.put(100, "sachin");
                                 hm.put(101, "sehwag");
                                 hm.put(102, "gambir");
   
                                 Set set = hm.entrySet();
                                 Iterator it = set.iterator();
   
                                 while (it.hasNext()) {
                                                 Map.Entry m = (Map.Entry) it.next();
                                                 System.out.println(m.getKey() + ":" + m.getValue());
   
                                 }
   
                  }
  }
Output:
Listing 6: Output of HashMapDemo.java
  102 : gambir
  100 : sachin
  101 : sehwag

HashSet

A HashSet represents a set of elements. It is available with collection package and extends AbstractSet and implements the Set interface. The HashSet class is used to create a collection and store it in a hash table. It does not guarantee the order of elements. It does not allow the duplicate elements to be stored.
We can write HashSet as follows:

class HashSet<T>

Here, T represents the generic type constructor. It represents which types of elements are being stored into the HashSet.
We can create object as follows:
HashSet<String> hs=new HashSet<String> ();
HashSet contains the following constructors:
  • HashSet (): It is default hash set.
  • HashSet (Collection c): It initializes hash set by using elements of c.
  • HashSet (int capacity): It creates HashSet with initial capacity (The default capacity is 16).
  • HashSet (int capacity, float fillRatio): it initializes capacity and fillRatio to grow the capacity after certain elements inserted.
HashSet methods:
MethodDescription
void clear()It removes all the elements from the HashSet.
Object clone()It returns duplicate copy of HashSet instance.
boolean contains (object obj)It returns true if the set contains the specified element.
boolean isEmpty()It returns true if there are no elements in the hash set.
Object remove(object key)It removes the element from the HashSet, if it is present. It returns true if element is removed successfully, otherwise false.
int size()It returns the number of elements present in the HashSet.
Example:
Listing 7: HashsetDemo.java – Example for HashSet
  package mrbool.com;
   
  import java.util.HashSet;
  import java.util.Iterator;
   
  public class HashsetDemo {
                  public static void main(String[] args) {
                                 HashSet<String> hs = new HashSet<String>();
                                 hs.add("cricket");
                                 hs.add("foorball");
                                 hs.add("baseball");
                                 hs.add("cricket");
                                 System.out.println(hs);
   
                                 System.out.println("Elements using iterator:");
                                 Iterator it = hs.iterator();
                                 while (it.hasNext()) {
                                                 System.out.println(it.next());
                                 }
   
                  }
   
  }
Output:
Listing 8: Output for HashsetDemo.java
  [baseball, cricket, foorball]
   
  Elements using iterator:
  baseball
  cricket
  foorball

LinkedList

LinkedList contains group of elements in the nodes. LinkedList extends AbstractSequentialList and implements the ListDeque and Queue interfaces.
Following are some of the features of LinkedList class:
  • LinkedList is very convenient to store the data.
  • It can contain duplicate elements.
  • It maintains insertion order.
  • It is not synchronized.
  • It doesn’t support random access for retrieving values.
  • It can be used as list, stack or queue.
LinkedList has the following declaration:

class LinkedList<E>

We can create LinkedList for storing String type elements as follows:
LinkedList<String> ll=new LinkedList<String> () ;
LinkedList class has the following methods:
MethodDescription
void add(int position, element obj)It inserts specified element at the specified position in the LinkedList.
boolean add(element obj)It adds specified element to the end of the LinkedList.
boolean addAll(Collection c)It appends all the elements of the collection to the end of the LinkedList.
boolean addAll(int index, Collection c)It inserts all the elements of the collection into the LinkedList, starting at the specified position.
element remove(int position)It removes specified element at the specified position in the LinkedList.
boolean remove(object obj)It removes first occurrence of specified element obj from the LinkedList.
void clear()It removes all the elements from the LinkedList.
boolean contains(Object o)It returns true if LinkedList contains specified element .
void addFirst(Object o)It inserts the element at the first position of the linked list.
void addLast(Object o)It appends the specified element to the end of the linked list.
Object get(int index)It returns the element at specified position in the LinkedList.
Object getFirst()It returns the first element in the LinkedList.
Object getLast()It returns the last element in the LinkedList.
int indexOf(Object o)It returns the first occurrence of the specified element in the list or -1 if the element is not found in the list.
int lastIndexOf(Object o)It returns the last occurrence of the specified element in the list or -1 if the element is not found in the list.
int size()It returns the number of elements in the linked list.
ListIterator listiterator(int index)It returns a list iterator of the elements in the list starting at specified position in the list.
Object remove(int index)It removes the element in the list at the specified position.
Object removeFirst()It removes the first element from the linked list.
Object removeLast()It removes the last element from the linked list.
Object set(int index, Object element)It replaces the element at the specified position in the list with the specified element .
Object[] toArray()It coverts linked list into an array of Object class type. All the elements in the list are stored in correct order.
Object[] toArray(Object [] a)It returns all the elements in the list are stored in correct order; The run type of returned array is that of the specified array.
Example for LinkedList:
Listing 9: LinkedListDemo.java
  package mrbool.com;
   
  import java.util.Iterator;
  import java.util.LinkedList;
   
  public class LinkedListDemo {
                  public static void main(String[] args) {
                                 LinkedList<String> ll = new LinkedList<String>();
                                 ll.add("India");
                                 ll.add("America");
                                 ll.add("China");
                                 ll.add("India");
   
                                 Iterator it = ll.iterator();
                                 while (it.hasNext()) {
                                                 System.out.println(it.next());
                                 }
                  }
  }
Output:
Listing 10: Output for LinkedListDemo.java
  India
  America
  China
  India




References  Used :- Java-arraylist-hashtable-hashmap-hashetlinkedlist
                                Collection-framework-key-interfaces

Microservices: Design Patterns

 "Microservices: Design Patterns":


  • Design Patterns for Microservices: Learn about various design patterns that can be leveraged when building and operating microservices, including decomposition, integration, data, and operational patterns.
  • Problem-Solving with Patterns: Understand how each pattern ties to specific problems and how they can help remedy common issues in microservices architecture.
  • Specific Patterns Covered: Gain insights into specific patterns such as the API gateway pattern, sidecar pattern, strangler pattern, and more, which help manage complexity and improve the efficiency of microservices.


"Vernacular of microservices":

  • Service Types: Understanding different types of services is crucial. These include data services, business services, translation services, and edge services.
  • Platform Definition: The platform encompasses all service operations across multiple data centers, including infrastructure, runtime, ancillary services, networking, and storage.
  • Operational and Diagnostic Components: These components are essential parts of the platform and should not be overlooked.







"Microservices and cloud native":

  • Distinct Concepts: Microservices and cloud-native are distinct concepts. Microservices do not inherently make a system cloud-native, and cloud-native does not require microservices.
  • Cloud-Native Architecture: Cloud-native is an architectural style focused on scalability, portability, and operating in the cloud. It includes practices like externalizing configuration and autoscaling.
  • Microservices: Microservices are smaller, scoped units of work that allow for independent scaling of different parts of a system. They are often used in cloud-native systems but are not a requirement.





















"Decomposition of a system":

  • Decomposition Approach: Decomposing a system involves breaking down problems into smaller, manageable services, similar to breaking down software problems into reusable functions.
  • Service Types: Different service types are created to address specific uses across the system, such as domain-based services, business process-based services, and atomic transaction-based services.
  • Common Patterns: The strangler pattern is used to migrate from monolithic systems to microservices, and the sidecar pattern helps offload operational functions to separate components.








"Domain-based microservices":

  • Focus on Data Domains: Domain-based microservices are built around data domains, making services more scalable by focusing on specific data patterns and usage within the system.
  • Design Approach: Start with the domain model, not the database schema. The model should represent the domain to the outside world, and actions should be defined based on how the data is used.
  • Iterative Process: Designing domain-based services involves trial and error with fast iterations. Telemetry data is crucial for making informed decisions during this process.









"Business process-based microservices":

  • Higher Level of Abstraction: Business process-based microservices provide a higher level of abstraction around specific business functionality, helping to encapsulate use cases and scale them effectively.
  • Separation of Concerns: These services typically do not have their own data access, keeping business domains and data domains separate to avoid complexity.
  • Distinct Functional Uses: It's important to define distinct functional uses for each business process service to prevent creating a monolithic structure within your microservices architecture.













"Atomic transaction-based microservices":

  • Need for Atomic Transactions: Atomic transactions are necessary when true atomicity is required across multiple data domains, ensuring ACID-compliant transactions.
  • Complexity and Risks: Implementing atomic transactions adds complexity to the system. It's crucial to ensure that stakeholders understand the risks and constraints involved.
  • Design Considerations: To build atomic services, data domains must share a database. Clear rules and rollback conditions must be defined, and the service must handle complete commits or rollbacks.





"Strangler pattern":

  • Concept: The strangler pattern involves gradually migrating from a monolithic system to microservices by incrementally replacing parts of the monolith with microservices.
  • Implementation: Start by identifying and carving out dependencies from the monolith into new microservice endpoints, then redirect internal clients to these new microservices.
  • Strategy: You can either start at the API layer and move down to the database or begin with the data store and move up to business processes, depending on which part of the system needs the most attention.
  • Outcome: Over time, as more functionality is moved to microservices, the monolith is "strangled" and can eventually be deprecated.











"Sidecar pattern":

  • Purpose: The sidecar pattern offloads processing tasks (like logging, monitoring, and network services) to a separate module, reducing repetitive code across services.
  • Implementation: Deploy the sidecar as a module with each microservice, allowing it to handle specific tasks without modifying the main application code.
  • Benefits: This pattern reduces duplicate code, provides unified and focused behavior, and integrates seamlessly with the natural deployment process, enhancing scalability and flexibility









 "Gateway pattern":

  • Purpose: The gateway pattern provides a buffer between underlying services and client needs, preventing chaos by managing how clients interact with system services.
  • Implementation: It acts as a single ingress point, handling tasks like security, authorization, payload mutation, and aggregation, while ensuring scalability and reliability.
  • Benefits: The gateway can limit access, aggregate data, and provide a consistent API contract, helping to manage client interactions without exposing internal services directly.













 "Process aggregator pattern":

  • Purpose: The process aggregator pattern is used to combine multiple business processes into a single API call, assembling a composite response for the client.
  • Implementation: It encapsulates business logic and consolidates payloads, ensuring that clients do not need to reproduce the same set of rules, adhering to the DRY (Don't Repeat Yourself) principle.
  • Caution: Use this pattern carefully as it can introduce a choke point in your system, potentially causing long-running processes and increased network IO. Consider asynchronous patterns for large data processing operations.










"Edge pattern":

  • Purpose: The edge pattern is a subset of the gateway pattern, designed to handle scalability concerns and client-specific needs by acting as client-specific gateways.
  • Benefits: It provides aggregation, consolidation, and complexity isolation tailored to a specific client, improving scalability and flexibility.
  • Implementation: Focuses on the needs of a single client, allowing for targeted processing, better scalability, and easier maintenance compared to a general gateway.







"Single service database" pattern:

  • Purpose: This pattern is used to ensure that each microservice has its own dedicated database, which helps in scaling both the service and the database independently.
  • Implementation: As load on a service increases, the associated database can be scaled independently to meet the demand, ensuring efficient resource utilization.
  • Benefits: Isolating the data domain and its store allows for independent scaling, reducing the impact on the overall system and potentially enabling regional data isolation for advanced use cases.







 "Shared service database" pattern:

  • Usage: Sometimes necessary due to existing contracts or startup constraints, even though single service databases are generally preferred.
  • Implementation: Treat data domains as separate databases within a single engine using schemas or logical groupings to maintain isolation.
  • Best Practices: Ensure each service has unique credentials and avoid cross-schema access to facilitate future database separation and maintain logical isolation.






"Command Query Responsibility Segregation (CQRS)":

  • Complexity: CQRS separates read and write operations into different models, increasing system complexity but improving data behavior across the system.
  • Use Case: It's particularly useful for task-based user interfaces and event-driven models where eventual consistency is acceptable.
  • Implementation: Requires careful design and significant homework to implement correctly, as improper implementation can lead to maintainability and operational challenges.







"Asynchronous eventing":

  • Purpose: Asynchronous eventing addresses long-running transactions or complex workflows that cannot fit into a single blocking API call.
  • Implementation: It involves triggering an event through a service API, which then cascades asynchronously, allowing behind-the-scenes processing after the client receives an accepted message.
  • Benefits: This pattern is powerful in distributed systems, solving complex problems by enabling non-blocking operations and improving overall system efficiency.







"Log aggregation patterns":

  • Purpose: Log aggregation helps in diagnosing and resolving errors quickly by consolidating log messages from various services into a single stream.
  • Consistency: Ensuring consistent log structure and format across all services is crucial for effective log aggregation and indexing.
  • Taxonomy: A common taxonomy for log messages should be shared across all services to facilitate easier parsing and correlation of logs.








"Metrics aggregation patterns":

  • Importance: Metrics are crucial for diagnosing system issues and can be more useful than logging due to less human interaction and easier instrumentation.
  • Consistency: Using a common taxonomy for metrics, similar to logs, helps in creating clear and descriptive dashboards.
  • Dashboards: High-level dashboards for overall system health and detailed dashboards for individual services are essential for effective monitoring and quick issue resolution.










 "Tracing patterns":

  • Purpose: Tracing helps recreate the call stack in a microservices architecture by injecting a trace identifier into every call, spanning from the edge to the database.
  • Implementation: Use a standards-based approach for tracing to leverage off-the-shelf tools and ensure every log message embeds the trace ID.
  • Benefits: Tracing aids in diagnosing issues by ensuring no call is lost and providing visual call stacks through application performance monitoring (APM) tools.






"External configuration":

  • Operational Importance: Externalized configuration is crucial for operational efficiency, especially during load and movement of services, as it helps in quickly resolving issues.
  • Tooling: Use tools that make external environment variables easy to find and manipulate. Consistent naming of variables is also very helpful.
  • Security: While exposing configuration, ensure that secrets are protected and accessible securely to the on-call team without exposing them to unauthorized access.





 "Service discovery":

  • Purpose: Service discovery helps manage the complexity of finding appropriate services in a dynamic runtime where service locations can vary.
  • Functionality: A central location allows new services to advertise themselves and their capabilities, enabling other services to query and find the needed services.
  • Benefits: This pattern enhances flexibility and scalability, making it easier to manage and locate services as the architecture grows.






"Continuous delivery":

  • Definition: Continuous delivery is the process of constantly delivering new code to production with full automation, moving artifacts through non-production environments to production using automated gates.
  • Strategies: Key strategies include automated integration tests, security testing (both penetration and internal security tests), and user acceptance testing (UAT) to ensure confidence in moving code to production.
  • Importance: CI/CD (Continuous Integration/Continuous Delivery) is crucial for microservices, requiring strong automation patterns to maintain efficiency and reliability.










"Documentation":

  • Critical Role: Documentation is essential in a microservices architecture for effective inter-team communication, especially when multiple teams are involved.
  • Tools: Use tools like OpenAPI for documenting APIs, whether you prefer contract-first or code-first development.
  • Consistency: Ensure each service exposes its documentation at a consistent URL (e.g., /docs) and consider automating the publication of documentation to a central repository.
  • Enhancements: Include examples of API consumption and team contact information in the documentation to improve usability and collaboration.









References  and resources  from :-   Course on  Linkdin Learning and  other  resources 

Some interesting things to explore more

 Here  some  some  things  to  study  more ,     How Google Search works               https://developers.google.com/search/docs/fundamental...