Top 10 Most Asked Complex Java Problems in FAANG Interviews

When it comes to preparing for interviews at FAANG companies (Facebook, Amazon, Apple, Netflix, Google), candidates need to be well-versed in a wide range of technical concepts, particularly those related to Java development and architecture. These companies often pose complex problems to evaluate the problem-solving ability, coding skills, and design acumen of their candidates. Here’s a list of the top 10 most commonly asked complex Java problems that Java Developers or Architects are likely to encounter during FAANG interviews.


1. Design a URL Shortener (e.g., Bit.ly)

One of the most common system design problems, a URL shortener is a task where the interviewee is required to design a service that converts long URLs into shorter versions while ensuring no collisions (i.e., two long URLs mapping to the same short URL).

Key concepts to cover:

  • Data structures (hashmap, database schema)
  • Collision resolution strategies (hash function)
  • Scalability and performance considerations
  • Database design for storing mappings between long and short URLs
  • Cache management for high-performance retrieval

2. Design a Distributed File System

In this system design challenge, candidates are asked to design a distributed file system that allows multiple machines to store and retrieve files efficiently. This problem tests the candidate’s ability to design scalable, fault-tolerant systems.

Key concepts to cover:

  • Sharding and partitioning of data
  • Data consistency and availability (CAP theorem)
  • Distributed file storage mechanisms (HDFS, Google File System)
  • Fault tolerance and replication
  • Metadata management and index structures

3. LRU Cache Implementation

Implementing a Least Recently Used (LRU) cache is a common interview problem. The goal is to design a cache that evicts the least recently used item when it reaches its limit.

Key concepts to cover:

  • Data structures (HashMap and Doubly Linked List)
  • Time complexity optimization (O(1) for both get and put operations)
  • Cache eviction strategies

4. Design a Parking Lot System

In this system design problem, candidates are asked to design a parking lot system that can manage multiple types of vehicles (e.g., compact, large, motorcycle) and allow for efficient space allocation and retrieval.

Key concepts to cover:

  • Object-oriented design and class hierarchy (Vehicle, ParkingSpot, etc.)
  • Polymorphism and abstraction in managing different vehicle types
  • Allocation and deallocation of parking spots
  • Data structures for efficient lookup (HashMap for parking spots)

5. Implement a Multi-threaded Producer-Consumer Problem

The producer-consumer problem is a classic concurrency challenge, where the goal is to ensure that multiple producers and consumers can access a shared resource safely without causing race conditions or deadlocks.

Key concepts to cover:

  • Thread synchronization using synchronized blocks or Lock classes
  • Condition variables and wait-notify mechanism
  • Deadlock prevention
  • Thread safety and atomic operations

6. Find the Longest Substring Without Repeating Characters

This problem is typically posed as a coding challenge and tests the candidate’s ability to work with strings and sliding window techniques. The task is to find the length of the longest substring without repeating characters.

Key concepts to cover:

  • Sliding window algorithm
  • HashMap for character frequency counting
  • Time complexity optimization (O(n))

7. Design a Real-time Chat System

This problem requires candidates to design a scalable chat system capable of handling multiple users, messages, and online/offline status updates in real time. The system must also ensure message persistence.

Key concepts to cover:

  • Pub/Sub pattern for real-time communication
  • Database design for storing messages
  • Message queues for handling asynchronous communication
  • User authentication and session management
  • Handling large volumes of data and scaling

8. Merge Intervals

In this problem, you are given a collection of intervals, and the goal is to merge any overlapping intervals. This problem often tests the candidate’s knowledge of sorting and interval management.

Key concepts to cover:

  • Sorting intervals based on start times
  • Merging intervals by comparing the current interval with the previous one
  • Time complexity optimization (O(n log n))

9. Find the kth Largest Element in an Unsorted Array

This is a typical coding problem that tests knowledge of sorting algorithms and efficient searching. The challenge is to find the kth largest element in an unsorted array without sorting the entire array.

Key concepts to cover:

  • Quickselect algorithm (O(n) average time complexity)
  • Heap data structures (min-heap for kth largest)
  • Time complexity analysis

10. Design a Notification System

Designing a scalable and efficient notification system is a common problem in FAANG interviews. The system should be able to send notifications to users in real time, support different notification types (email, SMS, in-app), and ensure delivery reliability.

Key concepts to cover:

  • Message queues (e.g., Kafka, RabbitMQ) for handling notifications
  • User preferences and notification batching
  • Delivery acknowledgment and retries
  • Scalability and distributed systems

Summary

FAANG companies pose tough technical challenges during interviews, and complex Java problems are an essential part of evaluating candidates. While preparing for these interviews, it’s important not just to focus on solving the problems but also on demonstrating solid design principles, algorithmic efficiency, and a deep understanding of system architecture. Being well-prepared for problems involving concurrency, system design, and advanced data structures will help you stand out during your interview.

By practicing these top 10 complex Java problems, you'll be in a great position to showcase your technical abilities and impress the interviewers with your problem-solving skills.

Stay Tuned for More!

These are just a few examples of the types of complex problems Java Developers and Architects may face during FAANG interviews. The interview process at these companies is designed to challenge candidates in real-world scenarios and assess their ability to think critically and solve complex problems under pressure.

I will be updating this post with more detailed solutions and insights into each of these questions in an upcoming post, so please stay tuned!

Feel free to leave any comments or suggestions, and share your own experiences if you’ve faced any of these problems during an interview!

Singleton Pattern and Its Multi-Threaded Implementation

The Singleton pattern is a well-known design pattern that restricts the instantiation of a class to a single object and provides a global point of access to that object. It ensures that a class has only one instance throughout the execution of an application, and this instance is accessible from anywhere in the program. Singleton is often used for managing shared resources, such as database connections, configuration settings, or logging systems, where creating multiple instances would be inefficient or undesirable.

In this article, we will dive into a detailed overview of the Singleton pattern, explore its implementation in a multi-threaded environment, and walk through a real-time example. This guide will also be useful if you're preparing for a technical interview, as questions related to design patterns like Singleton often come up in coding interviews.

Overview of the Singleton Pattern

The Singleton pattern falls under the creational category of design patterns. It is characterized by the following features:

  1. Single Instance: It ensures that there is only one instance of the class throughout the lifetime of an application.
  2. Global Access: The instance is globally accessible, meaning it can be accessed from anywhere in the program.
  3. Lazy Initialization: The instance is created only when it is needed, i.e., it’s instantiated only when the getInstance() method is called for the first time.
  4. Controlled Access: It provides controlled access to the instance, ensuring that no other part of the program can instantiate the class.

Structure of the Singleton Class

A typical Singleton class has:

  • A private static variable to hold the single instance of the class.
  • A private constructor to prevent external instantiation.
  • A public static method (getInstance()) to provide global access to the instance.

Basic Singleton Implementation in Java

public class Singleton {

    // Step 1: Create a private static variable to hold the single instance
    private static Singleton instance;

    // Step 2: Private constructor to prevent instantiation from outside
    private Singleton() {
        // Initialization code here
    }

    // Step 3: Public static method to return the single instance
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

In the example above:

  • The instance variable is a private static field that holds the single instance of the class.
  • The constructor is private, which ensures that no one can create a new instance from outside the class.
  • The getInstance() method checks if the instance is already created. If not, it initializes it and returns it.

Implementing Singleton in a Multi-threaded Environment

In a multi-threaded environment, several threads might try to create an instance of the Singleton class at the same time, leading to multiple instances being created, which violates the Singleton pattern. To ensure that only one instance is created in a thread-safe manner, we need to modify our implementation.

1. Using synchronized Block:

The simplest way to make the Singleton thread-safe is by using the synchronized keyword. By synchronizing the getInstance() method, we ensure that only one thread can access the method at a time, preventing multiple instances from being created.

public class Singleton {

    private static Singleton instance;

    private Singleton() {
        // Initialization code here
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

While this approach works, it can be inefficient because synchronization introduces overhead, and each time the getInstance() method is called, the thread must acquire a lock.

2. Using Double-Checked Locking:

To minimize synchronization overhead, we can use a technique known as double-checked locking. In this approach, we synchronize only the block of code where the instance is being created and perform a second check to ensure the instance is still null after acquiring the lock.

public class Singleton {

    private static volatile Singleton instance;

    private Singleton() {
        // Initialization code here
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Here’s how it works:

  • The first if checks if the instance is null before entering the synchronized block, which avoids unnecessary synchronization once the instance is initialized.
  • The synchronized block ensures that only one thread can create the instance.
  • The second if check ensures that the instance has not already been created by another thread while the first thread was waiting for the lock.

The volatile keyword ensures that the instance is correctly published to all threads, avoiding issues that could arise with caching.

3. Using Bill Pugh Singleton Design (Initialization-on-demand holder idiom):

A highly efficient and thread-safe way of implementing Singleton is using Bill Pugh's Singleton Design. It takes advantage of the Java classloader mechanism and the fact that static initializers are thread-safe.

public class Singleton {

    private Singleton() {
        // Initialization code here
    }

    private static class SingletonHelper {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHelper.INSTANCE;
    }
}

In this design:

  • The inner static class SingletonHelper contains the instance of the Singleton class.
  • The instance is created only when the getInstance() method is called.
  • The SingletonHelper class is loaded only when it is referenced, ensuring that the instance is created lazily and safely.

This implementation is thread-safe without requiring synchronization and is also highly efficient.

Real-Time Example of Singleton Pattern

A real-world example where the Singleton pattern can be applied is in logging systems. Consider a scenario where multiple components of an application (e.g., user authentication, database interactions, etc.) need to log messages. Instead of creating multiple instances of a logger, a single instance should be used across the entire application to avoid overhead and ensure consistency in logging.

public class Logger {

    private static volatile Logger instance;

    private Logger() {
        // Initialization of resources, like setting up file writers or loggers
    }

    public static Logger getInstance() {
        if (instance == null) {
            synchronized (Logger.class) {
                if (instance == null) {
                    instance = new Logger();
                }
            }
        }
        return instance;
    }

    public void log(String message) {
        // Log the message to a file or console
        System.out.println(message);
    }
}

In a multi-threaded application, different threads might be logging information simultaneously. The Singleton pattern ensures that there is only one instance of the Logger class, so all log entries are routed through this single instance, ensuring thread-safety and proper logging.

Summary

The Singleton pattern is a powerful and simple design pattern that helps ensure a class has only one instance and provides global access to it. In a multi-threaded environment, it’s crucial to make sure the pattern is implemented in a thread-safe manner to avoid creating multiple instances. Using techniques like double-checked locking or the Bill Pugh idiom can help maintain both thread-safety and efficiency.

If you're preparing for an interview, expect to be asked about Singleton in multi-threaded contexts and how you would implement it to ensure that the pattern is applied correctly. You should also be able to explain the trade-offs between different thread-safety mechanisms, such as synchronization and volatile variables.

Thanks for checking out my article! 😊 I’d love to hear your feedback. Was it helpful? Are there any areas I should expand on? Drop a comment below or DM me! Your opinion is important! 👇💬✨. Happy coding! 💻✨

Understanding and Preventing Memory Leaks in Java

As a Java developer, understanding memory management is crucial for creating efficient and high-performance applications. One of the most common challenges in this area is a memory leak. If you're new to Java or software development, the term might sound complex, but it’s something that every developer needs to grasp. Let’s break it down!

📌 What is a Memory Leak?

A memory leak occurs when an application consumes more and more memory over time without releasing it. This happens because objects that are no longer needed (such as those that aren’t referenced anymore) are still held in memory. In Java, this typically happens when the Garbage Collector (GC) cannot reclaim the memory occupied by these objects.

Imagine you have a bucket 🪣 that you keep filling with water 💧 (representing memory). However, the water keeps filling up, but there's no mechanism to empty the bucket. Eventually, the bucket overflows — and that’s when your application crashes due to running out of memory. This is similar to a memory leak in Java, where memory consumption continues to increase, leading to performance degradation or even application crashes.

🔍 Common Causes of Memory Leaks in Java

Memory leaks in Java can be tricky to spot, especially for new developers. Here are a few common scenarios where they might occur:

1. Unintentional Object References 📚

In Java, memory is managed by the Garbage Collector, which automatically frees up memory used by objects that are no longer needed. However, if objects are unintentionally referenced (or kept alive), the Garbage Collector cannot release the memory.

Example:

class MemoryLeakExample {
    private List<String> names = new ArrayList<>();

    public void addName(String name) {
        names.add(name);
    }

    // Let's say the names list is never cleared or removed
}

Here, every time you add a name to the names list, it keeps growing and the list is never cleared. If you don’t manage this properly, over time, the list will keep consuming more memory.

Fix: Always make sure to clear or remove unused objects and release unnecessary references.

names.clear(); // Clears the list to prevent memory leaks

2. Static References

Static variables can lead to memory leaks because they exist for the lifetime of the application. If a static reference points to an object that is no longer needed, the memory allocated to that object won't be freed.

Example:

class StaticLeakExample {
    private static List<String> staticList = new ArrayList<>();

    public static void addName(String name) {
        staticList.add(name);
    }
}

Here, the staticList will hold all names added to it for as long as the application runs, even if the names are no longer needed.

Fix: Avoid using static references unless absolutely necessary, or nullify them when they are no longer needed.

staticList = null; // Nullify the static reference when not needed

3. Listeners and Callbacks 🔄

Another common cause of memory leaks is when event listeners or callbacks are registered but not properly unregistered. For example, if a listener is attached to a GUI component or a background thread and never removed, it may hold onto references that prevent objects from being garbage collected.

Example:

class ButtonClickListener {
    public void registerListener(Button button) {
        button.addActionListener(e -> System.out.println("Button clicked!"));
    }
}

If the ButtonClickListener class is holding onto the Button object, it may never be garbage collected because the listener is still active.

Fix: Always unregister listeners or callbacks when they’re no longer needed, especially in Java Swing or Android development.

button.removeActionListener(listener); // Remove listener when done

4. Thread References 🧵

Threads are often used in Java for performing background tasks. However, if you create threads dynamically and fail to stop or dereference them when they are no longer needed, they can leak memory.

Example:

class ThreadLeakExample {
    public void createThread() {
        Thread t = new Thread(() -> {
            // Do some work here
        });
        t.start();
    }
}

In this example, if the thread t is never terminated or dereferenced, the application will hold onto that thread, potentially leading to a memory leak.

Fix: Always ensure threads are properly managed. Either terminate them when they’re done or use thread pools for better management.

t.interrupt(); // Interrupt and terminate the thread when done

💡 Best Practices to Prevent Memory Leaks

Here are some key tips to keep your Java code free from memory leaks:

  1. Use Weak References: A WeakReference allows an object to be garbage collected even if it is still referenced.

    Example:

    WeakReference<MyClass>weakRef = new WeakReference<>(new MyClass());
  2. Be Mindful of Collections: Always clear collections when they’re no longer needed, and avoid keeping unnecessary references in them.

  3. Avoid Static References: As mentioned earlier, avoid static references unless they’re necessary. They can keep objects alive for the entire application lifecycle.

  4. Use Proper Thread Management: If using multiple threads, ensure they’re properly terminated, and use thread pools where possible.

  5. Profile Your Application: Use tools like VisualVM or Eclipse MAT (Memory Analyzer Tool) to monitor and identify memory leaks in your application.

🚨 Summary

Memory leaks are one of the most common causes of performance degradation and crashes in Java applications. By understanding how they occur and following the best practices above, you can write more efficient and robust Java code. So, make sure to keep an eye on your object references, clear unused collections, and always manage your threads properly. Your app will thank you for it! 💪

Keep Learning!

As you gain more experience with Java, you’ll begin to identify memory leak issues faster. Don't get discouraged — we all start somewhere. Keep coding and optimizing! 🚀

Thanks for checking out my article! 😊 I’d love to hear your feedback. Was it helpful? Are there any areas I should expand on? Drop a comment below or DM me! Your opinion is important! 👇💬✨. Happy coding! 💻✨

Efficient Ways to Count Character Occurrences in a String Using Java

When working with strings in Java, a common problem that arises is counting how many times a particular character appears within a string. This seemingly simple task can be approached in several different ways, depending on the specific requirements of your project, such as performance considerations, readability, or scalability. In this blog post, we will explore several ways to solve this problem and provide the best approach for different scenarios.

1. Using Java Streams (String.chars() and filter)

Since Java 8 introduced the Stream API, we can take advantage of it to perform this task in a concise and efficient manner. The String.chars() method converts the string into an IntStream of character values, and we can then use the filter() method to count the occurrences of a specific character.

Code Example:

public class CountCharacter {
    public static void main(String[] args) {
        String str = "hello world";
        char ch = 'o';
        long count = str.chars()
                        .filter(c -> c == ch)
                        .count();
        System.out.println("Occurrences of '" + ch + "': " + count);
    }
}

Explanation:

  • str.chars() converts the string into an IntStream.
  • filter(c -> c == ch) filters out all characters that don't match the specified character.
  • count() returns the number of occurrences of the character.

Advantages:

  • Performance: The time complexity is O(n), which is optimal for this task.
  • Readability: The code is compact, making it easy to understand and maintain.

Best Use Case:

  • This approach is ideal for cases where you are working with modern Java (Java 8 or later) and need a clean, readable solution with good performance.

2. Using a HashMap to Count All Characters

If you're working on a problem that requires counting all characters in a string, a HashMap is an excellent choice. This method creates a frequency map for each character and then allows you to easily access the count of any character.

Code Example:

import java.util.HashMap;

public class CountCharacter {
    public static void main(String[] args) {
        String str = "hello world";
        char ch = 'o';
        System.out.println("Occurrences of '" + ch + "': " + countOccurrences(str, ch));
    }

    public static int countOccurrences(String str, char ch) {
        HashMap&lt;Character, Integer&gt; charCount = new HashMap&lt;&gt;();
        for (char c : str.toCharArray()) {
            charCount.put(c, charCount.getOrDefault(c, 0) + 1);
        }
        return charCount.getOrDefault(ch, 0);
    }
}

Explanation:

  • The charCount map stores the frequency of each character.
  • The for loop iterates through the string and updates the frequency of each character.
  • Finally, the method returns the count of the specified character.

Advantages:

  • Scalability: If you need to count the occurrences of multiple characters, the HashMap approach is more efficient than repeatedly searching through the string.
  • Performance: The time complexity is O(n), making this method scalable for larger strings.

Best Use Case:

  • This method is perfect for situations where you need to count the frequency of several characters, or when you want to store the frequency of all characters in the string for later use.

3. Using String.indexOf() in a Loop

The String.indexOf() method can be used to search for a character in a string, and by looping over the string, you can count how many times the character appears. While this method is not the most efficient, it can be useful for certain edge cases.

Code Example:

public class CountCharacter {
    public static void main(String[] args) {
        String str = "hello world";
        char ch = 'o';
        int count = 0;
        int index = 0;

        while ((index = str.indexOf(ch, index)) != -1) {
            count++;
            index++; // Move past the last occurrence
        }

        System.out.println("Occurrences of '" + ch + "': " + count);
    }
}

Explanation:

  • indexOf(ch, index) finds the first occurrence of the character starting from the current index.
  • Each time the character is found, the count is incremented, and the index is updated to continue searching from the next character.

Advantages:

  • Simplicity: This approach is very simple and easy to implement.
  • No extra data structures: It doesn't require additional memory for storing frequency counts.

Disadvantages:

  • Performance: The time complexity is O(n²), making this approach inefficient for long strings.
  • Inefficiency: As indexOf scans the string multiple times, it can become quite slow with large inputs.

Best Use Case:

  • This method can be used for small strings or when simplicity is more important than performance.

4. Using a Simple Loop (Classic Approach)

The most straightforward approach involves iterating through the string and manually checking each character. This method is simple, efficient, and easy to understand.

Code Example:

public class CountCharacter {
    public static void main(String[] args) {
        String str = "hello world";
        char ch = 'o';
        int count = 0;

        for (int i = 0; i &lt; str.length(); i++) {
            if (str.charAt(i) == ch) {
                count++;
            }
        }

        System.out.println("Occurrences of '" + ch + "': " + count);
    }
}

Explanation:

  • The for loop iterates through each character of the string.
  • If the character matches the target, the count is incremented.

Advantages:

  • Simplicity: This approach is very easy to implement and understand.
  • Performance: It has a time complexity of O(n), making it quite efficient for most use cases.

Best Use Case:

  • This is the go-to solution for small to medium-sized strings where performance isn't a major concern, and you want a simple, direct approach.

5. Using Apache Commons Lang's StringUtils.countMatches()

If you are already using Apache Commons Lang in your project, you can take advantage of the StringUtils.countMatches() method, which is optimized for counting occurrences of a character or substring.

Code Example:

import org.apache.commons.lang3.StringUtils;

public class CountCharacter {
    public static void main(String[] args) {
        String str = "hello world";
        char ch = 'o';
        System.out.println("Occurrences of '" + ch + "': " + StringUtils.countMatches(str, ch));
    }
}

Explanation:

  • The countMatches() method from Apache Commons Lang counts how many times a substring (or character) appears in a string.

Advantages:

  • Efficiency: The method is highly optimized for performance.
  • Ease of Use: It simplifies the process by abstracting away the implementation details.

Best Use Case:

  • This approach is ideal if you are already using the Apache Commons Lang library and want a quick, reliable solution.

Conclusion: Which Approach to Choose?

  • Best for Simplicity: The simple loop approach works well for most scenarios, providing both clarity and efficiency.
  • Best for Modern Java Projects: If you're using Java 8 or later, the Stream API approach with String.chars() is concise and elegant.
  • Best for Counting Multiple Characters: Use a HashMap if you need to count occurrences of multiple characters.
  • Best for Small Strings: If performance isn't a concern, the indexOf() method works fine but is less efficient for large inputs.
  • Best for Apache Commons Users: If you're already using Apache Commons Lang, the countMatches() method is the easiest and most optimized solution.


Ultimately, the right approach depends on your project requirements, the size of the data you're working with, and whether you prefer simplicity or scalability in your solution.

Binary Pattern Search in Java

 You have a given two string pattern and s(word). The first string pattern contains only the symbols 0 and 1 and the second string s contains only lowercase english letters.

Lets's say that pattern matches a substring s[1..r] or s if the following 3 conditions are met:

  • they have equal length
  • for each 0 in pattern the corresponding letter in the substring is a vowel
  • for each 1 in pattern the corresponding letter is a consonant.
Your task is to calculate the number of substrings of s that match pattern.

Note: in this task we defines the vowels as 'a', 'e', 'i', 'o', 'u' and 'y'. All other letters are constants.

Here is the solutions:

public class Test {
public static void main(String[] args) {
String pattern = "010";
String s = "amazing";
System.out.println("Total no occurrences: " + countMatches(pattern, s));
}

private static int countMatches(String pattern, String s) {
int pLen = pattern.length();
int sLen = s.length();
int matches = 0, fromIndex = 0;
if( pLen != sLen) {
String fs = s.replaceAll("[aeiouy]", "0").replaceAll("[bcdfghjklmnpqrstvwxz]", "1");
while ((fromIndex = fs.indexOf(pattern, fromIndex)) != -1) {
matches++;
fromIndex++;
}
}
return matches;
}
}

Output: Total occurrences: 2

Thanks and Enjoy !!!


Transaction management in JPA/Spring

Propagation is used to define how transactions related to each other. Common options

  • Required: Code will always run in a transaction. Create a new transaction or reuse one if available.
  • Requires_new: Code will always run in a new transaction. Suspend current transactions if one exists.


Isolation Defines the data contract between transactions.

  1. Read Uncommitted: Allows dirty reads
  2. Read Committed: Does not allow dirty reads
  3. Repeatable Read: If a row is read twice in the same transaction, the result will always be the same
  4. Serializable: Performs all transactions in a sequence


An isolation level is about how much a transaction may be impacted by the activities of other concurrent transactions. It supports consistency leaving the data across many tables in a consistent state. It involves locking rows and/or tables in a database.

The problem with multiple transactions
  • Scenario 1. If the T1 transaction reads data from table A1 that was written by another concurrent transaction T2. If on the way T2 is a rollback, the data obtained by T1 is an invalid one. E.g a=2 is original data. If T1 read a=1 that was written by T2.If T2 rollback then a=1 will be a rollback to a=2 in DB. But, Now, T1 has a=1 but in the DB table, it is changed to a=2.
  • Scenario2.If a T1 transaction reads data from table A1.If another concurrent transaction(T2) updates data on table A1. Then the data that T1 has read is different from table A1. Because T2 has updated the data in table A1.E.g if T1 read a=1 and T2 updated a=2.Then a!=b.
  • Scenario 3. If the T1 transaction reads data from table A1 with a certain number of rows. If another concurrent transaction(T2) inserts more rows on table A1. The number of rows read by T1 is different from the rows in table A1


Scenario 1 is called Dirty reads.
Scenario 2 is called Non-repeatable reads.
Scenario 3 is called Phantom reads.

So, the isolation level is the extent to which Scenario 1, Scenario 2, and Scenario 3 can be prevented. You can obtain a complete isolation level by implementing locking. That is preventing concurrent reads and writes to the same data from occurring. But it affects performance. The level of isolation depends upon application to application on how much isolation is required.


  1. ISOLATION_READ_UNCOMMITTED: Allows to read changes that haven’t yet been committed. It suffers from Scenario 1, Scenario 2, Scenario 3
  2. ISOLATION_READ_COMMITTED: Allows reads from concurrent transactions that have been committed. It may suffer from Scenario 2 and Scenario 3. Because other transactions may be updating the data.
  3. ISOLATION_REPEATABLE_READ: Multiple reads of the same field will yield the same results until it is changed by themselves.It may suffer from Scenario 3. Because other transactions maybe inserting the data
  4. ISOLATION_SERIALIZABLE: Scenario 1,Scenario 2,Scenario 3 never happens.It is complete isolation. It involves full locking. It affects performance because of locking.

Stack

What is stack?
--> Stack is the collection of objects accessed from one end.  eg. pile of the plate in the kitchen. It has two primitive operations are: Push for addition and Pop for deletion. All the operation are on the top of the stack.
--> LIFO: last in first out

PUSH Operation & Implementation:-
--> always added on top of the stack. syntax:- push(n)
eg.
-define the size of the stack.
- define the top of stack -1.
-push(n): it will push the element into the stack.

Overflow
-If there is no more space to push element in the stack, the stack is full!!!

POP Operation and Implementation:
-remove an element from the top of the stack. eg n = pop().

Underflow:
-if the stack has no more element and tried to remove the element. the stack is empty!!!

Advanced Multi Threading in Java [ Latch ] - Part 1

CountDown latch is one of the kinds of synchronizer which wait for another thread before performing the tasks or This is used to synchronize one or more tasks by enabling them to wait for the tasks completed by other tasks.  It was introduced in Java 5 along with other CyclicBarrier, Semaphore, CuncurrentHashMap and BlockingQueue. Its somehow like the wait and notify but in the more simpler form and will much less code.

It basically works in the latch principle. Or let us suppose we have a seller who is going to sell 10 (No. of operations) apples. The number of customers may be anything but what the seller is concerned about is the number of apples because when it reaches to 0 he can go home. The seller(Main Thread) will wait for the customers (awaits()). Let's say there are 10 customers(Threads) now who are in the line to buy Apple. When one customer buys that Apple then the number of apple decrease by 1 (countdown()) and another customer will get a chance to buy that apple so on the number of apples goes on decreases and finally become 0. After no apples left in the bucket, the seller can stop selling and go home happily. 

Note:: In CountDown Latch the countdown cannot be reset. 


Image result for CountDownLatch

Let's have a look at Java code::




#HappyCoding #CodingWorkspace

Display The Image On The Page

We're making our request to Unsplash, it's returning a response that we're then converting to JSON, and now we're seeing the actual JSON data. Fantastic! All we need to do now is display the image and caption on the page.

Here's the code that I'm using:


This code will be working following way
  • get the first image that's returned from Unsplash
  • create a <figure> tag with the small image
  • creates a <figcaption> that displays the text that was searched for along with the first name of the person that took the image
  • if no images were returned, it displays an error message to the us

#HappyCoding

jQuery methods used to make asynchronous calls

jQuery has a number of other methods that can be used to make asynchronous calls. These methods are:

Each one of these functions in turn calls jQuery's main .ajax() method. These are called "convenience methods" because they provide a convenient interface and do some default configuration of the request before calling .ajax().

Let's look at the .get() and .post() methods to see how they just call .ajax() under the hood.

Running an asynchronous request in the console. The request is for a resource on SWAPI. The request is displayed in the network pane.

So we can make a request with .ajax(), but we haven't handled the response yet.

#HappyCoding!!!

Zookeeper - Introduction

Image result for apache zookeeper


Introduction

Zookeeper is one of the famous apache's projects which is used to provide synchronized services across the servers i.e. it's a centralized infrastructure. It is very hard to manage and coordinate the different cluster at a time but zookeeper with its advanced API with the simple Architecture solves this issues. With the help of zookeeper, we can focus more on development rather than managing the clusters. 

Zookeeper does this by creating a file in its server known as znode, which resides in the memory of zookeeper. This node can be updated by any nodes in the clusters to update their status. This updated status can be gained by other nodes so that they can change their behaviors to provide the perfect services. 

Topics and partitions in Apache Kafka [Basic Topics]

Image result for apache Kafka

What are topics and partition in Kafka?
Topics are nothing but a particular stream of data. It is just like the table's in the database except without all the constraints. We can have as many topics as we want. Like in the database each topic is identified by its name. 
Similarly, topics are splits into partitions and each partition is ordered. Each message in the partition gets an incrementing id which is called offset.

Example::
Let us suppose we have a topic T which has a partition let P0 be one of them

step 1: Partition0 {initially it is empty}
step 2: Partition0 0 {here when we write a message to this then that message will have offset 0}
step 3: Partition0 0 1 {when we write another message to it then that message will have offset 1}
step 4: Partition0  0 1 2 and so on {just we described earlier in an incremental order}
and so on...

Note:: Offsets increase from 0 to n as we write data

Each partition will have their own offsets 

Partition0: 0 1 2 3 4 5 6 7  {here the partition goes from 0 to 7 }
Partition1: 0 1 2 3 4 5 {here the partiotion goes from 0 to 5}
Partition2: 0 1 2 3 4 5 6 7 8 {here the partition goes from 0 to 8}

so here the combination of these partitions[Partition0, Partition1, partition2] is called a TOPIC.

Things to keep in mind
  1. Offsets in one partition don't mean anything to other partition, Eg: offset 2 in Partition1 will be the same with offset 2 in other partitions.
  2. Orders are guaranteed only within the partitions. 
  3. Data in the partition are limited to the specific time. {default 2 weeks}
  4. Once the data is written in the partition it cannot be unchanged i.e. it is immutable.
  5. We push data to the topic, not the partitions.
  6. Unless we provide the key data is randomly assigned to the partitions.
  7. We can have as many partitions on the topic we want.
Happy Coding...

GO - Basic Variable declaration - Part 3

Image result for golang
Defining variables in the go
we use var to define a variabler in the GO. In GO we put the variable type only at the end of the variable name like:
var variable_name varaiable_type
var muNumber int

we can define multiple variable by this way
var variable1, variable2, variable3 variable_type
var num1, num2 int
here all variable will the of the type vatiable_type

defining the variable with the initial value
var variable_name type = value
eg. var age int = 14

defining multiple variable with intial value
var num1, num2, num3 = 2, 3, 4
// same as num1 = 2, num2 = 3, num3 = 4

lets define three variable without the type and the var keyword with their initial values
vname1, vname2, vname3 := v1, v2, v3
Now it looks much better. Use := to replace var and type, this is called a brief statement.
its simple but it has one limitation: this form can only be used inside of functions. You will get compile errors if you try to use it outside of function bodies. Therefore, we usually use var to define global variables.

blank variable 
"_" is known as blank variable in GO because it's blank :). for eg:
_ , a := 10, 20 
here 20 given to a but 10 is discarded, we will use this on the later examples in real case

NOTE: GO will give compile time error if we didnt use the variable which are already defined.

GO - Introduction - Part 1

Image result for golang

What is "go"?
Go or golang is the new programming language developed by google for their most roboost and to manage the large scale application.

Why go?
It is lightweight and more managable and is awesome for the web services and last but not the least it is easy to learn.

What are its features?

  1. Support for environment adopting patterns similar to dynamic languages. For example type inference (x := 0 is valid declaration of a variable x of type int)
  2. Compilation time is fast.
  3. InBuilt concurrency support: light-weight processes (via goroutines), channels, select statement.
  4. Conciseness, Simplicity, and Safety
  5. Support for Interfaces and Type embedding.


But to make it more simpler following features haves been ommited


  1. Production of statically linked native binaries without external dependencies.
  2. No support for type inheritance
  3. No support for method or operator overloading
  4. No support for circular dependencies among packages
  5. No support for pointer arithmetic
  6. No support for assertions
  7. No support for generic programming

Angular 2 - Part 9 [Template-Driven Form]


In this tutorial we will create a template-driven form which will contain username, email, password and gender fields. which is as shown below:


here is the template-driven.html template file for this form:

<h2>Template Driven</h2>
<form (ngSubmit)="onSubmit(f)" #f="ngForm">
  <div ngModelGroup = "userData">
    <div class="form-group">
      <label for="username">Username: </label>
      <input type="text" class="form-control"
             minlength="4"
             id="username"
             [(ngModel)]="user.username" name="username" required
             >
    </div>
    
    <div class="form-group">
      <label for="email">Email: </label>
      <input type="text" class="form-control"
             pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"
             id="email"
             [(ngModel)]="user.email" name="email" required
            >
    </div>
  </div>
  <div class="form-group">
    <label for="password">Password: </label>
    <input type="password" class="form-control"
           id="password"
           [(ngModel)]="user.password" name="password" required>
  </div>
  <div class="radio" *ngFor="let g of genders">
    <label>
      <input type="radio" [(ngModel)] = "user.gender" name="gender" [value]="g"> 
       {{g}}
    </label>
  </div>
  <button type="submit" class="btn btn-primary" >Submit</button>
</form>

Now let create a component for this form
template-driven.component.ts




import { Component, OnInit } from '@angular/core';
import {NgForm} from "@angular/forms";

@Component({
  selector: 'app-template-driven',
  templateUrl: './template-driven.component.html',
  styleUrls: ['./template-driven.component.css']
})
export class TemplateDrivenComponent{

  user = {
    username:"Yubraj",
    email:"yubraj@gmail.com",
    password:"asdfasdf",
    gender: "male"
  }
  
  genders = ["male", "female"];

  constructor() { }

  onSubmit(form: NgForm){
    console.log(form.value);
  }
}



What we did here is:
1. We created a html template
2. then we bind the html input with the user object which is in the component.
3. [(ngModel)]="user.username" .. is used to bind using two way data binding in the form
4. in the form we use (ngSubmit)="onSubmit()" to submit the form and #f is used to hold the form.
5. once submitting the form we will display the form value in the console.

What we need to implement is:
1. Only allow submission only when all the form data is valid.
2. show errors in the forms.

lets add some more attributes in the input fields i.e. #username, #email in order to represent the given field so we can show errors once it has been changed. Before that let us know that angular will add its own classes in the input field when running it, which are ng-valid if the form is valid and ng-invalid if the form is invalid as well as ng-dirty if the form value is changed and ng-touched if the form input
is touched or selected. which is as shown below:



so we modify the class ng-invalid and ng-valid which is used to highlight the input field if the data is not valid.

template-driven.component.css

.ng-invalid{ border-color: red; }
.ng-valid{  border-color: forestgreen; }

so once the input is invalid the border color will turn to red and on valid it will turn to green.


Adding the error message in the form:
we will add this line of code in the form to show the error in the form for each fields

<div class="alert alert-danger" role="alert" *ngIf="!username.valid">Invalid username</div>

here #username is used to reference the username input field in the form. So once it is invalid this above line will be displayed.  Similarly we can also make the submit button disabled if the form which is referenced by f. by this way:
<button type="submit" class="btn btn-primary" [disabled]="!f.valid">Submit</button>

lets check it out all together:

template-driven.component.html

<h2>Template Driven</h2>
<form (ngSubmit)="onSubmit(f)" #f="ngForm">
  <div ngModelGroup = "userData">
    <div class="form-group">
      <label for="username">Username: </label>
      <input type="text" class="form-control"
             minlength="4"
             id="username"
             [(ngModel)]="user.username" name="username" required
             #username="ngModel">
    </div>
    <div class="alert alert-danger" role="alert" *ngIf="!username.valid">Invalid username</div>
    <div class="form-group">
      <label for="email">Email: </label>
      <input type="text" class="form-control"
             pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"
             id="email"
             [(ngModel)]="user.email" name="email" required
             #email="ngModel">
    </div>
    <div class="alert alert-danger" role="alert" *ngIf="!email.valid">Invalid email address</div>
  </div>
  <div class="form-group">
    <label for="password">Password: </label>
    <input type="password" class="form-control"
           id="password"
           [(ngModel)]="user.password" name="password" required>
  </div>
  <div class="radio" *ngFor="let g of genders">
    <label>
      <input type="radio" [(ngModel)] = "user.gender" name="gender" [value]="g"> {{g}}
    </label>
  </div>
  <button type="submit" class="btn btn-primary" [disabled]="!f.valid">Submit</button>
</form>


So here is the output:


This whole code is available in the github. check it out here 
#happyCoding


Angular 2 - Part 8 [ Forms ]


Forms in Angular has always been so interesting. We can do lots of stuffs in the forms using a little and simple techniques in angular. Forms are very important in the web applications. Forms are used to login, registrations and also for many stuffs. Dynamic web is not possible without the forms. In angular 1.x we have seen how angular helps us in developing much user friendly forms. In angular 1.x all the forms are template driven where as in angular 2 we can also create a data-driven forms too which are much easier and easy to learn as well.
So in the later two tutorial we will discuss on how we can create two types of forms using angular 2 which are: 
  1. Template-Driven: Most of the logic are included in the template 
  2. Data-Driven: Logic are applied via a internal implementations
Check it out the examples of each type of in the upcoming tutorials. 
#happyCoding