The Programmer's Guide
  • About
  • Algorithm
    • Big O Notation
      • Tree
      • Problems
    • Basic Notes
    • Data Structure Implementation
      • Custom LinkedList
      • Custom Stack
      • Custom Queue
      • Custom Tree
        • Binary Tree Implementation
        • Binary Search Tree Implementation
        • Min Heap Implementation
        • Max Heap Implementation
        • Trie Implementation
      • Custom Graph
        • Adjacency List
        • Adjacency Matrix
        • Edge List
        • Bidirectional Search
    • Mathematical Algorithms
      • Problems - Set 1
      • Problems - Set 2
    • Bit Manipulation
      • Representation
      • Truth Tables
      • Number System
        • Java Program
      • Problems - Set 1
    • Searching
    • Sorting
    • Array Algorithms
    • String Algorithms
    • Tree
      • Tree Traversal Techniques
      • Tree Implementation
      • Applications of Trees
      • Problems - Set 1
    • Graph
      • Graph Traversal Techniques
      • Shortest Path Algorithms
      • Minimum Spanning Tree (MST) Algorithms
    • Dynamic Programming
      • Problems - Set 1
    • Recursion
    • Parallel Programming
    • Miscellaneous
      • Problems - Set 1
  • API
    • API Basics
      • What is an API?
      • Types of API
        • Comparison - TBU
      • Synchronous vs Asynchronous API
    • API Architecture
      • Synchronous & Asynchronous Communication
    • API Specification
  • Cloud Computing
    • Cloud Fundamentals
      • Cloud Terminology
      • Core Terminology
      • Cloud Models
      • Cloud Service Models
      • Benefits, Challenges and Risk of Cloud Computing
      • Cloud Ecosystem
  • Database
    • DBMS
      • Types of DBMS
        • Relational DBMS (RDBMS)
        • NoSQL DBMS
        • Object-Oriented DBMS (OODBMS)
        • Columnar DBMS
        • In-Memory DBMS
        • Distributed DBMS
        • Cloud-Based DBMS
        • Hierarchical DBMS
      • DBMS Architecture
      • DBMS Structure
    • SQL Databases
      • Terminology
      • RDBMS Concepts
        • Entity Relationship Diagram (ERD)
          • ERD Examples
        • Normalization
        • Denormalization
        • ACID & BASE Properties
          • ACID Properties
          • BASE Properties
        • Locking and Unlocking
      • SQL Fundamentals
        • SQL Commands
          • DDL (Data Definition Language)
          • DML (Data Manipulation Language)
          • DCL (Data Control Language)
          • TCL (Transaction Control Language)
          • DQL (Data Query Language)
        • SQL Operators
          • INTERSECT
          • EXCEPT
          • MINUS
          • IN and NOT IN
          • EXISTS and NOT EXISTS
        • SQL Clauses
          • Joins
          • OVER
          • WITH
          • CONNECT BY
          • MODEL
          • FETCH FIRST
          • KEEP
          • OFFSET with FETCH
        • SQL Functions
          • Oracle Specific
        • SQL Data Types
          • Numeric Types
          • Character Types
          • Date & Time Types
          • Large Object Types
        • Others
          • Indexing
      • Vendor Specific Concepts
        • Oracle Specific
          • Data Types
          • Character Set
          • Rownum, Rowid, Urowid
          • Order of Execution of the query
          • Keys
          • Tablespace
          • Partition
      • Best Practice
      • Resources & References
        • O’Reilly SQL Cookbook (2nd Edition)
          • 1. Retrieving Records
          • 2. Sorting Query Results
          • 3. Working with Multiple Tables
          • 4. Inserting, Updating, and Deleting
          • 5. Metadata Queries
          • 6. Working with Strings
          • 7. Working with Numbers
          • 8. Date Arithmetic
          • 9. Date Manipulation
          • 10. Working with Ranges
          • 11. Advanced Searching
          • 12. Reporting and Reshaping
          • 13. Hierarchical Queries
          • 14. Odds 'n' Ends
    • SQL vs NoSQL
    • Best Practices
  • Git
    • Commands
      • Setup and Configuration Commands
      • Getting and Creating Projects
      • Tracking Changes
      • Branching and Merging
      • Sharing and Updating Projects
      • Inspection and Comparison
      • Debugging
      • Patching
      • Stashing and Cleaning
      • Advanced Manipulations
    • Workflows
      • Branching Strategies
        • Git Flow
        • Trunk-Based Development
        • GitHub Flow
        • Comparison
      • Merge Strategies
        • Merge
        • Rebase
        • Squash
        • Fast-forward vs No-fast-forward
        • MR vs PR
      • Conflict Resolution
        • Handling Merge Conflicts
        • Merge Conflicts
        • Rebase Conflicts
        • Divergent Branches After git pull
        • Force Push
      • Patch & Recovery
        • Cherry-pick strategies
        • Revert vs Reset
        • Recover from a bad rebase
      • Rebasing Practices
        • Merge vs Rebase
        • Rebase develop branch on main branch
      • Repository Management
        • Working Directory
        • Mirror a repository
        • Convert a local folder to a Git repo
        • Backup and restore a Git repository
  • Java
    • Java Installation
    • Java Distributions
    • Java Platform Editions
      • Java SE
      • Java EE
      • Jakarta EE
      • Java ME
      • JavaFX
    • Java Overview
      • OOP Principles
        • Encapsulation
        • Inheritance
        • Polymorphism
        • Abstraction
          • Abstract Class & Method
          • Interface
            • Functional Interfaces
            • Marker Interfaces
          • Abstract Class vs Interface
      • OOP Basics
        • What is a Class?
          • Types of Classes
        • What is an Object?
          • Equals and HashCode
            • FAQ
          • Shallow Copy and Deep Copy
          • Ways to Create Object
          • Serialization & Deserialization
        • Methods & Fields
          • Method Overriding & Overloading
          • Method Signature & Header
          • Variables
        • Constructors
        • Access Modifiers
      • Parallelism & Concurrency
        • Ways to Identify Thread Concurrency or Parallelism
        • Thread Basics
          • Thread vs Process
          • Creating Threads
          • Thread Context Switching
          • Thread Lifecycle & States
          • Runnable & Callable
          • Types of Threads
          • Thread Priority
        • Thread Management & Synchronisation
          • Thread Resource Sharing
          • Thread Synchronization
            • Why is Synchronization Needed?
            • Synchronized Blocks & Methods
          • Thread Lock
            • Types of Locks
            • Intrinsic Lock (Monitor Lock)
            • Reentrant Lock
          • Semaphore
          • Thread Starvation
          • Thread Contention
          • Thread Deadlock
          • Best Practices for Avoiding Thread Issues
      • Keywords
        • this
        • super
        • Access Modifiers
      • Data Types
        • Default Values
        • Primitive Types
          • byte
          • short
          • int
          • long
          • float
          • double
          • char
          • boolean
        • Non-Primitive (Reference) Types
          • String
            • StringBuilder
            • StringBuffer
              • Problems
            • Multiline String
            • Comparison - String, StringBuilder & StringBuffer
          • Array
          • Collections
            • List
              • Array vs List
              • ArrayList
              • Vector
                • Stack
                  • Problems
              • LinkedList
            • Queue
              • PriorityQueue
              • Deque (Double-Ended Queue)
                • ArrayDeque
                • ConcurrentLinkedDeque - TBU
                • LinkedBlockingDeque - TBU
            • Map
              • HashMap
              • Hashtable
              • LinkedHashMap
              • ConcurrentHashMap
              • TreeMap
              • EnumMap
              • WeakHashMap
            • Set
              • HashSet
              • LinkedHashSet
              • TreeSet
              • EnumSet
              • ConcurrentSkipListSet
              • CopyOnWriteArraySet
        • Specialized Classes
          • BigInteger
          • BigDecimal
            • Examples
          • BitSet
          • Date and Time
            • Examples
          • Optional
          • Math
          • UUID
          • Scanner
          • Formatter
            • Examples
          • Properties
          • Regex (Pattern and Matcher)
            • Examples
          • Atomic Classes
          • Random
          • Format
            • NumberFormat
            • DateFormat
            • DecimalFormat
        • Others
          • Object
          • Enum
            • Pre-Defined Enum
            • Custom Enum
            • EnumSet and EnumMap
          • Record
          • Optional
          • System
          • Runtime
          • ProcessBuilder
          • Class
          • Void
          • Throwable
            • Error
            • Exception
              • Custom Exception Handling
              • Best Practice
            • Error vs Exception
            • StackTraceElement
    • Java Features by Version
      • How New Java Features are Released ?
      • Java Versions
        • Java 8
        • Java 9
        • Scoped Values
        • Unnamed Variables & Patterns
      • FAQ
    • Concepts
      • Set 1
        • Streams
          • flatmap
          • Collectors Utility Class
          • Problems
        • Functional Interfaces
          • Standard Built-In Interfaces
          • Custom Interfaces
        • Annotation
          • Custom Annotation
          • Meta Annotation
        • Generics
          • Covariance and Invariance
        • Asynchronous Computation
          • Future
          • CompletableFuture
          • Future v/s CompletableFuture
          • ExecutorService
            • Thread Pool
            • Types of Work Queues
            • Rejection Policies
            • ExecutorService Implementations
            • ExecutorService Usage
          • Locks, Atomic Variables, CountDownLatch, CyclicBarrier - TBU
          • Parallel Streams, Fork/Join Framework,Stream API with Parallelism - TBU
      • Set 2
        • Standards
          • ISO Standards
          • JSR
            • JSR 303, 349, 380 (Bean Validation)
        • Operator Precedence
      • Set 3
        • Date Time Formatter
        • Validation
      • Set 4
        • Input from User
        • Comparison & Ordering
          • Object Equality Check
          • Comparable and Comparator
            • Comparator Interface
          • Sorting of Objects
          • Insertion Ordering
    • Packages
      • Core Packages
        • java.lang
          • java.lang.System
          • java.lang.Thread
      • Jakarta Packages
        • jakarta.validation
        • javax.validation
      • Third-party Packages
    • Code Troubleshoot
      • Thread Dump
      • Heap Dump
    • Code Quality & Analysis
      • ArchUnit
      • Terminologies
        • Cyclic dependencies
    • Code Style
      • Naming Convention
      • Package Structure
      • Formatting
      • Comments and Documentation
      • Imports
      • Exception Handling
      • Class Structure
      • Method Guidelines
      • Page 1
      • Code Smells to Avoid
      • Lambdas and Streams Style
      • Tools
    • Tools
      • IntelliJ IDEA
        • Shortcuts for MAC
      • Apache JMeter
        • Examples
      • Thread Dump Capture
        • jstack
        • VisualVM - TBU
        • jcmd - TBU
        • JConsole - TBU
        • YourKit Java Profiler - TBU
        • Eclipse MAT - TBU
        • IntelliJ IDEA Profiler - TBU
        • AppDynamics - TBU
        • Dynatrace - TBU
        • Thread Dump Analyzers - TBU
      • Heap Dump Capture
        • jmap
        • VisualVM - TBU
        • jcmd - TBU
        • Eclipse MAT (Memory Analyzer Tool) - TBU
        • IntelliJ IDEA Profiler - TBU
        • YourKit Java Profiler - TBU
        • AppDynamics - TBU
        • Dynatrace - TBU
        • Kill -3 Command - TBU
        • jhat (Java Heap Analysis Tool) - TBU
        • JVM Options - TBU
      • Wireshark
        • Search Filters
    • Best Practices
      • Artifact and BOM Versioning
  • Maven
    • Installation
    • Local Repository & Configuration
    • Command-line Options
    • Build & Lifecycle
    • Dependency Management
      • Dependency
        • Transitive Dependency
        • Optional Dependency
      • Dependency Scope
        • Maven Lifecycle and Dependency Scope
      • Dependency Exclusions & Overrides
      • Bill of Materials (BOM)
      • Dependency Conflict Resolution
      • Dependency Tree & Analysis
      • Dependency Versioning Strategies
    • Plugins
      • Build Lifecycle Management
      • Dependency Management
      • Code Quality and Analysis
      • Documentation Generation
      • Code Generation
      • Packaging and Deployment
      • Reporting
      • Integration and Testing
      • Customization and Enhancement
        • build-helper-maven-plugin
        • properties-maven-plugin
        • ant-run plugin
        • exec-maven-plugin
        • gmavenplus-plugin
      • Performance Optimization
    • FAQs
      • Fixing Maven SSL Issues: Unable to Find Valid Certification Path
  • Spring
    • Spring Basics
      • What is Spring?
      • Why Use Spring
      • Spring Ecosystem
      • Versioning
      • Setting Up a Spring Project
    • Core Concepts
      • Spring Core
        • Dependency Injection (DI)
        • Stereotype Annotation
      • Spring Beans
        • Bean Lifecycle
        • Bean Scope
          • Singleton Bean
        • Lazy & Eager Initialization
          • Use Case of Lazy Initialization
        • BeanFactory
        • ApplicationContext
      • Spring Annotations
        • Spring Boot Specific
        • Controller Layer (Web & REST Controllers)
    • Spring Features
      • Auto Configuration
        • Spring Boot 2: spring.factories
        • Spring Boot 3: spring.factories
      • Spring Caching
        • In-Memory Caching
      • Spring AOP
        • Before Advice
        • After Returning Advice
        • After Throwing Advice
        • After (finally) Advice
        • Around Advice
      • Spring File Handling
      • Reactive Programming
        • Reactive System
        • Reactive Stream Specification
        • Project Reactor
          • Mono & Flux
      • Asynchronous Computation
        • @Async annotation
      • Spring Security
        • Authentication
          • Core Components
            • Security Filter Chain
              • HttpSecurity
              • Example
            • AuthenticationManager
            • AuthenticationProvider
            • UserDetailsService
              • UserDetails
              • PasswordEncoder
            • SecurityContext
            • SecurityContextHolder
            • GrantedAuthority
            • Security Configuration (Spring Security DSL)
          • Authentication Models
            • One-Way Authentication
            • Mutual Authentication
          • Authentication Mechanism
            • Basic Authentication
            • Form-Based Authentication
            • Token-Based Authentication (JWT)
            • OAuth2 Authentication
            • Multi-Factor Authentication (MFA)
            • SAML Authentication
            • X.509 Certificate Authentication
            • API Key Authentication
            • Remember-Me Authentication
            • Custom Authentication
          • Logout Handling
        • Authorization
        • Security Filters and Interceptors
        • CSRF
          • Real-World CSRF Attacks & Prevention
        • CORS
        • Session Management and Security
        • Best Practices
      • Spring Persistence
        • JDBC
          • JDBC Components
          • JDBC Template
          • Transaction Management
          • Best Practices in JDBC Usage
          • Datasource
            • Connection Pooling
              • HikariCP
            • Caching
        • JPA (Java Persistence API)
          • JPA Fundamentals
          • ORM Mapping Annotations
            • 1. Entity and Table Mappings
            • 2. Field/Column Mappings
            • 3. Relationship Mappings
            • 4. Inheritance Mappings
            • 5. Additional Configuration Annotations
          • Querying Data
            • JPQL
            • Criteria API
            • JPA Specification
              • Example - Employee Portal
            • Native SQL Queries
            • Named Queries
            • Query Return Types
            • Pagination & Sorting
              • Example - Employee Portal
            • Projection
          • Fetch Strategies in JPA
        • JPA Implementation
          • Hibernate
            • Properties
            • Example
        • Spring Data JPA
          • Repository Abstractions
          • Entity-to-Table Mapping
          • Derived Query Methods
        • Cross-Cutting Concerns
          • Transactions
          • Caching
          • Concurrency
        • Examples
          • Employee Portal
            • API
    • Distributed Systems & Communication
      • Distributed Scheduling
      • Inter-Service Communication
        • 1. RestTemplate
        • 2. WebClient
        • 3. OpenFeign
        • Retry Mechanism
          • @Retryable annotation
            • Example
    • Security & Data Protection
      • Encoding | Decoding
        • Types
          • Base Encoding
            • Base16 - TBD
              • Encoding and Decoding in Java - TBD
            • Base32
              • Encoding and Decoding in Java
            • Base64 -TBD
              • Encoding and Decoding in Java - TBD
          • Text Encoding - TBD
            • Extended ASCII
              • Encoding and Decoding in Java - TBD
                • ISO-8859-1
                • Windows-1252 - TBD
                • IBM Code Pages - TBD
            • ASCII
              • Encoding and Decoding in Java
        • Java Guidelines
          • Text Encoding Decoding Examples
          • Base Encoding Decoding Examples
          • Best Practices and Concepts
          • Libraries
      • Cryptography
        • Terminology
        • Java Cryptography Architecture (JCA)
        • Key Management
          • Key Generation
            • Tools and Libraries
              • OpenSSL
              • Java Keytool
                • Concept
                • Use Cases
            • Key & Certificate File Formats
          • Key Distribution
          • Key Storage
          • Key Rotation
          • Key Revocation
        • Encryption & Decryption
          • Symmetric Encryption
            • Algorithm
            • Modes of Operation
            • Examples
          • Asymmetric Encryption
            • Algorithm
            • Mode of Operation
            • Examples
    • Utilities & Libraries
      • Apache Libraries
        • Apache Camel
          • Camel Architecture
            • Camel Context
            • Camel Endpoints
            • Camel Components
            • Camel Exchange & MEP
          • Spring Dependency
          • Different Components
            • Camel SFTP
        • Apache Commons Lang
      • MapStruct Mapper
      • Utilities by Spring framework
        • FileCopyUtils
    • General Concepts
      • Spring Boot Artifact Packaging
      • Classpath and Resource Loading
      • Configuration - Mapping Properties to Java Class
      • Validations in Spring Framework
        • Jakarta Validation
          • Jakarta Bean Validation Annotations
    • Practical Guidelines
      • Spring Configuration
      • Spring Code Design
  • Software Testing
    • Software Testing Methodologies
      • Functional Testing
      • Non Functional Testing
    • Software Testing Life Cycle (STLC)
    • Integration Test
      • Dynamic Property Registration
    • Java Test Framework
      • JUnit
        • JUnit 4
          • Examples
        • JUnit 5
          • Examples
        • JUnit 4 vs JUnit 5
  • System Design
    • Foundations
      • Programming Paradigms
      • Object-Oriented Design
        • SOLID Principles
        • GRASP Principles
        • Composition
        • Aggregation
        • Association
      • Design Pattern
        • Creational Pattern
        • Structural Pattern
        • Behavioral Pattern
        • Examples
          • Data Collector
          • Payment Processor
        • Design Enhancements
          • Fluent API Design
            • Examples
    • Architectural Building Blocks
      • CAP Theorem
      • Load Balancer
        • Load Balancer Architecture
        • Load Balancing in Java Microservices
          • Client-Side Load Balancing Example
          • Server-Side Load Balancing Example
        • Load Balancer Monitoring Tool
      • Scaling
        • Vertical Scaling (Scaling Up)
        • Horizontal Scaling (Scaling Out)
        • Auto-Scaling
        • Database Scaling via Sharding
      • Caching
        • Pod-Level vs Distributed Caching
      • Networking Metrics
        • Types of Delay
        • Scenario
      • System Characteristics
      • Workload Types
      • Resilience & Failure Handling
    • Performance
      • Why Is My API Sometimes Slow ?
    • Security
      • Security by Design
      • Zero Trust Security Model
      • Zero Trust Architecture
      • Principles
        • CIA
        • Least Privilege Principle
        • Defense in Depth
      • Security Threats & Mitigations
        • OWASP
          • Top 10 Security Threats
          • Application Security Verification Standard
          • Software Assurance Maturity Model
          • Dependency Check
          • CSRFGuard
          • Cheat Sheets
          • Security Testing Guide
          • Threat Dragon
        • Threat Modeling
      • Compliance & Regulation
        • PCI DSS
    • Deployment Patterns
    • Diagrams
      • UML Diagrams
        • PlantUML
          • Class Diagram
          • Object Diagram
          • Sequence Diagram
          • Use Case Diagram
          • Activity Diagram
          • State Diagram
          • Architecture Diagram
          • Component Diagram
          • Timing Diagram
          • ER Diagram (Entity-Relationship)
          • Network Diagram
    • Common Terminologies
    • Problems
      • Reference Materials
      • Cache Design
  • Interview Guide
    • Non-Technical
      • Behavioural or Introductory Guide
      • Project Specific
    • Technical
      • Java Interview Companion
        • Java Key Concepts
          • Set 1
          • Set 2
        • Java Code Snippets
        • Java Practice Programs
          • Set 3 - Strings
          • Set 4 - Search
          • Set 5 - Streams and Collection
      • SQL Interview Companion
        • SQL Practice Problems
          • Set 1
      • Spring Interview Companion
        • Spring Key Concepts
          • Set 1 - General
          • Set 2 - Core Spring
        • Spring Code Snippets
          • JPA
      • Application Server
      • Maven
      • Containerized Application
      • Microservices
    • General
      • Applicant Tracking System (ATS)
      • Flowchart - How to Solve Coding Problem?
Powered by GitBook
On this page
  • What are the features of JAVA?
  • How does Java enable high performance?
  • What is Inheritance?
  • What is Encapsulation?
  • What is Polymorphism?
  • What is meant by Interface?
  • What is meant by Abstract class?
  • Difference between Array and Array List
  • Difference between HashMap and HashTable
  • Difference between HashSet and TreeSet
  • Difference between Abstract class and Interface
  • What is Java Collections Framework?
  • Explain the different lists available in the collection?
  • Explain about Set and their types in a collection
  • Explain about Map and its types?
  • Explain the Priority Queue?
  • What is the final keyword in Java?
  • What is a Thread? Different ways to create a thread?
  • Ways to Create a Thread in Java
  • Different Thread Methods
  • Different ways to stop or pause a thread
  • When to use the Runnable interface Vs Thread class?
  • Difference between start() and run() method of thread class
  • Difference between Multi-threading and Parallel processing?
  • Explain the thread life cycle in Java.
  • What is Synchronization?
  • What is Volatile Variable and its purpose?

Was this helpful?

  1. Interview Guide
  2. Technical
  3. Java Interview Companion
  4. Java Key Concepts

Set 2

What are the features of JAVA?

Features of Java are as follows:

  • OOP concepts

    • Object-oriented

    • Inheritance

    • Encapsulation

    • Polymorphism

    • Abstraction

  • Platform independent: A single program works on different platforms without any modification.

  • High Performance: JIT (Just In Time compiler) enables high performance in Java. JIT converts the bytecode into machine language and then JVM starts the execution.

  • Multi-threaded: A flow of execution is known as a Thread. JVM creates a thread which is called the main thread. The user can create multiple threads by extending the thread class or by implementing the Runnable interface.

How does Java enable high performance?

Java uses Just In Time compiler to enable high performance. It is used to convert the instructions into bytecodes.

What is Inheritance?

Inheritance means one class can extend to another class. So that the codes can be reused from one class to another class. The existing class is known as the Super class whereas the derived class is known as a sub class.

// Super class
public class Manupulation {
}

// Sub class
public class Addition extends Manipulation {
}

What is Encapsulation?

Purpose of Encapsulation:

  • Protects the code from others.

  • Code maintainability.

We are declaring ‘a’ as an integer variable and it should not be negative.

public class Addition {
    int a=5;
}

If someone changes the exact variable as “a = -5” then it is bad.

In order to overcome the problem we need to follow the steps below:

  • We can make the variable private or protected.

  • Use public accessor methods such as set<property> and get<property>.

So that the above code can be modified as:

public class Addition {
    private int a = 5; //Here the variable is marked as private
    // getter
    // setter
}

For encapsulation, we need to make all the instance variables private and create setter and getter for those variables. Which in turn will force others to call the setters rather than access the data directly.

What is Polymorphism?

Polymorphism means many forms. Polymorphism is applicable for overriding and not for overloading.

What is meant by Interface?

Multiple inheritances cannot be achieved in java. To overcome this problem the Interface concept is introduced. An interface in Java is a template or reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Interfaces cannot contain instance fields or constructors. Java does not support multiple inheritance (i.e., a class cannot inherit from more than one class) to avoid complexity and ambiguity (such as the Diamond Problem). However, multiple inheritance of type is achieved by using interfaces. A class can implement multiple interfaces, thus providing a way to achieve multiple inheritances.

  • All the methods in the interface are internally public abstract void.

  • All the variables in the interface are internally public static final that is constants.

  • Classes can implement the interface and not extends.

  • The class which implements the interface should provide an implementation for all the methods declared in the interface.

In an interface, we do not need to explicitly mark methods as abstract; they are implicitly public and abstract.

interface MyInterface {
    // Constant
    int CONSTANT = 10; // public static final by default

    // Abstract method
    void method1(); // public abstract by default

    // Default method (since Java 8)
    default void method2() {
        System.out.println("This is a default method");
    }

    // Static method (since Java 8)
    static void method3() {
        System.out.println("This is a static method");
    }
}

class MyClass implements MyInterface {
    @Override
    public void method1() {
        System.out.println("Implementation of method1");
    }
}

public class Main {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.method1(); // Implementation of method1
        myClass.method2(); // This is a default method
        MyInterface.method3(); // This is a static method
    }
}

What is meant by Abstract class?

An abstract class in Java is a class that cannot be instantiated on its own and is intended to be subclassed by other classes. It is used to define common characteristics and behaviors that multiple derived classes can share, but it can also include abstract methods that must be implemented by the subclasses.

  1. Cannot Be Instantiated: You cannot create an instance of an abstract class.

  2. Can Contain Abstract Methods: These are methods declared without an implementation. Subclasses must provide implementations for these methods.

  3. Can Contain Concrete Methods: These are methods with an implementation. Subclasses can use or override these methods.

  4. Can Have Constructors: Although you cannot instantiate an abstract class, you can define constructors in it, and these constructors are called when an instance of a subclass is created.

  5. Can Have Fields and Methods: Just like regular classes, abstract classes can have member variables and methods.

  6. Can Implement Interfaces: Abstract classes can implement interfaces, and the implementing subclasses must provide implementations for the interface methods.

interface AnimalBehavior {
    void eat();
}

abstract class Animal implements AnimalBehavior {
    // Fields
    private String name;

    // Constructor
    public Animal(String name) {
        this.name = name;
    }

    // Concrete method
    public void sleep() {
        System.out.println(name + " is sleeping.");
    }

    // Abstract method
    public abstract void makeSound();

    // Concrete method that uses the abstract method
    public void performSound() {
        makeSound();
    }

    // Getter for name
    public String getName() {
        return name;
    }
}

class Dog extends Animal {
    // Constructor
    public Dog(String name) {
        super(name); // Call to the constructor of the abstract class
    }

    // Implementation of the abstract method
    @Override
    public void makeSound() {
        System.out.println(getName() + " says: Bark Bark");
    }

    // Implementation of the interface method
    @Override
    public void eat() {
        System.out.println(getName() + " is eating dog food.");
    }
}

class Cat extends Animal {
    // Constructor
    public Cat(String name) {
        super(name); // Call to the constructor of the abstract class
    }

    // Implementation of the abstract method
    @Override
    public void makeSound() {
        System.out.println(getName() + " says: Meow Meow");
    }

    // Implementation of the interface method
    @Override
    public void eat() {
        System.out.println(getName() + " is eating cat food.");
    }
}

class Cat extends Animal {
    // Constructor
    public Cat(String name) {
        super(name); // Call to the constructor of the abstract class
    }

    // Implementation of the abstract method
    @Override
    public void makeSound() {
        System.out.println(getName() + " says: Meow Meow");
    }

    // Implementation of the interface method
    @Override
    public void eat() {
        System.out.println(getName() + " is eating cat food.");
    }
}

public class Main {
    public static void main(String[] args) {
        // Animal animal = new Animal("Generic Animal"); // This would be an error: Cannot instantiate the abstract class

        // Create instances of subclasses
        Dog dog = new Dog("Buddy");
        Cat cat = new Cat("Whiskers");

        // Call concrete methods
        dog.sleep(); // Buddy is sleeping.
        cat.sleep(); // Whiskers is sleeping.

        // Call abstract method implementations
        dog.makeSound(); // Buddy says: Bark Bark
        cat.makeSound(); // Whiskers says: Meow Meow

        // Call interface method implementations
        dog.eat(); // Buddy is eating dog food.
        cat.eat(); // Whiskers is eating cat food.

        // Call concrete method in abstract class that uses an abstract method
        dog.performSound(); // Buddy says: Bark Bark
        cat.performSound(); // Whiskers says: Meow Meow
    }
}

Difference between Array and Array List

Feature
Array
ArrayList

Definition

A fixed-size data structure that holds elements of the same type.

A resizable array implementation of the List interface.

Size

Fixed size, determined at the time of creation.

Dynamic size, can grow or shrink as needed.

Performance

Faster for indexed access and manipulation due to fixed size.

Slower for indexed access compared to arrays due to resizing and potential overhead.

Flexibility

Less flexible; size cannot be changed after creation.

More flexible; can change size dynamically.

Initialization

int[] arr = new int[10];

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

Element Type

Can hold primitive types or objects.

Can only hold objects (wrapper classes for primitives).

Memory Management

Continuous memory allocation.

Non-continuous memory allocation; uses an internal array that grows as needed.

Methods Available

Limited to basic operations (e.g., length, clone).

Extensive methods from the List interface (e.g., add, remove, get, size, contains).

Iteration

Requires loop constructs like for, while.

Supports enhanced for-loop and iterator.

Type Safety

Type-safe with primitive types and objects.

Type-safe with generics; can enforce type constraints.

Null Values

Can hold null values.

Can hold null values.

Use Case

Best for fixed-size collections where performance is critical.

Best for dynamic collections where the size may change frequently.

Example

int[] numbers = {1, 2, 3, 4, 5};

ArrayList<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));

Multidimensional

Supports multidimensional arrays (e.g., int[][] matrix).

Supports only single-dimensional ArrayLists; multidimensional behavior achieved with nested ArrayLists.

Capacity Management

No concept of capacity; fixed size.

Initial capacity can be specified; grows automatically when capacity is exceeded.

Primitive Handling

Directly stores primitive types.

Requires boxing/unboxing for primitive types (e.g., int to Integer).

Difference between HashMap and HashTable

Feature
HashMap
Hashtable

Thread Safety

Not thread-safe

Thread-safe

Synchronization

No methods are synchronized

All methods are synchronized

Performance

Faster due to lack of synchronization

Slower due to synchronization overhead

Null Keys and Values

Allows one null key and multiple null values

Does not allow null keys or null values

Legacy

Part of the Java Collections Framework

Legacy class (exists since JDK 1.0)

Iteration Order

Does not guarantee any specific order

Does not guarantee any specific order

Initial Capacity and Load Factor

Default initial capacity of 16 and load factor of 0.75

Initial capacity is 11 and load factor is 0.75

Fail-Fast Iterator

Yes, throws ConcurrentModificationException if the map is modified while iterating

Yes, but the behavior is undefined

Use Case

Best for non-threaded applications

Best for legacy applications requiring thread safety

Example Initialization

HashMap<String, Integer> map = new HashMap<>();

Hashtable<String, Integer> table = new Hashtable<>();

Synchronization Control

Can be synchronized externally using Collections.synchronizedMap(new HashMap<>());

Internally synchronized, cannot be made non-synchronized

Difference between HashSet and TreeSet

Feature
HashSet
TreeSet

Underlying Data Structure

Hash table

Red-Black tree (a type of self-balancing binary search tree)

Order of Elements

No guaranteed order

Elements are sorted in natural order or by a provided comparator

Performance (Basic Operations)

O(1) average time complexity for add, remove, and contains operations

O(log n) time complexity for add, remove, and contains operations

Null Elements

Allows a single null element

Does not allow null elements (throws NullPointerException)

Duplicates

Does not allow duplicate elements

Does not allow duplicate elements

Iteration Order

No guaranteed iteration order

Iterates in ascending order

Comparator Support

No

Yes, can use a custom comparator for sorting

Methods for Range Operations

No

Yes, provides methods like subSet(), headSet(), tailSet()

Example Initialization

Set<String> set = new HashSet<>();

Set<String> set = new TreeSet<>();

Use Case

Best for collections with unique elements and no ordering requirement

Best for collections with unique elements that need to be sorted

Difference between Abstract class and Interface

Feature
Abstract Class
Interface

Definition

Can contain abstract and concrete methods.

Can only contain abstract methods (until Java 8). From Java 8 onwards, can contain default and static methods.

Purpose

To provide a common base class with shared code.

To define a contract that implementing classes must follow.

Inheritance

A class can inherit only one abstract class (single inheritance).

A class can implement multiple interfaces (multiple inheritance).

Implementation

Can provide method implementations.

Cannot provide method implementations (except default and static methods from Java 8 onwards).

Fields

Can have instance variables (fields) and static fields.

Can only have static final fields (constants).

Constructors

Can have constructors.

Cannot have constructors.

Access Modifiers

Can have any access modifier (public, protected, private).

Methods are implicitly public (until Java 9). Can have private methods from Java 9 onwards.

When to Use

When you want to share code among several closely related classes.

When you want to define a role that can be shared among classes not necessarily related.

Multiple Inheritance

Does not support multiple inheritance.

Supports multiple inheritance.

Example Usage

abstract class Animal { ... }

interface AnimalBehavior { ... }

Method Implementation

Can contain both abstract and concrete methods.

Can contain abstract methods, and from Java 8 onwards, default and static methods.

State Management

Can manage state via instance variables.

Cannot manage state, only constants.

Instantiation

Cannot be instantiated directly.

Cannot be instantiated directly.

What is Java Collections Framework?

The Java Collections Framework is a unified architecture for representing and manipulating collections of objects. It includes interfaces, implementations, and algorithms to help developers work with groups of objects in a standard way. The key components of the Java Collections Framework are:

Interfaces

These are abstract data types that represent collections. Some of the primary interfaces include:

  • Collection: The root interface in the collection hierarchy. A collection represents a group of objects known as its elements.

    • List: An ordered collection (also known as a sequence). Allows duplicate elements. Examples: ArrayList, LinkedList.

    • Set: A collection that does not allow duplicate elements. Examples: HashSet, TreeSet.

    • Queue: A collection designed for holding elements prior to processing. Examples: PriorityQueue, LinkedList.

    • Deque: A double-ended queue that allows elements to be added or removed from both ends. Examples: ArrayDeque, LinkedList.

  • Map: An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value. Examples: HashMap, TreeMap, Hashtable.

Implementations

These are the concrete classes that implement the collection interfaces. Some examples include:

  • ArrayList: Implements the List interface. Uses a dynamic array to store elements.

  • LinkedList: Implements both List and Deque interfaces. Uses a doubly linked list to store elements.

  • HashSet: Implements the Set interface. Uses a hash table for storage.

  • TreeSet: Implements the Set interface. Uses a Red-Black tree for storage, which orders the elements.

  • HashMap: Implements the Map interface. Uses a hash table for storage.

  • TreeMap: Implements the Map interface. Uses a Red-Black tree for storage, which orders the keys.

Algorithms

These are methods that perform useful computations, such as searching and sorting, on objects that implement collection interfaces. These algorithms are defined as static methods within the java.util.Collections class.

java.util.Collections Class

The java.util.Collections class consists of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers" which return a new collection backed by a specified collection, and a few other odds and ends.

Key Methods in java.util.Collections

  • Sorting:

    • sort(List<T> list): Sorts the specified list into ascending order.

    • sort(List<T> list, Comparator<? super T> c): Sorts the specified list according to the order induced by the specified comparator.

  • Searching:

    • binarySearch(List<? extends T> list, T key): Searches the specified list for the specified object using the binary search algorithm.

    • binarySearch(List<? extends T> list, T key, Comparator<? super T> c): Searches the specified list for the specified object using the binary search algorithm and a comparator.

  • Shuffling:

    • shuffle(List<?> list): Randomly permutes the specified list.

    • shuffle(List<?> list, Random rnd): Randomly permutes the specified list using the specified source of randomness.

  • Synchronization:

    • synchronizedCollection(Collection<T> c): Returns a synchronized (thread-safe) collection backed by the specified collection.

    • synchronizedList(List<T> list): Returns a synchronized (thread-safe) list backed by the specified list.

    • synchronizedMap(Map<K,V> m): Returns a synchronized (thread-safe) map backed by the specified map.

  • Unmodifiable Collections:

    • unmodifiableCollection(Collection<? extends T> c): Returns an unmodifiable view of the specified collection.

    • unmodifiableList(List<? extends T> list): Returns an unmodifiable view of the specified list.

    • unmodifiableMap(Map<? extends K,? extends V> m): Returns an unmodifiable view of the specified map.

Explain the different lists available in the collection?

In the Java Collections Framework, the List interface is a part of the java.util package and represents an ordered collection (also known as a sequence). The List interface extends the Collection interface and includes operations for positional access, searching, iteration, and range-view. Various implementations of the List interface provide different ways of storing and managing the elements. Here are the main List implementations available:

1. ArrayList

  • Description:

    • Implements the List interface using a dynamically resizable array.

    • Provides fast random access to elements.

  • Key Characteristics:

    • Resizing: Automatically grows when elements are added beyond its capacity.

    • Performance: O(1) time complexity for positional access. O(n) for add/remove operations when resizing is necessary.

    • Nulls: Allows null elements.

  • Use Case: Suitable for frequent read operations and occasional insertions and deletions.

import java.util.ArrayList;
import java.util.List;

public class ArrayListExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");

        System.out.println(list);
    }
}

2. LinkedList

  • Description:

    • Implements the List interface using a doubly linked list.

    • Provides efficient insertion and removal of elements.

  • Key Characteristics:

    • Structure: Each element (node) contains a reference to the previous and next elements.

    • Performance: O(1) time complexity for insertions and deletions at the beginning or end. O(n) for positional access.

    • Nulls: Allows null elements.

  • Use Case: Suitable for applications that require frequent insertions and deletions, particularly at the beginning or end of the list.

import java.util.LinkedList;
import java.util.List;

public class LinkedListExample {
    public static void main(String[] args) {
        List<String> list = new LinkedList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");

        System.out.println(list);
    }
}

3. Vector

  • Description:

    • Implements the List interface using a dynamically resizable array, similar to ArrayList.

    • Synchronized, making it thread-safe.

  • Key Characteristics:

    • Thread-Safety: All methods are synchronized.

    • Performance: O(1) time complexity for positional access. Slower than ArrayList due to synchronization overhead.

    • Nulls: Allows null elements.

  • Use Case: Suitable for legacy codebases and applications requiring thread-safe list operations.

import java.util.List;
import java.util.Vector;

public class VectorExample {
    public static void main(String[] args) {
        List<String> list = new Vector<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");

        System.out.println(list);
    }
}

4. Stack

  • Description:

    • A subclass of Vector that implements a last-in-first-out (LIFO) stack.

  • Key Characteristics:

    • LIFO: Provides typical stack operations like push, pop, and peek.

    • Performance: Similar to Vector.

    • Nulls: Allows null elements.

  • Use Case: Suitable for stack operations and legacy applications requiring stack functionalities.

import java.util.Stack;

public class StackExample {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        stack.push("Apple");
        stack.push("Banana");
        stack.push("Cherry");

        System.out.println(stack);
    }
}

5. CopyOnWriteArrayList

  • Description:

    • A thread-safe variant of ArrayList in which all mutative operations (e.g., add, set, remove) are implemented by making a fresh copy of the underlying array.

  • Key Characteristics:

    • Thread-Safety: Thread-safe without using synchronization.

    • Performance: Efficient for read operations, but slower for write operations due to array copying.

    • Nulls: Allows null elements.

  • Use Case: Suitable for applications with many concurrent read operations and relatively few write operations.

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListExample {
    public static void main(String[] args) {
        List<String> list = new CopyOnWriteArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");

        System.out.println(list);
    }
}

Explain about Set and their types in a collection

In the Java Collections Framework, the Set interface is a part of the java.util package and represents a collection that does not allow duplicate elements. The Set interface extends the Collection interface. There are several implementations of the Set interface, each providing different ways to store and manage elements. Here's a detailed look at the internals of Set and its types:

Set Interface

The Set interface defines a collection that does not allow duplicate elements. It models the mathematical set abstraction and provides methods for basic operations like adding, removing, and checking for elements. The primary implementations of the Set interface include HashSet, LinkedHashSet, and TreeSet.

1. HashSet

  • Description:

    • Implements the Set interface using a hash table.

    • Provides constant-time performance for basic operations (add, remove, contains).

  • Internals:

    • Uses a HashMap internally to store elements.

    • Elements are stored as keys in the HashMap, with a dummy value.

    • The hash code of the element is used to determine its position in the hash table.

  • Key Characteristics:

    • Order: No guaranteed order of elements.

    • Performance: O(1) average time complexity for basic operations.

    • Nulls: Allows a single null element.

  • Use Case: Suitable for collections where fast access is required, and the order of elements is not important.

import java.util.HashSet;
import java.util.Set;

public class HashSetExample {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("Apple");
        set.add("Banana");
        set.add("Cherry");

        System.out.println(set); // Order is not guaranteed
    }
}

2. LinkedHashSet

  • Description:

    • Extends HashSet and maintains a linked list of the entries in the set.

    • Provides insertion-order iteration.

  • Internals:

    • Uses a LinkedHashMap internally.

    • Maintains a doubly linked list running through all of its entries to maintain insertion order.

  • Key Characteristics:

    • Order: Maintains insertion order of elements.

    • Performance: Slightly slower than HashSet due to the additional linked list.

    • Nulls: Allows a single null element.

  • Use Case: Suitable for collections where fast access is required, but the order of elements needs to be preserved.

import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetExample {
    public static void main(String[] args) {
        Set<String> set = new LinkedHashSet<>();
        set.add("Apple");
        set.add("Banana");
        set.add("Cherry");

        System.out.println(set); // Order is preserved
    }
}

3. TreeSet

  • Description:

    • Implements the Set interface using a Red-Black tree (a self-balancing binary search tree).

    • Provides sorted order of elements.

  • Internals:

    • Uses a TreeMap internally.

    • Elements are stored as keys in the TreeMap.

    • The tree is sorted according to the natural ordering of its elements or by a comparator provided at set creation time.

  • Key Characteristics:

    • Order: Elements are sorted in ascending order or by a provided comparator.

    • Performance: O(log n) time complexity for basic operations.

    • Nulls: Does not allow null elements (throws NullPointerException).

  • Use Case: Suitable for collections where sorted order of elements is required.

import java.util.Set;
import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add("Apple");
        set.add("Banana");
        set.add("Cherry");

        System.out.println(set); // Elements are sorted in ascending order
    }
}

Explain about Map and its types?

In the Java Collections Framework, the Map interface is a part of the java.util package and represents a collection of key-value pairs. A Map cannot contain duplicate keys, and each key can map to at most one value. There are several implementations of the Map interface, each providing different ways to store and manage key-value pairs. Here's a detailed look at the Map interface and its types:

Map Interface

The Map interface defines a collection that maps keys to values. It includes methods for basic operations like putting, getting, removing, and checking for elements. The primary implementations of the Map interface include HashMap, LinkedHashMap, TreeMap, and Hashtable.

1. HashMap

  • Description:

    • Implements the Map interface using a hash table.

    • Provides constant-time performance for basic operations (put, get, remove).

  • Internals:

    • Uses an array of buckets, where each bucket is a linked list (or tree in case of many collisions).

    • The hash code of the key is used to determine its position in the hash table.

  • Key Characteristics:

    • Order: No guaranteed order of keys.

    • Performance: O(1) average time complexity for basic operations.

    • Nulls: Allows one null key and multiple null values.

  • Use Case: Suitable for collections where fast access is required, and the order of keys is not important.

import java.util.HashMap;
import java.util.Map;

public class HashMapExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Cherry", 3);

        System.out.println(map);
    }
}

2. LinkedHashMap

  • Description:

    • Extends HashMap and maintains a doubly linked list of the entries.

    • Provides insertion-order iteration.

  • Internals:

    • Uses a hash table with a linked list running through all of its entries to maintain insertion order.

  • Key Characteristics:

    • Order: Maintains insertion order of keys.

    • Performance: Slightly slower than HashMap due to the additional linked list.

    • Nulls: Allows one null key and multiple null values.

  • Use Case: Suitable for collections where fast access is required, but the order of keys needs to be preserved.

import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new LinkedHashMap<>();
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Cherry", 3);

        System.out.println(map);
    }
}

3. TreeMap

  • Description:

    • Implements the Map interface using a Red-Black tree (a self-balancing binary search tree).

    • Provides sorted order of keys.

  • Internals:

    • Uses a tree structure where elements are sorted according to the natural ordering of its keys or by a comparator provided at map creation time.

  • Key Characteristics:

    • Order: Keys are sorted in ascending order or by a provided comparator.

    • Performance: O(log n) time complexity for basic operations.

    • Nulls: Does not allow null keys (throws NullPointerException).

  • Use Case: Suitable for collections where sorted order of keys is required.

import java.util.Map;
import java.util.TreeMap;

public class TreeMapExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new TreeMap<>();
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Cherry", 3);

        System.out.println(map); // Keys are sorted in ascending order
    }
}

4. Hashtable

  • Description:

    • Implements the Map interface using a hash table.

    • Synchronized, making it thread-safe.

  • Internals:

    • Uses an array of buckets, where each bucket is a linked list.

    • The hash code of the key is used to determine its position in the hash table.

  • Key Characteristics:

    • Order: No guaranteed order of keys.

    • Performance: Slower than HashMap due to synchronization overhead.

    • Nulls: Does not allow null keys or values (throws NullPointerException).

  • Use Case: Suitable for legacy applications requiring thread-safe map operations.

import java.util.Hashtable;
import java.util.Map;

public class HashtableExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new Hashtable<>();
        map.put("Apple", 1);
        map.put("Banana", 2);
        map.put("Cherry", 3);

        System.out.println(map);
    }
}

Explain the Priority Queue?

In the Java Collections Framework, PriorityQueue is an implementation of the Queue interface that provides a priority-based ordering of elements. Elements in a PriorityQueue are ordered either by their natural ordering (if they implement the Comparable interface) or by a comparator provided at queue construction time. This makes PriorityQueue useful in scenarios where elements need to be processed based on their priority.

Key Features of PriorityQueue:

  1. Priority Ordering:

    • Elements are ordered based on their priority, defined by either natural order or a custom comparator.

    • The head of the queue is always the least element with respect to the specified ordering.

  2. Dynamic Size:

    • Unlike arrays or linked lists, PriorityQueue sizes can change dynamically as elements are added or removed.

  3. Efficient Operations:

    • Basic operations like add, offer, peek, and poll have logarithmic time complexities (O(log n)), where n is the number of elements in the queue.

    • Removing the head (highest priority element) is efficient due to the underlying heap structure.

Internal Structure:

Internally, a PriorityQueue uses a heap data structure, specifically a binary heap, to maintain the priority order of elements. In a binary heap:

  • Min-Heap: The smallest element is always at the root, making it suitable for PriorityQueue where the smallest element (by natural order or comparator) is dequeued first.

  • Max-Heap: The largest element is at the root, which can be simulated by using a comparator that reverses the natural order.

Example Usage:

import java.util.PriorityQueue;

public class PriorityQueueExample {
    public static void main(String[] args) {
        // Creating a priority queue of integers
        PriorityQueue<Integer> pq = new PriorityQueue<>();

        // Adding elements to the priority queue
        pq.add(10);
        pq.add(20);
        pq.add(15);
        pq.add(5);

        // Printing elements of the priority queue
        System.out.println("PriorityQueue elements: " + pq);

        // Removing elements from the priority queue
        System.out.println("Removing elements from the priority queue:");
        while (!pq.isEmpty()) {
            System.out.println("Removed: " + pq.poll());
        }
    }
}

Use Cases:

  • Task Scheduling: Process tasks based on their priority (e.g., shortest job first in scheduling algorithms).

  • Event Handling: Handle events or notifications based on urgency or importance.

  • Graph Algorithms: Implement algorithms like Dijkstra's shortest path algorithm, where nodes are processed in order of their priority.

What is the final keyword in Java?

Final variable: Once a variable is declared as final, then the value of the variable could not be changed. It is like a constant.

Final method: A final keyword in a method, couldn’t be overridden. If a method is marked as a final, then it can’t be overridden by the subclass.

Final class: If a class is declared as final, then the class couldn’t be subclassed. No class can extend the final class.

What is a Thread? Different ways to create a thread?

In Java, a thread refers to the smallest unit of execution within a process. It allows concurrent execution of tasks, enabling programs to perform multiple operations simultaneously. Threads share memory space and resources within the same process, making them lightweight compared to processes.

Every java program has at least one thread called the main thread, the main thread is created by JVM. The user can define their own threads.

Ways to Create a Thread in Java

There are two main ways to create a thread in Java:

1. Extending the Thread Class

You can create a thread by extending the Thread class and overriding its run() method, which contains the code that executes when the thread starts.

Example:

// Step 1: Define a class that extends Thread
class MyThread extends Thread {
    // Step 2: Override the run() method
    @Override
    public void run() {
        System.out.println("Thread is running...");
    }
}

// Step 3: Create an instance of the thread and start it
public class ThreadExample {
    public static void main(String[] args) {
        // Step 4: Create and start the thread
        MyThread thread = new MyThread();
        thread.start(); // starts the execution of the thread
    }
}

2. Implementing the Runnable Interface

You can create a thread by implementing the Runnable interface and providing an implementation for the run() method. This approach separates the thread's behavior from the thread itself, allowing better code organization and reuse.

Example:

// Step 1: Define a class that implements Runnable
class MyRunnable implements Runnable {
    // Step 2: Implement the run() method
    @Override
    public void run() {
        System.out.println("Runnable thread is running...");
    }
}

// Step 3: Create an instance of the Runnable and pass it to a Thread
public class RunnableThreadExample {
    public static void main(String[] args) {
        // Step 4: Create a Runnable instance
        MyRunnable myRunnable = new MyRunnable();

        // Step 5: Pass the Runnable instance to a Thread
        Thread thread = new Thread(myRunnable);

        // Step 6: Start the thread
        thread.start(); // starts the execution of the thread
    }
}

Key Points to Remember:

  • Both approaches (Thread subclass and Runnable interface) achieve the same goal of creating a new thread.

  • Implementing Runnable is generally preferred over extending Thread because it allows better separation of concerns and allows the class to extend another class if needed.

  • When a thread's run() method completes, the thread terminates unless specified otherwise.

Additional Considerations:

  • Lambda Expression (Java 8 and later): You can use lambda expressions to create and start a thread, especially when the thread logic is simple and can be expressed inline.

    Example using lambda expression:

    Thread thread = new Thread(() -> {
        System.out.println("Thread using lambda is running...");
    });
    thread.start();
  • Executor Framework: Java provides higher-level concurrency utilities such as ExecutorService and ThreadPoolExecutor from the java.util.concurrent package, which manage thread execution more efficiently than creating threads manually.

Threads are fundamental to Java's support for concurrent programming, allowing developers to create applications that can perform tasks concurrently and efficiently utilize available resources.

Different Thread Methods

In Java, several methods are crucial for thread management and synchronization. Here's an overview of each method you mentioned:

1. join()

The join() method allows one thread to wait for the completion of another thread. When a thread calls join() on another thread, it suspends its execution until the thread it joined completes its execution or a specified timeout occurs.

Example:

Thread thread1 = new Thread(() -> {
    System.out.println("Thread 1 is running...");
});

Thread thread2 = new Thread(() -> {
    try {
        thread1.join(); // Wait for thread1 to complete
        System.out.println("Thread 2 is running after thread1 completes...");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

thread1.start();
thread2.start();

2. yield()

The yield() method is a hint to the scheduler that the current thread is willing to yield its current use of the processor. It allows the scheduler to select another thread to run instead of the current thread. However, yielding is not guaranteed to have any effect on thread execution order.

Example:

Thread thread1 = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
        System.out.println("Thread 1 is running...");
        Thread.yield(); // Yield to allow other threads to run
    }
});

Thread thread2 = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
        System.out.println("Thread 2 is running...");
        Thread.yield(); // Yield to allow other threads to run
    }
});

thread1.start();
thread2.start();

3. wait(), notify(), notifyAll()

These methods are used for inter-thread communication and synchronization using object monitors:

  • wait(): Causes the current thread to wait until another thread invokes the notify() or notifyAll() method for this object or a specified timeout expires.

  • notify(): Wakes up a single thread that is waiting on this object's monitor. If multiple threads are waiting, one of them is chosen to be awakened.

  • notifyAll(): Wakes up all threads that are waiting on this object's monitor. This method should be used to notify waiting threads if multiple threads may be waiting for the same condition.

Example:

class SharedObject {
    synchronized void method1() {
        System.out.println("method1 is executing...");
        try {
            wait(); // Thread waits until notified
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("method1 resumed...");
    }

    synchronized void method2() {
        System.out.println("method2 started...");
        notify(); // Notify one waiting thread
        // notifyAll(); // Notify all waiting threads
    }
}

public class WaitNotifyExample {
    public static void main(String[] args) {
        SharedObject sharedObject = new SharedObject();

        Thread thread1 = new Thread(() -> sharedObject.method1());
        Thread thread2 = new Thread(() -> sharedObject.method2());

        thread1.start();
        thread2.start();
    }
}

Other Methods

  • sleep(long milliseconds): Causes the current thread to sleep for the specified number of milliseconds. This method is used for pausing execution.

  • interrupt(): Interrupts the thread, causing it to exit from its waiting or sleeping state, throwing an InterruptedException if it's waiting.

  • isAlive(): Checks if the thread is alive (i.e., started and not yet terminated).

  • setDaemon(boolean on): Marks the thread as either a daemon thread (background thread) or a user thread. Daemon threads are terminated when all user threads have finished executing.

Different ways to stop or pause a thread

In Java, there are several ways to stop or pause a thread, each suited to different scenarios and requirements. Here are some common methods:

1. Thread.sleep(long milliseconds)

The Thread.sleep() method pauses the execution of the current thread for the specified number of milliseconds. It can be used to introduce delays or pause execution temporarily.

Example:

Thread thread = new Thread(() -> {
    try {
        System.out.println("Thread started...");
        Thread.sleep(2000); // Pause for 2 seconds
        System.out.println("Thread resumed after sleep...");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

thread.start();

2. Thread.yield()

The Thread.yield() method is a hint to the scheduler that the current thread is willing to yield its current use of the processor. It allows the scheduler to select another thread to run instead of the current thread. However, its effectiveness can vary across different JVM implementations.

Example:

Thread thread1 = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
        System.out.println("Thread 1 is running...");
        Thread.yield(); // Yield to allow other threads to run
    }
});

Thread thread2 = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
        System.out.println("Thread 2 is running...");
        Thread.yield(); // Yield to allow other threads to run
    }
});

thread1.start();
thread2.start();

3. Thread.interrupt()

The Thread.interrupt() method interrupts a thread that is currently in a waiting, sleeping, or blocking state. It causes the thread to throw an InterruptedException or wake up from sleep.

Example:

Thread thread = new Thread(() -> {
    try {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("Thread is running...");
            Thread.sleep(1000); // Thread continues to run until interrupted
        }
    } catch (InterruptedException e) {
        System.out.println("Thread interrupted...");
    }
});

thread.start();

// Interrupt the thread after 3 seconds
try {
    Thread.sleep(3000);
    thread.interrupt();
} catch (InterruptedException e) {
    e.printStackTrace();
}

4. Using a volatile flag or boolean variable

You can use a volatile boolean flag or variable to control the execution of a thread. The thread periodically checks the flag and exits or pauses based on its value.

Example:

class MyRunnable implements Runnable {
    private volatile boolean flag = true;

    public void stop() {
        flag = false;
    }

    @Override
    public void run() {
        while (flag) {
            System.out.println("Thread is running...");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        System.out.println("Thread stopped.");
    }
}

public class VolatileFlagExample {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();

        // Stop the thread after 5 seconds
        try {
            Thread.sleep(5000);
            myRunnable.stop();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

5. Using wait() and notify()

For more complex coordination between threads, you can use wait() and notify() methods for inter-thread communication and synchronization. This allows threads to pause and resume based on specific conditions.

Example:

class SharedObject {
    synchronized void method1() {
        System.out.println("method1 is executing...");
        try {
            wait(); // Thread waits until notified
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("method1 resumed...");
    }

    synchronized void method2() {
        System.out.println("method2 started...");
        notify(); // Notify one waiting thread
        // notifyAll(); // Notify all waiting threads
    }
}

public class WaitNotifyExample {
    public static void main(String[] args) {
        SharedObject sharedObject = new SharedObject();

        Thread thread1 = new Thread(() -> sharedObject.method1());
        Thread thread2 = new Thread(() -> sharedObject.method2());

        thread1.start();
        thread2.start();
    }
}

When to use the Runnable interface Vs Thread class?

Aspect

Runnable Interface

Extending Thread Class

Inheritance

Does not require extending a specific class

Requires extending the Thread class

Flexibility

Allows the class to extend another class if needed

Limits the class to only extending Thread

Code Reuse

Promotes better code organization and reusability

Limited reuse because the class extends Threaddirectly

Separation of Concerns

Separates thread logic from the thread object itself

Combines thread logic with the thread object

Multiple Inheritance

Allows implementing multiple interfaces

Does not support multiple inheritance

Thread Pooling

Better suited for use with thread pools and executors

Less flexible with thread pools and executors

Concurrency

Encourages better synchronization practices

Requires careful handling of thread synchronization

Common Practice

Preferred approach in modern Java programming

Older style, still used in certain scenarios

Difference between start() and run() method of thread class

Aspect

start() Method

run() Method

Invocation

Invoked to start the execution of a new thread

Contains the actual code to be executed by the thread

Execution Context

Executes in a new thread context

Executes in the current thread context

Method Signature

public void start()

public void run()

Concurrency

Initiates thread creation and scheduling

Does not create a new thread; runs in current thread

Thread Lifecycle

Starts the thread lifecycle (NEW -> RUNNABLE)

No effect on thread lifecycle

Overriding

Should not be overridden

Should be overridden to define thread's task

Calling Sequence

Called once per thread instance

Called when start() method is invoked

Execution Control

Returns immediately after starting the thread

Blocks until run() method completes

Use Case

Use to initiate concurrent execution

Contains the task to be executed by the thread

Example

thread.start();

public void run() { /* task implementation */ }

Difference between Multi-threading and Parallel processing?

The terms "multi-threading" and "parallel processing" are related to concurrent execution in computing but refer to distinct concepts:

Multi-threading:

  • Definition: Multi-threading refers to the concurrent execution of multiple threads within the same process.

  • Concurrency: Threads share the same memory space and resources of the process.

  • Execution: Threads are managed by the operating system's thread scheduler, which allocates CPU time to each thread.

  • Communication: Threads within the same process can communicate directly via shared memory.

  • Use Cases:

    • Enhancing responsiveness in GUI applications by offloading long-running tasks to background threads.

    • Improving performance by overlapping I/O operations with computation.

Parallel Processing:

  • Definition: Parallel processing involves executing multiple tasks simultaneously across multiple processors or cores to achieve faster computations.

  • Concurrency: Tasks are executed independently and concurrently on different processors.

  • Execution: Typically involves distributing tasks across multiple CPUs or cores to achieve performance gains.

  • Communication: Processes in parallel processing may communicate via inter-process communication mechanisms or shared data structures.

  • Use Cases:

    • Scientific computing and simulations where large datasets are processed concurrently.

    • Big data analytics, where tasks can be divided and processed across multiple nodes in a cluster.

Key Differences:

  • Concurrency vs. Parallelism:

    • Concurrency (multi-threading) focuses on managing multiple tasks (threads) that may be executed in overlapping time periods within the same process.

    • Parallelism involves simultaneous execution of multiple tasks across different processors or cores, aiming for faster computation.

  • Resource Utilization:

    • Multi-threading primarily optimizes CPU and I/O resource utilization within a single computing unit (e.g., a single machine or node).

    • Parallel processing utilizes multiple computing units (CPUs/cores) to divide and conquer tasks for higher throughput.

  • Communication Overhead:

    • Multi-threading benefits from low communication overhead as threads share memory space.

    • Parallel processing across multiple processors or nodes may involve higher communication overhead due to inter-process communication.

Example Scenario:

  • Multi-threading:

    • A web server handling multiple client requests concurrently using threads to manage each request's I/O and computation tasks.

  • Parallel Processing:

    • A data analytics platform processing vast amounts of data by distributing computation across multiple nodes in a cluster, leveraging parallelism to achieve faster data processing.

Explain the thread life cycle in Java.

The thread life cycle in Java describes the various states a thread transitions through during its execution. Here’s a concise explanation of the thread life cycle stages:

  1. New:

    • A thread begins its life cycle in the New state when an instance of the Thread class is created but start()method is not yet invoked.

  2. Runnable:

    • After invoking the start() method, the thread moves to the Runnable state.

    • In this state, the thread is ready to run, but it may not be currently executing due to CPU scheduling.

  3. Running:

    • The thread enters the Running state when the CPU scheduler selects it to execute.

    • It executes its task within this state until it voluntarily relinquishes CPU control or is preempted by a higher-priority thread.

  4. Blocked/Waiting:

    • A thread can transition to the Blocked or Waiting state under certain conditions:

      • Blocked: When waiting for a monitor lock to enter a synchronized block or method.

      • Waiting: When waiting indefinitely for another thread to perform a specific action, such as calling wait() or join() methods.

  5. Timed Waiting:

    • Threads enter the Timed Waiting state when they call methods like sleep() or join() with a timeout parameter.

    • They wait for the specified time period or until another thread notifies them.

  6. Terminated:

    • A thread completes its task and enters the Terminated state.

    • This happens when the run() method finishes execution or an unhandled exception terminates the thread.

What is Synchronization?

Synchronization in Java refers to the mechanism that controls access to shared resources or critical sections by multiple threads. It ensures that only one thread can access the shared resource at a time, preventing concurrent access that could lead to data inconsistency or corruption.

Advantages of Synchronization:

  1. Thread Safety: Synchronization ensures that shared resources are accessed in a mutually exclusive manner, preventing data races and maintaining data integrity.

  2. Consistency: It helps in maintaining consistency among shared data by enforcing a strict order of access, ensuring that changes made by one thread are visible to others.

  3. Prevents Deadlocks: Properly implemented synchronization techniques can prevent deadlock situations where two or more threads are blocked forever, waiting for each other to release resources.

  4. Coordination: It facilitates coordination between threads, allowing them to communicate effectively and synchronize their activities based on specific conditions.

Disadvantages of Synchronization:

  1. Overhead: Synchronization introduces overhead due to context switching and acquiring/releasing locks, which can impact performance, especially in highly concurrent applications.

  2. Potential Deadlocks: Improper use of synchronization primitives can lead to deadlocks, where threads are stuck indefinitely waiting for resources that are held by other threads.

  3. Complexity: Managing synchronization correctly requires careful attention to detail, as incorrect synchronization can lead to subtle bugs that are hard to detect and debug.

  4. Reduced Parallelism: Synchronization may limit parallelism in multi-core systems, as threads may need to wait for access to shared resources even when they could otherwise execute independently.

Example:

class Counter {
    private int count;

    // Synchronized method ensures atomicity and thread safety
    public synchronized void increment() {
        count++;
    }

    // Non-synchronized method for demonstration
    public void decrement() {
        count--;
    }
}

In the example above:

  • The increment() method is synchronized to ensure that only one thread can execute it at a time, preventing race conditions when modifying count.

  • The decrement() method is not synchronized, which could lead to data corruption if accessed concurrently by multiple threads without proper synchronization.

What is Volatile Variable and its purpose?

In Java, a volatile variable is a type of variable that ensures visibility and atomicity guarantees when accessed or modified by multiple threads. Its primary purpose is to provide a consistent view of the variable's value across all threads, without the need for synchronization mechanisms like locks or synchronized blocks.

Purpose of Volatile Variable:

  1. Visibility Guarantee:

    • When a variable is declared as volatile, any write to that variable is immediately visible to other threads. This ensures that changes made by one thread are immediately reflected in other threads.

  2. Atomicity on Writes:

    • Writing to a volatile variable is atomic. This means that operations on the variable are indivisible, and no other thread can observe an intermediate state during a write operation.

  3. Preventing Compiler Optimizations:

    • Accessing a volatile variable prevents the compiler and the JVM from applying certain optimizations that could reorder or cache the variable's access, ensuring the variable's updated value is always read from main memory.

When to Use Volatile Variables:

  • Flag Variables: Use volatile for boolean flags or state variables that control the execution of threads across multiple cores or threads.

  • Read-Modify-Write Operations: When performing read-modify-write operations (e.g., incrementing a counter), using volatile ensures atomicity without explicit synchronization.

  • Status Flags: For variables used to signal state changes across threads, such as status updates or termination signals.

Example:

public class SharedResource {
    private volatile boolean flag = false;

    public void setFlag(boolean value) {
        this.flag = value;
    }

    public void doWork() {
        while (!flag) {
            // Perform work while flag is false
        }
        // Exit loop when flag becomes true
    }
}

In this example:

  • The flag variable is declared as volatile to ensure that changes made to flag in one thread are immediately visible to other threads.

  • The doWork() method continuously checks the flag variable's value without the need for explicit synchronization, relying on the visibility guarantee provided by volatile

PreviousSet 1NextJava Code Snippets

Last updated 3 months ago

Was this helpful?