Category Archives: java 8

Java 8: Lambda Expression


Java 8 introduced lambda expression to move toward functional programming. A lambda expression is an anonymous function that doesn’t have a name and doesn’t belong to any class.

Where to use the Lambda Expression

A lambda expression can only be used where the type they are matched against is a single abstract method(SAM) interface or functional interface.

To use a lambda expression, you can either create your own functional interface or use the predefined functional interface provided by Java.

Example of a pre-defined interface: Runnable, callable, ActionListener, etc.

Pre Java 8: Use anonymous inner classes.
Post-Java 8: Now use lambda expression instead of anonymous inner classes.

Points to remember

  • Lambda expression is also known as a closure that allows us to treat functionality as a method arguments (passing functions around) or treat code as data.
  • Lambda expression concept was first introduced in the LISP programming language.
  • Lambda expression is used to provide an implementation of a functional interface or Single Method Interface.
  • Lambda expression treated as a function so the compiler does not create .class file.
  • Lambda expression doesn’t need to define a method again for implementation.
  • Lambda expression benefit is less coding.

Java Lambda expression Syntax

To create a lambda expression, On the left side of the symbol lambda operator(->) specify input parameters (if there are any), and on the right side place the expression or block of statements.


 (parameter_list) -> {function_body}

For example, the lambda expression (x, y) -> x + y specifies that lambda expression takes two arguments x and y and returns the sum of these.

Note:

  • Optional type declaration: No need to declare the data type of a parameter. The compiler can inference the data type from the value of the parameter.
  • The optional parenthesis around parameter: No needs to declare a single parameter in parenthesis. For multiple parameters, parentheses are required.
  • Optional curly braces: For a single line of the statement, No need to use curly braces in the expression body.
  • Optional return keyword: The compiler automatically returns the value if the body has a single expression statement to return the value. Curly braces are required to indicate that expression statement returns a value.

Here is some Lamda expression example according to a number of arguments.

No Argument Syntax


()->{
//write some statemnet here
}

One Argument Syntax


(arg1)->{
//write some statemnet here
}

Two Argument Syntax


(arg1,arg2)->{
//write some statemnet here
}

Method vs Lambda Expression in Java

A function (or method) in Java has four main parts:
1. Name
2. Parameter list
3. Body
4. return type.

A lambda expression has these main parts:
Lambda expression only has a parameter list and body.
1. No name – Lambda expression is an anonymous function that doesn’t have a name.
2. Parameter list
3. Body – This is the main part of the function where implementation is written.
4. No return type – Don’t need to write a return statement explicitly. The compiler is able to infer the return type by checking the code.

Example 1: Lambda Expression with a predefined functional interface

In this thread, execution example consider both ways legacy and lambda expression to implement the run method and start threads.

public class PredefinedFunctionalInterfaceExample {
public static void main(String[] args) {

// Implementing Runnable using anonymous class (legacy way)
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("Thread name : " + Thread.currentThread().getName());
}
};
Thread thread1 = new Thread(runnable1);

// Implementing Runnable using Lambda expression because Runnable having
// only one abstarct method run()
Runnable runnable2 = () -> {
System.out.println("Thread name : " + Thread.currentThread().getName());
};
Thread thread2 = new Thread(runnable2);

// Start Threads
thread1.start();
thread2.start();
}
}

Example 2: lambda Expression with your own functional interface

In this example, define the functional interface “YourFunctionalInterface” definition by the lambda expression for arguments (a,b). When we call the functional interface method with the argument (120,100) then it will make reference to the given definition of FunctionalInterface and return the result as 220.

@FunctionalInterface
interface YourFunctionalInterface
{
 public int addValues(int a, int b);
}

public class CalculateClass {

   public static void main(String args[]) {
        // lambda expression
    YourFunctionalInterface sum = (a, b) -> a + b;
        System.out.println("Result: "+sum.addValues(120, 100));
    }
}

Output


Result: 220

Example 3: Lambda Expression with no arguments

@FunctionalInterface
interface MyFunctionalInterface {
//abstarct method with no argument
public String sayWelcome();
}
public class LambdaExpressionExample {
public static void main(String args[]) {
//No argument lambda expression
MyFunctionalInterface msg = () -> {
return "Welcome to Facing Issues on IT !!";
};
System.out.println(msg.sayWelcome());
}
}

Output


Welcome to Facing Issues on IT !!

Example 4: Lambda Expression for Collection Iteration

import java.util.*;
public class LambdaExpressionLoopExample{
public static void main(String[] args) {
List list=new ArrayList();
list.add("Saurabh");
list.add("Gaurav");
list.add("Bharti");
list.add("Herry");
list.add("Henry");
list.forEach(
// lambda expression for list iteration
(names)->System.out.println(names)
);
}
}

Output


Saurabh
Gaurav
Bharti
Herry
Henry

Note:

  1. As you can see from these examples lambda expression used less code.
  2. Lambda expression is backward compatible so we can enhance our existing API when migrating to Java 8.

References

Java 8: Optional for handling NULL


Java 8 introduces a new class called java.util.Optional to overcome the headache of NullPointerException. Optional class is a type of container of optional single value that either contains a value or doesn’t (it is then said to be “empty”).

The optional class having lots of methods to deal with different cases:

Create Optional Object

Create Optional Object : Empty


Optional optionalObj=Optional.empty();

Create Optional Object: Non-Null
Optional.of() method throw NullPointerException if passing object reference is null.


YourClass yourObj=new YourClass();
Optional optionalObj=Optional.of(yourObj);

Create Optional Object: Allowed Null
Optional.ofNullable() method allowed null reference in Optional object container.


YourClass yourObj=null;
Optional optionalObj=Optional.ofNullable(yourObj);

Check Optional Object for value present

Optional.isPresent() method return boolean true/false based on any value present in Optional container.


if(optionalObj.isPresent())
{
//do something
}

Optional Object for value

if Optional.isPresent() method return true then we get value from Optional object by get() method. If value is not exist in Optional object and trying to call get() method then throw exception as NoSuchElementException


if(optionalObj.isPresent())
{
YourClass yourObj=optionalObj.get();
}

Set Optional Object default value and actions

We can use Optional.orElse() method which provide default value if Optional object is empty.


YourClass yourObj=optionalObj.orElse(new YourClass("defaut"));
</pre We can use Optional.orElseThrow() method which instread of returning default value if Optional empty , throw an exception:

YourClass yourObj = optionalObj.orElseThrow(IllegalStateException::new);

Example 1

In this example, covered all the above case.


import java.util.Optional;
public class OptionalExamples {

	public static void main(String args[]) {
		OptionalExamples java8Tester = new OptionalExamples();
	      Integer value1 = null;
	      Integer value2 = new Integer(25);

	      //Optional.ofNullable - allows passed parameter to be null.
	      Optional<Integer> firstParam = Optional.ofNullable(value1);

	      //Optional.of - throws NullPointerException if passed parameter is null
	      Optional<Integer> secondParam = Optional.of(value2);
	      System.out.println(java8Tester.sum(firstParam,secondParam));
	   }

	   public Integer sum(Optional<Integer> a, Optional<Integer> b) {
	      //Optional.isPresent - checks the value is present or not

	      System.out.println("First parameter is present: " + a.isPresent());
	      System.out.println("Second parameter is present: " + b.isPresent());

	      //Optional.orElse - returns the value if present otherwise returns
	      //the default value passed.
	      Integer value1 = a.orElse(new Integer(0));

	      //Optional.get - gets the value, value should be present
	      Integer value2 = b.get();
	      return value1 + value2;
	   }

}

Output


First parameter is present: false
Second parameter is present: true
25

Example 2

public class OptionalExaple2

	public static void main(String[] args) {
		Optional<String> completeName = Optional.ofNullable(null);
		// The isPresent() method returns true if this instance of Optional has
		// non-null value and false otherwise.
		System.out.println("Complete Name is set? " + completeName.isPresent());
		// The orElseGet() method provides the fallback mechanism in case
		// Optional has null value by accepting the function to generate the
		// default one.
		System.out.println("Complete Name: " + completeName.orElseGet(() -> "[Unknown]"));
		// The map() method transforms the current Optional’s value and returns
		// the new Optional instance.
		System.out.println(completeName.map(s -> "Hey " + s + "!").orElse("Hey Unknown!"));

		Optional<String> firstName = Optional.of("Saurabh");
		System.out.println("First Name is set? " + firstName.isPresent());
		// The orElse() method is similar to orElseGet() but instead of function
		// it accepts the default value.
		System.out.println("First Name: " + firstName.orElseGet(() -> "[Unknown]"));
		System.out.println(firstName.map(s -> "Hey " + s + "!").orElse("Hey Unnknown!"));
		System.out.println();

	}

}

Output


Complete Name is set? false
Complete Name: [Unknown]
Hey Unknown!
First Name is set? true
First Name: Saurabh
Hey Saurabh!

References

 

Java 8: Base64 Encoding and Decoding


In Java 8 added new class Base64 for encryption and decryption. It supports three types encoding and decoding:

  • Simple
  • URL
  • MIME

Note: Passing a null argument to a method of this class will cause a NullPointerException to be thrown.

Simple

Uses “The Base64 Alphabets” lying in A-Za-z0-9+/ for encoding and decoding. The encoder does not add any line feed/line separate character in output and decoder rejects all characters out of the Base 64 alphabet.

Example: Simple Encoding and Decoding

import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Base64s {

	public static void main(String[] args) {
    final String text = "Facing Issues On IT in Java 8!";

        final String encoded = Base64.getEncoder().encodeToString( text.getBytes( StandardCharsets.UTF_8 ) );
        System.out.println("After Encoding:"+ encoded );

        final String decoded = new String(Base64.getDecoder().decode( encoded ),StandardCharsets.UTF_8 );
        System.out.println("After Decoding:"+ decoded );
	}
}

Output


After Encoding:RmFjaW5nIElzc3VlcyBPbiBJVCBpbiBKYXZhIDgh
After Decoding:Facing Issues On IT in Java 8!

URL

Uses “URL and Filename safe Base64 Alphabet” lying in A-Za-z0-9+_ for encoding and decoding. The encoder does not add any line feed/line separater character in output and decoder rejects all characters out of the Base 64 alphabet.

Example: URL Encoding and Decoding

import java.util.Base64;

public class Base64URLExample {

	public static void main(String[] args) {
		String originalUrl = "https://www.google.co.in/?gfe_rd=cr&ei=dzbFV&gws_rd=ssl#q=java";
		String encodedUrl = Base64.getUrlEncoder().encodeToString(originalUrl.getBytes());
		System.out.println("After Encoding:"+ encodedUrl );

		byte[] decodedBytes = Base64.getUrlDecoder().decode(encodedUrl);
		String decodedUrl = new String(decodedBytes);
		System.out.println("After Decoding:"+ decodedUrl );
	}

}

Output


After Encoding:aHR0cHM6Ly93d3cuZ29vZ2xlLmNvLmluLz9nZmVfcmQ9Y3ImZWk9ZHpiRlYmZ3dzX3JkPXNzbCNxPWphdmE=
After Decoding:https://www.google.co.in/?gfe_rd=cr&ei=dzbFV&gws_rd=ssl#q=java

MIME

Uses “The Base64 Alphabet” lying in lying in A-Za-z0-9+/ for encoding and decoding. The encoded output must be represented in lines of no more than 76 characters each and uses a carriage return ‘\r’ followed immediately by a linefeed ‘\n’ as the line separator. No line separator is added to the end of the encoded output. All line separators or other characters not found in the base64 alphabet table are ignored in decoding operation.

Example: MIME Encoding and Decoding

import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.UUID;

public class Base64Mime {

	public static void main(String[] args) {

		try {
			StringBuilder stringBuilder = new StringBuilder();
			// Lets generate some mime input to encode
			for (int i = 0; i < 10; ++i) {
				stringBuilder.append(UUID.randomUUID().toString());
			}

			byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8");
			String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes);
			System.out.println("Base64 Encoded String (MIME) :" + mimeEncodedString);

			byte[] decodedBytes = Base64.getMimeDecoder().decode(mimeEncodedString);
			String decodedMime = new String(decodedBytes);
			System.out.println("Base64 Decoded String (MIME) :" + decodedMime);

		} catch (UnsupportedEncodingException e) {
			System.out.println("Error :" + e.getMessage());
		}
	}

}

Output


Base64 Encoded String (MIME) :YWY1MWRkMDAtNjg0MC00MDE4LTk5YWYtMDE4NTFhYmZkYzA3M2Q0MjU1YjMtNDFiOS00ZmZmLTky
NjktYzc5YjU2Mzg4OGMyM2IzZTAyN2QtNzhkMC00YzRiLTg3MzgtZWFiMmI3OTdlNmVlMzdmYzQ3
ZDItYmI2Zi00NmVjLThlYTQtOWUwYWJlODA0M2IwN2I1NzIxNjUtNzJjZC00ODhmLWJkMWUtOWVl
NGI3YTc5M2NmZjczMjU1MDItMzIyNC00Mjc1LWI2MjQtNTcxZTU3ZmZkZjVhNTdiMmM4NTgtMzFi
Yi00ZjNlLWI5MWYtZWJkNjc5ODlkOTA2NDQ4MDZiZDQtOWM4Zi00NjJlLWI1ZWUtODZiNWM0MTJm
MmVjM2JmMjFjMDAtNjUwYi00ZjE0LWI5ZTUtOTY2YjE2NjUzMWQxMGJhYTIzMTAtOTFmMy00OGYz
LTg1ZTgtZmU3OTEyMjNhODc3
Base64 Decoded String (MIME) :af51dd00-6840-4018-99af-01851abfdc073d4255b3-41b9-4fff-9269-c79b563888c23b3e027d-78d0-4c4b-8738-eab2b797e6ee37fc47d2-bb6f-46ec-8ea4-9e0abe8043b07b572165-72cd-488f-bd1e-9ee4b7a793cff7325502-3224-4275-b624-571e57ffdf5a57b2c858-31bb-4f3e-b91f-ebd67989d90644806bd4-9c8f-462e-b5ee-86b5c412f2ec3bf21c00-650b-4f14-b9e5-966b166531d10baa2310-91f3-48f3-85e8-fe791223a877

References

Java 8: Arrays Parallel Processing


Java 8 added lots of new methods to allow parallel processing for arrays. The most frequently used one is parallelSort() which may speed up the arrays sorting on multicore machines.

Java 8 new methods for Arrays

  • Arrays.parallelSetAll(): Set all elements of the specified array, in parallel, using the provided generator function to compute each element.
  • Arrays.parallelSort(): Sorts the specified array into ascending numerical order.
  • Arrays.parallelPrefix(): Cumulates, in parallel, each element of the given array in place, using the supplied function.

Example: Arrays Parallel Processing

In this example uses method parallelSetAll() to fill up arrays with 25000 random values.
After that, the apply parallelSort() on these arrays values. Here you can see the output of the initial 10 values before and after sorting.

public class ParallelArrays {

	public static void main(String[] args) {
		    long[] arrayOfLong = new long [ 25000 ];
            //Fill long array with random numbers parallelly
	        Arrays.parallelSetAll( arrayOfLong,index -> ThreadLocalRandom.current().nextInt( 1000000 ) );
			//Print initial 10 values of array
            System.out.println("Before Sorting:Print initial 10 values of array");
	        Arrays.stream( arrayOfLong ).limit( 10 ).forEach(i -> System.out.print( i + " " ) );
	        System.out.println();
			//Parallel Sort Array Values
	        Arrays.parallelSort( arrayOfLong );
			//Print initial 10 values of array
			System.out.println("After Sorting:Print initial 10 values of array");
	        Arrays.stream( arrayOfLong ).limit( 10 ).forEach(i -> System.out.print( i + " " ) );
	        System.out.println();
	}

}

Output


Before Sorting:Print initial 10 values of array
164965 546280 269106 800751 338598 862392 358814 206345 611726 788465 
After Sorting: Print initial 10 values of array
4 13 87 93 94 145 203 281 319 397

References

Java 8 : Nashorn JavaScript Engine


Java 8 introduced a new Nashorn Javascript Engine to replace existing Rhino. Nashorn Javascript engine provides 2 to 10 times better performance and it directly compiles the code in memory and passes the bytecode to JVM. Nashorn JavaScript Engine enhanced version of javax.script.ScriptEngine and follows the same set of rules, permitting for Java and JavaScript interoperability.

Points to remember

  • Use jjs command to run Javascript through Nashhorn Engine.
  • The class name for the Nashorn Javascript engine is jdk.nashorn.api.scripting.NashornScriptEngine.

Exmaple: Nashorn JavaScript Engine

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class NashornEngineTest {

	public static void main(String[] args) {
		try {
			ScriptEngineManager manager = new ScriptEngineManager();
			ScriptEngine engine = manager.getEngineByName("JavaScript");

			System.out.println(engine.getClass().getName());
			System.out.println("Result:"
					+ engine.eval("function increment() { return 1; }; increment() + 1;"));
		} catch (ScriptException ex) {
			ex.printStackTrace();
		}

	}

}

Output


jdk.nashorn.api.scripting.NashornScriptEngine
Result:2.0

References

Java 8:Named Parameters in Reflection


With Java 8 reflection API added method to get parameters name of the method. For that, you need to make some compile-time configuration as pass the compiler flag: javac -parameters.

In this example, you will difference in reflection API output with and without named parameter configuration.

Example: Named Parameter Reflection API

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class NamedParameterExample {

	public static void main(String[] args) throws Exception {

		for(Method method :NamedParameterExample.class.getDeclaredMethods()) {
			System.out.println("\nMethod :"+method.getName()+" Parameters are :");
			for (final Parameter parameter : method.getParameters()) {
				System.out.println("Parameter: " + parameter.getName());
			}
		}
	}

	public static void printValues()
	{
		//Some statement here
	}

	public static int addOperation(int A, int b)
	{
		return A+b;
	}

	public static int substractionOperation(int param1 , int param2)
	{
		return param1-param2;
	}
}

Output: Without Configuration for the named parameter


Method :main Parameters are :
Parameter: arg0

Method :printValues Parameters are :

Method :addOperation Parameters are :
Parameter: arg0
Parameter: arg1

Method :substractionOperation Parameters are :
Parameter: arg0
Parameter: arg1

Output: With Configuration for the named parameter



Method :main Parameters are :
Parameter: args

Method :printValues Parameters are :

Method :addOperation Parameters are :
Parameter: A
Parameter: b

Method :substractionOperation Parameters are :
Parameter: param1
Parameter: param2

Eclipse Configuration for Named Parameter

Go to Window Tab -> Preferences -> Compiler -> Select Checkbox for “Store Information about method parameters (usable via reflection)”.
As shown in the below screen.

Java 8 named parameter eclipse setting

Console Configuration for Named Parameter

On time on compile with javac pass additional configuration as javac -parameters “class name”.

Maven Configuration for Named Parameter

On section of the maven-compiler-plugin:


<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId> 
  <version>3.1</version>
  <configuration> 
       <compilerArgument>-parameters</compilerArgument>
       <source>1.8</source> 
       <target>1.8</target> 
  </configuration>
</plugin>

Java 8: Reflection API to get Repeatable Annotation Detail


Java 8, introduced some new reflection APIs to retrieve annotation related information from different elements types like classes, interfaces, method, type, etc.

Reflection API provides new method getAnnotionByType() to return array of repeating annotations type.

Pre-requisite: Java: Annotations

In previous post Java 8: Repeatable Annotations you have learned about the creation and implementation of repeatable annotation. Let’s take one more example of repeatable annotation and see how to get annotation detail by Java reflection APIs.

Example: Retrieve Annotation Detail by Reflection API

As repeating annotations should themselves annotated with @Repeatable(Filetrs.class) annotation. Here Filters is just a holder of Filter’s annotations. The filterable interface defined Filter annotation two times with different values.

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class RepeatingAnnotations {
	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	public @interface Filters {
		Filter[] value();
	}

	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	@Repeatable(Filters.class)
	public @interface Filter {
		String value();
	};

	@Filter("filter1")
	@Filter("filter2")
	public interface Filterable {
	}

	public static void main(String[] args) {

	    /**
		*Here reflection API Class.getAnnotationsByType() returns
		*array of applied annotations
		*/
		for (Filter filter : Filterable.class
				.getAnnotationsByType(Filter.class)) {
			System.out.println(filter.value());
		}
	}

}

Output


filter1
filter2

Java 8: Repeatable Annotations


In Java 8 introduced repeatable annotation so that same annotation can be used multiple time on the same declaration and type use. For example, create a custom annotation to implement as repeatable annotation.

Pre-Requisite : Java: Annotations Tutorial

See also: Java 8: Reflection API to get Repeatable Annotation Detail

Create Custom Repeatable Annotation

import java.lang.annotation.Repeatable;
@Repeatable(Schedules.class)
public @interface Schedule {
String dayOfMonth() default "first";
String dayOfWeek() default "Mon";
int hour() default 2;
}

Create an array of repeatable annotation


package com.common.annotations;
public @interface Schedules {
Schedule[] value();
}

Use of repeatable annotation


package com.common.annotations;
import java.util.Date;
public class RepeatableAnnotationExample {
    public static void main(String[] args) {

    } 

@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour=23)
   public void doPeriodicCleanup() {
     System.out.println("Clean up started at :"+new Date());
   }
}

Java 8: StringJoiner Class


In java 8, introduced a new class StringJoiner to join more than one strings with the specified delimiter. This class also provides prefix and suffix to the final delimited String. We can also set default text value if no values added for string joined.

Constructors

  • StringJoiner(CharSequence delimiter): Constructs a StringJoiner with a delimiter, with no prefix or suffix.
  • StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix): Constructs a StringJoiner with delimiter on values and add prefix and suffix on the final value.

Example 1: StringJoiner with delimiter (:)

Here in this example defined StringJoiner with a delimiter (:) to separate values, use StringJoiner.setEmptyValue() method to default value if not data added. Use StringJoiner.add() method to add values on StringJoiner.

import java.util.StringJoiner;

public class StringJoinerExample {

	public static void main(String[] args) {
		// Passing Hyphen(:) as delimiter
        StringJoiner myFriends = new StringJoiner(":");
        myFriends.setEmptyValue("No Friends Found");
        System.out.println("Friends Detail : When no data added");
        System.out.println(myFriends);
        // Joining multiple strings by using add() method
        myFriends.add("Saurabh");
        myFriends.add("Gaurav");
        myFriends.add("Raghav");
        myFriends.add("Shailesh");
        myFriends.add("Ankur");                 

        System.out.println("Friends Detail : After data added");
        // Displaying the output String with delimiter :
        System.out.println(myFriends);
	}

}

Output


Friends Detail : When no data added
No Friends Found
Friends Detail : After data added
Saurabh:Gaurav:Raghav:Shailesh:Ankur

Example 2: StringJoiner with a delimiter (:), prefix, and suffix

In this example, defined StringJoiner with a delimiter for values, prefix, and suffix for final delimited String.

import java.util.StringJoiner;

public class StringJoinerPrefixSuffixExample {

	public static void main(String[] args) {
		// Passing colon (:) as delimiter , prefix ({) and suffix (})
        StringJoiner myFriends = new StringJoiner(":","{","}"); 

        myFriends.setEmptyValue("No Friends Found");
        System.out.println("Friends Detail : When no data added");
        System.out.println("Friends Detail :"+myFriends);
        // Joining multiple strings by using add() method
        myFriends.add("Saurabh");
        myFriends.add("Gaurav");
        myFriends.add("Raghav");
        myFriends.add("Shailesh");
        myFriends.add("Ankur");
        System.out.println("Friends Detail : After data added");
        // Displaying the output String with delimiter :
        System.out.println(myFriends);
	}

}

Output


Friends Detail : When no data added
Friends Detail :No Friends Found
Friends Detail : After data added
{Saurabh:Gaurav:Raghav:Shailesh:Ankur}

Example 3: Merge StringJoiner 1 with a delimiter (:), StringJoiner 2 with a delimiter (,)

We can use StringJoiner.merge() method to merge the values of two StringJoiner. Here also use StringJoiner.length() method which returns the length of the final delimited String.

import java.util.StringJoiner;

public class StringJoinerMergeExample {

	public static void main(String[] args) {
	   // Passing Hyphen(:) as delimiter
        StringJoiner myFriends = new StringJoiner(":");
        // Joining multiple strings by using add() method
        myFriends.add("Saurabh");
        myFriends.add("Gaurav");
        myFriends.add("Raghav");
        myFriends.add("Shailesh");
        myFriends.add("Ankur");                 

        System.out.println("Friends Detail 1: After data added");
        // Displaying the output String with delimiter :
        System.out.println(myFriends); 

     // Passing Hyphen(:) as delimiter
        StringJoiner myFriends1 = new StringJoiner(",");
        // Joining multiple strings by using add() method
        myFriends1.add("Saurabh1");
        myFriends1.add("Gaurav1");
        myFriends1.add("Raghav1");
        myFriends1.add("Shailesh1");
        myFriends1.add("Ankur1");                 

        System.out.println("Friends Detail 2: After data added");
        // Displaying the output String with delimiter :
        System.out.println(myFriends1); 

        //Merge StringJoiner
        myFriends1.merge(myFriends);
        System.out.println("Result after merge Friends Detail 1 & 2:");
        System.out.println(myFriends1);

        //Length of String Joiner
        System.out.println(myFriends1.length());

	}

}

Output


Friends Detail 1: After data added
Saurabh:Gaurav:Raghav:Shailesh:Ankur
Friends Detail 2: After data added
Saurabh1,Gaurav1,Raghav1,Shailesh1,Ankur1
Result after merge Friends Detail 1 & 2:
Saurabh1,Gaurav1,Raghav1,Shailesh1,Ankur1,Saurabh:Gaurav:Raghav:Shailesh:Ankur
78

References

Java 8: Functional Interface


“An interface having exactly one abstract method is called Function Interface. Along with one abstract method can have any number of default and static methods.”

Points to Remember

  • This is also called as Single Abstract Method Interfaces or SAM Interfaces.
  • The default method having implementation is not considered as an abstract method.
  • An interface declares an abstract method overriding one of the public methods of java.lang.Object is not considered as an abstract method because any implementation of the interface will have an implementation from java.lang.Object or elsewhere.
  • If you declare an interface with @FunctionalInterface then the annotated interface must satisfy the requirements of a functional interface, if not match requirement will get the compile-time issue.

Note: Compiler will treat an interface as a functional interface if fulfilling conditions of Functional interface regardless of whether or not declared with @FunctionalInterface annotation.

Where to use Functional Interface

  • Functional Interface uses to represent Lambda Expressions.

Create your own functional interface

We can create our own Functional Interface by using @FunctionalInterface or Define interface having only one abstract method.

@FunctionalInterface
interface YourFunctionalInterface
{
 public int addValues(int a, int b);
}

Use of Functional Interface

We can use our own functional interface as above or predefined interface also such as Runnable, ActionListener, Comparator, etc. all these having a single abstract method.

Example: Use your own functional interface

In this example, define the functional interface “YourFunctionalInterface” definition by the lambda expression for arguments (a,b). When we call the functional interface method with the argument (120,100)  then it will make reference to the given definition of FunctionalInterface and return the result as 220.

public class CalculateClass {

   public static void main(String args[]) {
        // lambda expression
    YourFunctionalInterface sum = (a, b) -> a + b;
        System.out.println("Result: "+sum.addValues(120, 100));
    }
}

Output


Result: 220

Example: Use a predefined functional interface

In this thread, execution example consider both ways legacy and lambda expression to implement the run method and start threads.

public class PredefinedFunctionalInterfaceExample {
public static void main(String[] args) {

// Implementing Runnable using anonymous class (legacy way)
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("Thread name : " + Thread.currentThread().getName());
}
};
Thread thread1 = new Thread(runnable1);

// Implementing Runnable using Lambda expression because Runnable having
// only one abstarct method run()
Runnable runnable2 = () -> {
System.out.println("Thread name : " + Thread.currentThread().getName());
};
Thread thread2 = new Thread(runnable2);

// Start Threads
thread1.start();
thread2.start();
}
}

References