Monday, July 4, 2022

Map implementations

  • HashTable
  • HashMap
  • IdentityMap
  • EnumMap
  • ConcurrentHashMap
  • LinkedHashMap
  • TreeMap
  • WeakHashMap
  • Collections.SynchronizedMap
Youtube : link

Wednesday, June 29, 2022

Core Java Concepts

 Cloning In Java

  • Shallow copy vs Deep copy
  • Techniques to achive
    • Object clone method
    • Copy contstructor
    • Third party tools - Apache common langs, Google gson, Jackson
References :
Copy contrcutor - link
Deep copy - link
Difference between Shallow vs Deep - link
Dzone article - link

Immutable Object

An immutable object is an object whose internal state remains constant after it has been entirely created.

Note that final only forbids us from changing the reference the variable holds, it doesn't protect us from changing the internal state of the object it refers to by using its public API:

How to make immutable object
  • declare the class as final so it cannot be extended
  • all class members should be private so they cannot be accessed outside of class
  • shouldn't contain any setter methods to change the value of class members
  • the getter method should return the copy of class members
  • class members are only initialized using constructor
Reference
Baeldung : link
Other - link

Java Generics

Difference between : List <? extends Number> vs List <T extends Number>
Stackoverflow : link

Java Serialization

  • Classes that are eligible for serialization need to implement a special marker interface, Serializable. 
  • static fields belong to a class and are not serialized
  • we can use the keyword transient to ignore class fields during serialization
  • Inheritance : When a class implements the java.io.Serializable interface, all its sub-classes are serializable as well
  • Composition : when an object has a reference to another object, these objects must implement the Serializable interface separately, or else a NotSerializableException will be thrown:
  • Serial Version UID
    • The JVM associates a version (long) number with each serializable class
    • We use it to verify that the saved and loaded objects have the same attributes, and thus are compatible on serialization.
    • Any changes result in a different number, and can cause an InvalidClassException
    • If a serializable class doesn't declare a serialVersionUID, the JVM will generate one automatically at run-time. However, it's highly recommended that each class declares its serialVersionUID, as the generated one is compiler dependent and thus may result in unexpected InvalidClassExceptions.
    • If you're actually using serialization, it only matters if you plan on storing and retrieving objects using serialization directly. The serialVersionUID represents your class version, and you should increment it if the current version of your class is not backwards compatible with its previous version.
    • it is good practice to provide the serialVersionUID value and update it after changes to the class so that we can have control over the serialization/deserialization processReferences :
Baeldung : link1link2
Stackoverflow : link


Integer Cache

  • Integer Cache was introduced in Java 5 in order to improve memory management.
  • Integer Cache works only on auto boxing which means Conversion from a primitive type to an object reference 
  • By default keeps cache of range between -128 to 127. But this can be increased with
    -XX: AutoBoxCacheMax=size parameter
  • Integer cache gives you the facility to cache other objects also for Example like Byte, Short, Long, Character etc.
Code example
Integer a = 1000, b = 1000;  
System.out.println(a == b); // false  
Integer c = 100, d = 100;  
System.out.println(c == d); // true

References

Geek : link
Medium :  link

Comparing Doubles

  • it isn't as easy as comparing other primitive types
  • As a matter of fact, it's problematic in many other languages, not only Java.
  • Inaccuracy with comparisons using the == operator is caused by the way double values are stored in a computer's memory.
  • we can't have an exact representation of most double values in our computers. They must be rounded to be saved
  • The recommended algorithm to compare double values in plain Java is a threshold comparison method. In this case, we need to check whether the difference between both numbers is within the specified tolerance, commonly called epsilon:
    double epsilon = 0.000001d;
    assertThat(Math.abs(d1 - d2) < epsilon).isTrue();
  • The smaller the epsilon's value, the greater the comparison accuracy. However, if we specify the tolerance value too small, we'll get the same false result as in the simple == comparison. In general, epsilon's value with 5 and 6 decimals is usually a good place to start.
  • Third party libraries to compare doubles : Apache Commons Math, Guava, Junit
References :
Baeldung : link

How to lose object in Map?

  • Equals and hashCode methods implemented by keys are mutable
  • Solution : to make keys immutable. If not possible,  make sure keys are not changed
Reference

Blog : link

BitSet

  • we can use BitSets to represent a vector of bits
  • similar to boolean[] but takes less memory
  • new boolean[1024] take 1 MB
  • new BitSet(1024) takes 1024 bit, 168 bytes  which is 130 KB 
Reference
Baeldung : link
















Sunday, June 19, 2022

Spring Concepts

 Bean Scopes

  • Singleton
  • Prototype
  • Request
  • Session
  • Application
  • WebSocket
Reference : link

Injecting dependencies

  1. Constructor based
  2. Setter based
  3. Field based
    • This approach might look simpler and cleaner, but we don't recommend using it because it has a few drawbacks such as:
      • This method uses reflection to inject the dependencies, which is costlier than constructor-based or setter-based injection.
      • It's really easy to keep adding multiple dependencies using this approach. If we were using constructor injection, having multiple arguments would make us think that the class does more than one thing, which can violate the Single Responsibility Principle.
Reference : link

Injecting Prototype into Singleton

  • Every request to get prototype object from singleton bean will return same instance of prototype
  • In order to return different prototype bean there are different ways
    • Injecting ApplicationContext
    • Method Injection with @Lookup annotation
    • javax.inject API  
Reference  : link


Using bean outside of Spring context 

  • Implement ApplicationContextAware 
  • Inject into static field
  • Then call context.getBean method
public class ApplicationContextUtils implements ApplicationContextAware {
  private static ApplicationContext ctx;

 private static final String USER_SERVICE = "userServiceBean";

  @Override
  public void setApplicationContext(ApplicationContext appContext)
      throws BeansException {
    ctx = appContext;
  }

  public static ApplicationContext getApplicationContext() {
    return ctx;
  }

  public static UserService getUserService(){ 
return ctx.getBean(USER_SERVICE);
}
}

Reference : Stackoverflow
Reference  : link

BeanFactory vs ApplicationContext

  • BeanFactory loads beans on demand (Lazy loading)
  • ApplicationContext loads all beans at startup (Easger loading)
  • BeanFactory only when memory consumption is critical
  • ApplicationContext provides
    • Annotation based dependency injection
    • Event publication
    • Messaging (i18n)
    • Easy integration with Spring AOP feature
Reference : Baeldung


@ExceptionHandler and Global Handler

Reference : Baeldung


@Autowire

  • Allows Spring to resolve and inject collaborating beans into our bean
  • by declaring all the bean dependencies in a Spring configuration file, Spring container can autowire relationships between collaborating beans. This is called Spring bean autowiring
  • Resolving bean conflicts using @Qualifier annotation
  • @Qualifier helps to avoid ambiguity
  • @SpringBootApplication -  is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScan. When we run Spring Boot application, it will automatically scan the components in the current package and its sub-packages. Thus it will register them in Spring's Application Context, and allow us to inject beans using @Autowired.
  • We can use autowiring on properties, setters, and constructors
  • @Autowired(required = false) - makes bean optional. Otherwise throws NoSuchBeanDefinitionException 
Reference :  link

Design Patterns in Spring

  • Singleton - The singleton pattern is a mechanism that ensures only one instance of an object exists per application. This pattern can be useful when managing shared resources or providing cross-cutting services, such as logging. By default, Spring creates all beans as singletons.
  • Factory Method pattern - The factory method pattern entails a factory class with an abstract method for creating the desired object. For example : BeanFactory, ApplicationContextFactory are factory patterns
  • Proxy - Proxies are a handy tool in our digital world, and we use them very often outside of software (such as network proxies). In code, the proxy pattern is a technique that allows one object — the proxy — to control access to another object — the subject or service. For example : @Transactioin annotation is creating proxy object
  • Template - In many frameworks, a significant portion of the code is boilerplate code. For example, when executing a query on a database, the same series of steps must be completed:  Establish a connection, Execute query, Perform cleanup, Close the connection - These steps are an ideal scenario for the template method pattern.
    The template method pattern is a technique that defines the steps required for some action, implementing the boilerplate steps, and leaving the customizable steps as abstract. 
    For example : JDBC template, JMS, JPA templates 
Reference : link

Spring Events

  • The event class should extend ApplicationEvent if we're using versions before Spring Framework 4.2. As of the 4.2 version, the event classes no longer need to extend the ApplicationEvent class.
  • The publisher should inject an ApplicationEventPublisher object.
  • The listener should implement the ApplicationListener interface.
  • We can write our Custom events
  • Spring allows us to create and publish custom events that by default are synchronous. This has a few advantages, such as the listener being able to participate in the publisher’s transaction context.
  • In some cases, publishing events synchronously isn't really what we're looking for — we may need async handling of our events.We can turn that on in the configuration by creating an ApplicationEventMulticaster bean with an executor. The event, the publisher and the listener implementations remain the same as before, but now the listener will asynchronously deal with the event in a separate thread.
  • Existing framework events - ContextRefreshedEvent, ContextStartedEvent, RequestHandledEvent etc
Reference  - link

@Async

  • annotating a method of a bean with @Async will make it execute in a separate thread. In other words, the caller will not wait for the completion of the called method.
  • enabling asynchronous processing with Java configuration.by adding the @EnableAsync to a configuration class
  • Additional options : 
    • annotation – By default, @EnableAsync detects Spring's @Async annotation and the EJB 3.1 javax.ejb.Asynchronous. We can use this option to detect other, user-defined annotation types as well.
    • mode indicates the type of advice that should be used — JDK proxy based or AspectJ weaving.
    • proxyTargetClass indicates the type of proxy that should be used — CGLIB or JDK. This attribute has effect only if the mode is set to AdviceMode.PROXY.
    • order sets the order in which AsyncAnnotationBeanPostProcessor should be applied. By default, it runs last so that it can take into account all existing proxies.
  • @Async has two limitations
    • It must be applied to public methods only
    • Self-invocation — calling the async method from within the same class — won't work.
      The reasons are simple: The method needs to be public so that it can be proxied. And self-invocation doesn't work because it bypasses the proxy and calls the underlying method directly.
  • Methods With Void Return Type
  • Methods With Return Type - by wrapping the actual return in the Future
  • By default, Spring uses a SimpleAsyncTaskExecutor to actually run these methods asynchronously. But we can override the defaults at two levels: the application level or the individual method level.
    • Override the Executor at the Method Level
    • Override the Executor at the Application Level
  • Exception Handling -When a method return type is a Future, exception handling is easy. Future.get() method will throw the exception. But if the return type is void, exceptions will not be propagated to the calling thread. So, we need to add extra configurations to handle exceptions.
    • create a custom async exception handler by implementing AsyncUncaughtExceptionHandler interface
    • handleUncaughtException() method is invoked when there are any uncaught asynchronous exceptions
    • override the getAsyncUncaughtExceptionHandler() method to return our custom asynchronous exception handler
Reference : link

Hiberante

 Map entity to multiple tables

  • Annotate table with @SecondayTable(name ="author_details") annotation.
  • Provide table name in @Column(table ="author_details")  annotation
  • Benefit to split entity and its details into separate tables. Like author and author details
    Reference

Difference between First level and Second Level cache


KeyFirst level cacheSecond level cache


Basic 

First level cache is a session level 

cache and it is always associated with 

session level object

Second level cache is session factory level 

cache and it is available across all sessions


Enabled 

It is enabled by default.

It is not enabled by default.


Availability 

It is available for a session 

It is available across all session.


Configuration 

No Extra configuration required 

We have to decide  which
concurrency strategy to use and
also need to configure cache
expiration 
and physical cache attributes.


Different Entity states in JPA and Hibernate
























N+1 Problem

  • there is car and wheel table --> SELECT * FROM Cars;
  • in order to fetch wheel car we will hit db  --> SELECT * FROM Wheel WHERE CarId = ?
  • Solution to this JOIN tables (or Entity Graph)

Reference : Stackoverflow
Reference : Entity Graph 


Hibernate Fetch types

  • FetchMode JOIN : Eager loading which loads all the collections and relations at the same time.
  • FetchMode SELECT(default) : Lazy loading which loads the collections and relations only when required.
  • FetchMode SELECT with Batch Size : Fetch upto “N”collections or entities(“Not number of records”)
  • FetchMode SUBSELECT : Group the collection of an entity into a Sub-Select query.
Reference : link
Reference : Baeldung

Load() vs Get()

load()get()
Only use load() method if you are sure that the object exists.If you are not sure that the object exist, then use one of get() methods.
load() method will throw an exception if the unique id is not found in the database.get() method will return null if the unique id is not found in the database.
load() just returns a proxy by default and database won't be hit until the proxy is first invoked.get() will hit the database immediately.

Reference : link

Dirty Checking

  • Hibernate has a feature of checking all managed entity properties. Whenever an entity is loaded through hibernate, it makes an additional copy of that whole entity object along with the all entity's property values
  • So even if only one property of the persistent object is changed, Hibernate will still check all managed entities. It detects which objects have been modified and then calls update statements on all updated objects.
  • Hibernate monitors all persistent objects. At the end of a unit of work, it knows which objects have been modified. Then it calls update statement on all updated objects. This process of monitoring and updating only objects that have been changed is called automatic dirty checking in hibernate.
  • Within the Persistence Context, Hibernate has a copy of all persistent objects that were loaded from the database. It compares these persistent objects with these objects to detect the objects that have been modified or are dirty. This is the default implementation.
Reference : link

Query Cache and Second Level Cache

Second level cache look likes(key value)
*---------------------------------------------*
|          Person Data Cache                     |
|----------------------------------------------|
| 1 -> [ "John" , "Q" , "Public" , null ]   |
| 2 -> [ "Joey" , "D" , "Public" ,  1   ]    |
| 3 -> [ "Sara" , "N" , "Public" ,  1   ]    |
*---------------------------------------------*

Query cache look likes (key value)
*-------------------------------------------------------------------- *
|                       Query Cache                                                 |                     
|----------------------------------------------------------|-----------
| ["from Person where firstName=?", ["Joey"] ] -> [1, 2] ]  |
*---------------------------------------------------------------------*

What is the relation between the two caches?
  • If a query under execution has previously cached results, then no SQL statement is sent to the database. Instead the query results are retrieved from the query cache, and then the cached entity identifiers are used to access the second level cache.
  • If the second level cache contains data for a given Id, it re-hydrates the entity and returns it. If the second level cache does not contain the results for that particular Id, then an SQL query is issued to load the entity from the database.
Reference : link


Hibernate Inheritance Mapping 

  • MappedSuperclass – the parent classes, can't be entities
  • Single Table – The entities from different classes with a common ancestor are placed in a single table.
  • Joined Table – Each class has its table, and querying a subclass entity requires joining the tables.
  • Table per Class – All the properties of a class are in its table, so no join is required.
Reference : link


Monday, June 13, 2022

Spring Transaction Management

 

  • Transaction Propagation : Propagation defines our business logic's transaction boundary. Spring manages to start and pause a transaction according to our propagation setting. (in other words  : Defines how transactions relate to each other)
    • REQUIRED : Code will always run in a transaction. Creates a new transaction or reuses one if available.
    • REQUIRED_NEW : Code will always run in a new transaction. Suspends the current transaction if one exists.
    • SUPPORTS
    • MANDATORY
    • NEVER
    • NOT_SUPPORTED
    • NESTED

  • Transaction  Isolation :  solation is one of the common ACID properties: Atomicity, Consistency, Isolation, and Durability. Isolation describes how changes applied by concurrent transactions are visible to each other. (in other words :  Defines the data contract between transactions)
    Isolation Levels
    • DEFAULT 
    • READ_UNCOMMITTED : Allows dirty reads
    • READ_COMMITTED :  Does not allow dirty reads
    • REPEATABLE_READ : If a row is read twice in the same transaction, the result will always be the same 
    • SERIALIZABLE : Performs all transactions in a sequence
Each isolation level prevents zero or more concurrency side effects on a transaction:
  • Dirty read: read the uncommitted change of a concurrent transaction
  • Nonrepeatable read: get different value on re-read of a row if a concurrent transaction updates the same row and commits
  • Phantom read: get different rows after re-execution of a range query if another transaction adds or removes some rows in the range and commits

  • References

    Baeldung : link 

    Stackoverflow : link

    Transactions with Spring and JPA : link


    Saturday, June 11, 2022

    Design Patterns - Singleton


    • Eager - thread safe but can be broken with below techniques
      • reflection
      • object cloning
      • serialization/deserialization
    • Lazy - in multithread environment can be archived with below techniques
      • synchronize whole method
      • Double checked locking - synchronize inside method + volatile
      • Bill Pugh method - static Holder Class
      • Enum method

    Referances

    Singleton all scenarios : link  

    Baeldung : link 

    Saturday, March 12, 2022

    Spring Web MVC

    Front Controller

    the concept of the Front Controller in the typical Spring Model View Controller architecture

    At a very high level, here are the main responsibilities we're looking at:

    • Intercepts incoming requests
    • Converts the payload of the request to the internal structure of the data
    • Sends the data to Model for further processing
    • Gets processed data from the Model and advances that data to the View for rendering


    • DispatcherServlet plays the role of the Front Controller in the architecture.
    • The diagram is applicable both to typical MVC controllers as well as RESTful controllers
    • MVC applications are not service-oriented hence there is a View Resolver that renders final views based on data received from a Controller
    • RESTful applications are designed to be service-oriented and return raw data (JSON/XML typically). Since these applications do not do any view rendering, there are no View Resolvers – the Controller is generally expected to send data directly via the HTTP response

    MVC Controller : 

    @Controller
    @RequestMapping(value="Test")
    public class TestController{
    .....
    }

    Rest Controller :

    Maven Dependencies :  spring-web,  spring-webmvc,  jackson-databind

    @Controller
    public class TestController{
       @GetMapping(value = "/student/{studentId}")
        public @ResponseBody Student getTestData(@PathVariable Integer studentId) {
            Student student = new Student();
            student.setName("Peter");
            student.setId(studentId);

            return student;
        } 
    }
    @ResponseBody annotation on the method – which instructs Spring to bypass the view resolver and essentially write out the output directly to the body of the HTTP response.

    Spring Boot - @RestController

    @RestController
    public class RestAnnotatedController {
        @GetMapping(value = "/annotated/student/{studentId}")
        public Student getData(@PathVariable Integer studentId) {
            Student student = new Student();
            student.setName("Peter");
            student.setId(studentId);

            return student;
        }
    }
    @RestController annotation from Spring Boot is basically a quick shortcut that saves us from always having to define @ResponseBody. Help by pass view rendering stage and directly writing response to HTTP response body

    @RequestMapping
    the annotation is used to map web requests to Spring Controller methods

    Example 1 : Request Mapping with by path and HTTP method

    @RequestMapping(value = "/ex/foos", method = POST)
    @ResponseBody
    public String postFoos() {
        return "Post some Foos";
    }


    Example 2 : Request Mapping and HTTP header

    @RequestMapping(
      value = "/ex/foos", 
      headers = { "key1=val1", "key2=val2" }, method = GET)
    @ResponseBody
    public String getFoosWithHeaders() {
        return "Get some Foos with Header";
    }


    Example 3 : Mapping media types produced and consumed by controller

    @RequestMapping(value="/method6",
    produces={"application/json","application/xml"},
    consumes="text/html")
    @ResponseBody
    public String method6(){
    return "method6";
    }
    Above method can consume message only with Content-Type as text/html and is able to produce messages of type application/json and application/xml.


    Example 4 : Request Mapping with Path Variable

    @RequestMapping(value = "/ex/foos/{fooid}/bar/{barid}", method = GET)
    @ResponseBody
    public String getFoosBySimplePathWithPathVariables
      (@PathVariable long fooid, @PathVariable long barid) {
        return "Get a specific Bar with id=" + barid + 
          " from a Foo with id=" + fooid;
    }

    Example 5 : Request Mapping with Request Parameters

    @RequestMapping(value = "/ex/bars", method = GET)
    @ResponseBody
    public String getBarBySimplePathWithRequestParam( @RequestParam("id") long id) {
        return "Get a specific Bar with id=" + id;
    }

    http://localhost:8080/spring-rest/ex/bars?id=100

    Example 6 :  Request Mapping with Fallback

    @RequestMapping(
      value = "*", 
      method = { RequestMethod.GET, RequestMethod.POST ... })
    @ResponseBody
    public String allFallback() {
        return "Fallback for All Requests";
    }

    @RequestMapping New Shortcut Annotations

    • @GetMapping
    • @PostMapping
    • @PutMapping
    • @DeleteMapping
    • @PatchMapping



    Reference 1 :  Baeldung
    Reference 2 :  Journal Dev


    Saturday, February 19, 2022

    Object Oriented Programming

     Advantages of OOP :

    • Reusability
    • OOPs is very helpful in solving very complex level of problems.
    • Highly complex programs can be created, handled, and maintained easily using object-oriented programming.
    • OOPs, promote code reuse, thereby reducing redundancy.
    • OOPs also helps to hide the unnecessary details with the help of Data Abstraction.
    • OOPs, are based on a bottom-up approach, unlike the Structural programming paradigm, which uses a top-down approach.
    • Polymorphism offers a lot of flexibility in OOPs.

    Properties of OOP :

    • Encapsulation
    • Data abstraction
    • Polymorphism 
    • Inheritance 

    Encapsulation vs Data Abstraction

    Encapsulation is the packing of "data" and "functions operating on that data" into a single component and restricting the access to some of the object's components. Encapsulation means that the internal representation of an object is generally hidden from view outside of the object's definition.

    Abstraction is a mechanism which represent the essential features without including implementation details.

    Encapsulation:-- Information hiding.
    Abstraction:-- Implementation hiding.


    Polymorphism 

    Polymorphism is composed of two words - “poly” which means “many”, and “morph” which means “shapes”. Therefore Polymorphism refers to something that has many shapes.

    Types of Polymorphism 




    Compile time polymorphism : method overloading

    Runtime polymorphism : method overriding 


    Reference :

    Thursday, May 28, 2020

    Java Multithreading


    Why we need Threads?

    1.  Responsiveness - can be achieved with Concurrency (Multitasking)
    2.  Performance      - can be achieved with Parallelism



    Context Switching
    •  Context switching is expensive 
    •  Context switching between threads is a lot cheaper than context switching between processes
    •  Too many threads - OS spending more time in management than real productive work
    •  Thread consuming less resources than processes.

    Thread scheduling 
    • There are different possible of ways to schedule
      • First Come First Serve - problem with that if long threads come first other thread will be unresponsiveness, it is called starvation  
      • Short Job First - this time longest job will wait
      • Epochs -  OS divides CPU time to moderately sized pieces called Epochs.  OS allocates different time for each thread in each Epoch. It is done according to Dynamic Priority calculations. 
    Thread creation & it's methods
    • Two way of creating threads
      • Implement Runnable interface provide in construction of Thread object
      • Extend Thread object
    • Number of threads should be equal to number of cores in machines
    • Use thread.setUncaughtExceptionHandler  to catch unchecked exceptions during run-time.
      You can either clean up resources or log the issue for trouble shooting purposes
    • Stopping thread from another thread has two ways
      • Thread.interrupt() - you can interrupt the thread in two scenarios
        1. If the thread is executing a method that throws an InterruptedException
        2. If the thread code is handing the interrupt signal explicitly
      • Daemon threads - background threads that do not prevent the application from exiting if the main thread terminates. Other reason , code in a worked thread is not under our control, and we do not want it to block our application from terminating
    • By default, at least if one thread is running application will not stop even main thread stopped. So we need to stop all threads gracefully
    • Thread.join() 
      • calling the join() method has a synchronization effect. join() creates a happens-before relationship
      • Happens-before :  This means that when a thread t1 calls t2.join(), then all changes done by t2 are visible in t1 on return. However, if we do not invoke join() or use other synchronization mechanisms, we do not have any guarantee that changes in the other thread will be visible to the current thread even if the other thread has completed.
      • When we invoke the join() method on a thread, the calling thread goes into a waiting state. It remains in a waiting state until the referenced thread terminates.
      • Timed join() is dependent on the OS for timing. So, we cannot assume that join() will wait exactly as long as specified.
    • In order to avoid creation/destroy of threads there is thread pooling mechanisms.

    Data Sharing between Threads
    • Thread local variables are stored in stack . Like local variable and local object references
    • Shared information stored in Heap. Like Objects, class members and static variables
    • Critical section guarded with synchronized keyword. Two ways of doing this
      • synchronized on method level - Monitor

      • synchronized inside method with explicit object - lock


      • Re-entrant - thread in synchronized method/section can access to other synchronized method/section  



    Atomic Operations
    • Object reference assignment - including getter, setter for exmaple
    • Primitive type assignments except long and double. Because long and double 64 bit long 
    • We can define long and double volatile.  With volatile they are guaranteed in single HW operation
    • Knowledge of atomic operations is key to us create high performance applications 

    Concurrency problems
    • Race condition : two threads working on same shared object. One of them modifying the object , due to OS scheduling  it may cause incorrect results. Core of the problem is non-atomic operation performed on shared object . Solution - identifying  the critical section where race condition happened and protecting with  synchronized block.
      https://stackoverflow.com/questions/34510/what-is-a-race-condition
    • Data race : solution, establish happens-before semantics by one of these methods
      • synchronization of method
      • using volatile. No compiler re-ordering will happen. whatever code before and after volatile will run as is.
    Locking Strategies
    • Coarse-grained strategy : lock whole object. Might impact the performance
    • Fine-grained strategy  : lock party of shared objects using lock object

    Deadlock 
    • Condition to leads to deadlock
      • Mutual exclusion
      • Hold and wait
      • Non-preemptive allocation 
      • Circular wait
    • Solution to deadlock is avoid one the conditions mentioned above
      • Avoid circular wait - this one easiest one. 
    • Deadlock detection
      • Watchdog
      • Thread interruption 
      • tryLock operation
    Reentrant Lock
    •  Similar locking with synchronized locking but provides more control over lock with advanced operations
    •  Pattern to use it
      class SharedData{
         private Lock lockObject = new ReenterantLock();

         public void method(){
              lockObject.lock();
              try{
                   userSharedObject();
             }finally(){
                  lockObject.unlock();
              } 
         }
      }
    • In order to avoid starvation - one thread is continuously using shared object but other are waiting - you can set true into constructor of  ReenterantLock(true) object. which is fairness flag. But this one comes with cost. Use only when you really need it.
    • ReenterantLock.lockInterrupility()
    • ReenterantLock.tryLock()
    • ReenterantReadWriteLock - if our shared object is read intensive we can use it otherwise it can perform worse then traditional locks. Example of using read-write lock is caching where system is read intensive. Multiple read threads can access the shared object and lock it, we can see number of concurrent read threads. Only one write thread can lock the shared object no other write/read threads can access during write lock. 
    Semaphore
    • Can restrict number of threads accessing to shared data.
    • similar to lock but different in many ways. 
    • One use case if Producer-Consumer using semaphore. Producer-consumer pattern used in web sockets, video streaming, Actor models
    Condition variable


    Other methods
    • wait
    • notify() and notifyAll()
    Lock free programming
    • AtomicInteger, AtomicLong...
    • AtomicReferences




    Tuesday, May 26, 2020

    Java Exceptions



    • All RuntimeExceptions are unchecked exceptions rest of them are checked exceptions
    • Always use try-with-resource. In order to use objects  should implement AutoClosable
    • Exceptions are very slowly. Code running inside try-catch is performing slowly. If you have chance just use simple test (like if(!s.empty) s.pop() ) rather then guarded section
    • Throw early, catch late






    Sources :




    Java hashCode()

    • Objects that are equal must have the same hash code within a running process
    • Whenever you implement equals, you MUST also implement hashCode
    • Whenever two different objects have the same hash code, we call this a collision.
    • A collision is nothing critical, it just means that there is more than one object in a single
      bucket, so a HashMap lookup has to look again to find the right object. A lot of collisions will degrade the performance of a system, but they won’t lead to incorrect results.
    • It is good to generate same hash code in different execution of programs but you should not relay on this. String and Integer are generating same hash code always will be same.But while most of the hashCode implementations provide stable values, you must not rely on it.here are Java libraries that actually return different hashCode values in different processes and this tends to confuse people. Google’s Protocol Buffers is an example.
    • Do not use hashCode in distributed applications
    • You may know that cryptographic hash codes such as SHA1 are sometimes used to identify objects (Git does this, for example). Is this also unsafe? No. SHA1 uses 160-bit keys, which makes collisions virtually impossible. Even with a gigantic number of objects, the odds of a collision in this space are far below the odds of a meteor crashing the computer that runs your program. This article has a great overview of collision probabilities.
    • A cryptographic hash such as MD5 or SHA-1 would be ok for many cases, but might be a bit heavyweight if you’re dealing with a really high-throughput service.

    Sources


    How does HashMap works in Java

    • Array created with default capacity of 16
    • Then getting hash code of the key
    • It rehashes the hash code to prevent against a bad hashing function from the key that would put all data in the same index (bucket) of the inner array
    • It takes the rehashed hash hashcode and bit-masks it with the length (minus 1) of the array. This operation assures that the index can’t be greater than the size of the array. You can see it as a very computationally optimized modulo function.

    • Finding appreciate array index according to hash code and saving in bucket associated with this index
    • In Java 8 , if bucket size more than 8 automatically converting that bucket from linked list to read black tree
    • Can auto size the map according to load factor. Initial arrays size is 16 and load factor is 0.75
    • HashMap is not thread safe but HashTable is thread safe but locks whole data structure during concurrent access.  On the other hand , ConcurrentHashMap is locking only bucket
    • Mostly Integer and String used as map key because they immutable and provide string hash code function
    • If you have too many data to put on Map , it is advisable to create map with approximate high initial capacity. Because there is additional overhead of shrinking the map


    Youtube : link




    Java Collections





    Iterable Interface

    The Iterable interface is the root interface for all the collection classes because the Collection interface extends the Iterable interface, therefore, all the subclasses of Collection interface also implement the Iterable interface.
    The iterable interface contains only one abstract method.
    • Iterator iterator(): It returns the iterator over the elements of type T.

    Iterator Interface

    The iterator interface provides the facility of iterating the elements in a forward direction only.

    public interface Iterator<E>{
            E next();     
            boolean hasNext();
            void  remove();
            default void forEachRemaining(Consumer<? super E> action);
    }

    Collection Interface

    The Collection interface builds the foundation for the Collection framework. The collection interface is one of the interfaces which is implemented by all the Collection framework classes. It provides common methods to implement by all the subclasses of collection interfaces.
    public interface Collection<E>{

            boolean add(E element)
            Iterator<E>  iterator()  
           int size()boolean isEmpty()
           boolean contains(Object obj)
           boolean containsAll(Collection<?> c)
           boolean equals(Object other)
    boolean addAll(Collection<? extends E> from)
           boolean remove(Object obj)
           boolean removeAll(Collection<?> c)
           void clear()
    boolean retainAll(Collection<?> c)
           Object[] toArray()
           <T> T[] toArray(T[] arrayToFill)   
            ...............
    }


    Concrete Collections


    List Interface

    ArrayList and LinkedList implements this interface.  get and set methods can be works  different  in 

    terms of performance due to nature of array and list data structure. Java language designer added

    RandomAccess tagging interface in order to distinguish between these two

    public interface List<E>{
            void add(int index, E element)
    void remove(int index)
    E get(int index)
    E set(int index, E element)
    }



    Set Interface

    * Usually implemented by HashSet and TreeSet classes
    * TreeSet visits elements in sorted order
    * In HashSet if someone providing poor hashing algorithm then it can be slower. On the other hand TreeSet performance guaranteed. But you have to provide Compactor or implement compareTo method  

    Queue  Interface

    * Queue let you efficiently add at the tail and remove from head
    * Deque can add/remove on both ends
    * Priority Queue  isn't queue 
        -  doesn't remember in which order elements were added
        -  when removed , highest priority elements were removed
        -  useful for work scheduling 




    Concurrent Modification
    Suppose one iterator traverses a collection and  another modifies the collection by add/removing the

    element. in the case of linked list , that won't work - the links will not be consistent. Linked list

    detects the concurrent modification and throws ConcurrentModificationException

    In order to understand to which collection have modification count you need to check the java API

    documentation.  This is also sometimes called fail-fast

    Reference - 1

    Reference - 2 


    Maps

    * HashMap hashes the keys, TreeMap organizes them in sorted order
    * map.get(id) can return null if not exists. Then you need to check the value. In order to avoid you can use map.getOrElse(id, $value) if key absent returns $value

    * Easiest way to iterate over map : map.forEach ( (k,v)-> doSomething ) 

    * Updating map entries
    • map.put(word, map.get(word) +1 )
    • If key is not present then you can use map.put(word, map.getOrDefault(word,0 ) + 1 )
    • map.putIfAbsent(word, 0) then map.put(word, map.get(word) +1)
    • map.merge(word, 1 , Integer::sum)  If word wasn't present, put 1 . Otherwise , put them sum of 1 and previous value
    • Efficient map.forEach( (k,v) -> do something with k,v )
    * LinkedHashMap traverses the entries in the other which they were added

    Views

    * A view implements a collection interface without storing the elements. Examples :

      Collection<String> greetings = Collections.nCopies(100,"Hello");  // create illusion of 100 hellos

      Collection<String> greetings = Collections.singletion("Helllo");

      Collection<String> greetings = Collections.emptySet();

      List<Employee> list = staff.subList(10,20);

    Restricted Views

    Collections.unmodifiableCollection
    Collections.unmodifiableList
    Collections.unmodifiableSet
    Collections.unmodifiableSortedSet
    Collections.unmodifiableNaviagableSet
    Collections.unmodifiableMap

    * look but don't touch
    * Synchronized views for safe concurrent access. But you should use  a thread safe collection instead.


      







    Practical

    List<String> names = Arrays.asList("A", "B", "C");

    In Java - 7
    List<Integer> digits = [1,2,3,4,5,6];   
    Set<Integer> digits = {1,2,3,4,5,6};

    In Java -9
    List<Integer> digits = List.of(1,2,3,4,5,6);   

    Set<Integer> digits =  Set.of(1,2,3,4,5,6);


    Map<Integer, String> map  = {4 : "ab", 5 : "bc", 6 : "ce"};
    In Java -9
    Version 1  : 
    Map<Integer, String> map  = Map.of(4 , "ab", 5 , "bc", 6 , "ce");
    OR
    Version -2 : 
    import static java.util.Map.*
    map = ofEnteries( entry(4,"a") ,   entry(5,"b") , entry(6,"d") )
    * Version 1 works only if you have less than 10 elements

    Collection to Arrays
    String[] names = collection.toArray( new String[collection.size()]);

    References 

    Book :  Core Java 11 Fundamentals, Second Edition by Cay S. Horstmann