@FunctionalInterface

An interface with only one abstract method is called Functional Interface

 

 

public static void main(String[] args) {
   
tentimes(inputPrm - > System.out.println(inputPrm));
   
//tentimes(System.out::println);  // You can also replace lambda with static method reference
}

public static void tentimes(Consumer myFunction) {
   
for (int i = 0; i < 10; i++)
       
myFunction.accept("hello");
}

 

 

Stream In Java

 

stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result.

 

Intermediate Operations:

1.     map: The map method is used to map the items in the collection to other objects according to the Function passed as argument.
List number = Arrays.asList(2,3,4,5);
List square = number.stream().map(x->x*x).collect(Collectors.toList());

2.     filter: The filter method is used to select elements as per the Predicate passed as argument.
List names = Arrays.asList("Reflection","Collection","Stream");
List result = names.stream().filter(s->s.startsWith("S")).collect(Collectors.toList());

3.     sorted: The sorted method is used to sort the stream.
List names = Arrays.asList("Reflection","Collection","Stream");
List result = names.stream().sorted().collect(Collectors.toList());

Terminal Operations:

1.     collect: The collect method is used to return the result of the intermediate operations performed on the stream.
List number = Arrays.asList(2,3,4,5,3);
Set square = number.stream().map(x->x*x).collect(Collectors.toSet());

2.     forEach: The forEach method is used to iterate through every element of the stream.
List number = Arrays.asList(2,3,4,5);
number.stream().map(x->x*x).forEach(y->System.out.println(y));

3.     reduce: The reduce method is used to reduce the elements of a stream to a single value.
The reduce method takes a BinaryOperator as a parameter.

List number = Arrays.asList(2,3,4,5);
int even = number.stream().filter(x->x%2==0).reduce(0,(ans,i)-> ans+i);

Here ans variable is assigned 0 as the initial value and i is added to it .

 

  • Lambda expressions,
  • Method references,
  • Functional interfaces,
  • Stream API,
  • Default methods,
  • Base64 Encode Decode,
  • Static methods in interface,
  • Optional class,
  • Collectors class,
  • ForEach() method,
  • Parallel array sorting,
  • Nashorn JavaScript Engine,
  • Parallel Array Sorting,
  • Type and Repating Annotations,
  • IO Enhancements,
  • Concurrency Enhancements,
  • JDBC Enhancements etc.

 

 

String literal vs New String in Java

 

 

String a = "Java";

String b = "Java";

System.out.println(a == b);  // True

 

 

String c = new String("Java");

String d = new String("Java");

System.out.println(c == d);  // False

 

String c = new String("Java");

String d = new String("Java");

System.out.println(c.equals(d));  // True

 

String e = "JDK";

String f =  new String("JDK");

System.out.println(e == f);  // False

 

String interning using inter() method

Java by default doesn't put all String object into String pool, instead they gives you flexibility to explicitly store any arbitrary object in String pool. You can put any object to String pool by calling intern() method of java.lang.String class. Though, when you create using String literal notation of Java, it automatically call intern() method to put that object into String pool, provided it was not present in the pool already. This is another difference between string literal and new string, because in case of new, interning doesn't happen automatically, until you call intern() method on that object. 

 

 

6. Garbage Collection

Before Java 7, the JVM placed the Java String Pool in the PermGen space, which has a fixed size — it can't be expanded at runtime and is not eligible for garbage collection.

The risk of interning Strings in the PermGen (instead of the Heap) is that we can get an OutOfMemory error from the JVM if we intern too many Strings.

From Java 7 onwards, the Java String Pool is stored in the Heap space, which is garbage collected by the JVMThe advantage of this approach is the reduced risk of OutOfMemory error because unreferenced Strings will be removed from the pool, thereby releasing memory.

 

 

Until Java 8, Strings were internally represented as an array of characters – char[], encoded in UTF-16, so that every character uses two bytes of memory.

With Java 9 a new representation is provided, called Compact Strings. This new format will choose the appropriate encoding between char[] and byte[] depending on the stored content

 

NICE one

 

 

To get rid from ConcurrentModificationException Use CopyOnWriteArrayList

 

 

If you wanna create new list, use Stream.map method:

List<Fruit> newList = fruits.stream()

    .map(f -> new Fruit(f.getId(), f.getName() + "s", f.getCountry()))

    .collect(Collectors.toList())

If you wanna modify current list, use Collection.forEach:

fruits.forEach(f -> f.setName(f.getName() + "s"))

 

https://vladmihalcea.com/the-best-way-to-handle-the-lazyinitializationexception/

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

How to Detect Deadlock in Java

To detect a deadlock in java, we need to look at the java thread dump of the application, in last post I explained how we can generate thread dump using VisualVM profiler or using jstack utility.

 

 

 

 

 

 

By default, parallel streams use `ForkJoinPool`

 

Java 8

 

Fork/Join framework added in Java SE . Divide and conquer method

 

 

Java 8 new features

 

 @FunctionalInterface

IntStream

 

 

 

 

 

 

 

 

 

Java 9

List.of

Set.of

Map.of

 

Stream<String> stream

User.ifPresentOrElse(x,y)

Interfaces got private method

Jshell

HttpClient

JigsawModule

 

Java 10

Var variable

 

Java 11

 

Strings & Files

Strings and Files got a couple new methods (not all listed here):

Run Source Files

Starting with Java 10, you can run Java source files without having to compile them first. A step towards scripting.

ubuntu@DESKTOP-168M0IF:~$ java MyScript.java

The header says it all:

(var firstName, var lastName) -> firstName + lastName

HttpClient

The HttpClient from Java 9 in its final, non-preview version.

ZGC Garbage collector

 

Java 12

 

 

Java 13

 

Switch expressions can now return a value

 

 

Java 14

 

Have a look at this pre Java 14 class, which only contains data, (potentially) getters/setters, equals/hashcode, toString.

Again, this is a preview feature and subject to change in future releases.

Helpful NullPointerExceptions

Finally NullPointerExceptions describe exactly which variable was null.

 

 

 

 

 

2. Different ways to create streams

 

Stream Operations

Intermediate Operations

·        filter()

·        map()

·        flatMap()

·        distinct()

·        sorted()

·        peek()

·        limit()

·        skip()

Terminal Operations

·        forEach()

·        forEachOrdered()

·        toArray()

·        reduce()

·        collect()

·        min()

·        max()

·        count()

·        anyMatch()

·        allMatch()

·        noneMatch()

·        findFirst()

·        findAny()

 

 

By using AtomicInteger as a replacement for Integer we're able to increment the number concurrently in a thread-safe manor without synchronizing the access to the variable. The method incrementAndGet() is an atomic operation so we can safely call this method from multiple threads

 

 

5 java class design principles

 

 

Related image

 

Related image

 

 

1.     Dependency: Aggregation implies a relationship where the child can exist independently of the parent. For example, Bank and Employee, delete the Bank and the Employee still exist. whereas Composition implies a relationship where the child cannot exist independent of the parent. Example: Human and heart, heart don’t exist separate to a Human

2.     Type of Relationship: Aggregation relation is “has-a” and composition is “part-of” relation.

3.     Type of association: Composition is a strong Association whereas Aggregation is a weak Association.

 

 

 

https://www.youtube.com/watch?v=ImtZgX1nmr8

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

@Bean

@ConditionalOnMissingBean(SomeBean.class)

public SomeBean otherBean(){

    return new SomeBean();

}

 

Some use cases where this annotation comes in handy are:

·        Specifying a fallback bean which gets only loaded as a backup if there is no bean of the same type present (for example: using an in-memory database if there is no real database configured)

·        Specifying a default bean which allows being overridden in the case that a more specific bean of the same type is present in the context (for example: using a default authentication mechanism unless someone decides to replace it with his own custom authentication)

 

https://www.tutorialspoint.com/what-are-the-in-built-functional-interfaces-in-java

 

A Supplier interface has only one single method called get(). It does not accept any arguments and returns an object of any data type.

 

import java.util.*;

import java.util.function.*;

 

public class SupplierTest {

   private static void printNames(Supplier<String> arg) {

      System.out.println(arg.get());

   }

   private static void listBeginWith(List<String> list, Predicate<String> valid) {

      printNames(() -> "\nList of countries:");

      list.forEach(country -> {     // lambda expression

         if(valid.test(country)) {

            printNames(() -> country);

         }

      });

   }

   public static void main(String[] args) {

      String[] countries = {"India", "Australia", "England", "South Africa", "Srilanka", "Newzealand", "West Indies"};

      List<String> countryList = Arrays.asList(countries);

      listBeginWith(countryList, (s) -> s.startsWith("I"));

      listBeginWith(countryList, (s) -> s.contains("I"));

      listBeginWith(countryList, (s) -> s.endsWith("ia"));

   }

}

The Consumer interface has only one single method called accept(). It accepts a single argument of any data type and does not return any result.

 

        // Consumer to display a number

        Consumer<Integer> display = a -> System.out.println(a);

  

        // Implement display using accept()

        display.accept(10);

 

The Predicate interface has only one single method test(). It may be true or false depending on the values of its variables.

 

 

 

 

 

 

 

 

 

final int multiplier = 2; // Final variable

// Lambda expression using final variable
Function<Integer, Integer> multiplyBy = (num) -> num * multiplier;

System.out.println(multiplyBy.apply(5)); // Output: 10

int multiplier2 = 2; // Not final

// Compilation error: Local variable multiplier defined in an enclosing scope must be final or effectively final
multiplier2 = 3;

Function<Integer, Integer> multiplyBy2 = (num) -> num * multiplier2;



class A1 {
   
static final String sample="simple";
   
String output=sample+"sample";
   
String output2=new String(sample+"sample");

   
void a() {
       
System.out.println("simplesample".hashCode() );

       
if ("simplesample" == output) {
           
System.out.println("sample == output " + output.hashCode() );
        }
       
else {
           
System.out.println("sample!= output " + output.hashCode());
        }

       
if ("simplesample" == output2) {
           
System.out.println("sample == output2 " + output2.hashCode() );
        }
       
else {
           
System.out.println("sample!= output2 " + output2.hashCode());
        }
    }

   
public static void main(String[] args) {
       
A1 a1 = new A1();
       
a1.a();
    }

}

 

-479454756

sample == output -479454756

sample!= output2 -479454756