CompletableFuture is used for asynchronous or non-blocking programming in Java. With asynchronous programming, you can have one or many tasks being processed at the same time. This is done by using separate threads, other than the main thread, to process other tasks. The main thread is not blocked or waiting so tasks can be done in parallel. The main thread is just notified when other threads are done with their tasks whether it’s completion or failure.
A Future is used as a reference to the result of an asynchronous computation. It provides an isDone() method to check whether the computation is done or not, and a get() method to retrieve the result of the computation when it is done.
List<String> placeHolders = Arrays.asList(RestService.PLACEHOLDER_USER, RestService.PLACEHOLDER_TODO);
CompletableFuture<ArrayNode>[] futures = new CompletableFuture[placeHolders.size()];
for (int i = 0; i < futures.length; i++) {
CompletableFuture<ArrayNode> pl = restService.getPlaceHolderTestingList(placeHolders.get(i));
futures[i] = pl;
}
CompletableFuture.allOf(futures).join();
try {
for (int i = 0; i < futures.length; i++) {
ArrayNode plhds = futures[0].get();
log.info("plhds={}", ObjectUtils.toJson(plhds));
}
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
List<String> placeHolders = Arrays.asList(RestService.PLACEHOLDER_USER, RestService.PLACEHOLDER_TODO);
CompletableFuture<ArrayNode>[] futures = new CompletableFuture[placeHolders.size()];
for (int i = 0; i < futures.length; i++) {
CompletableFuture<ArrayNode> pl = restService.getPlaceHolderTestingList(placeHolders.get(i));
futures[i] = pl;
}
CompletableFuture.allOf(futures).join();
try {
for (int i = 0; i < futures.length; i++) {
ArrayNode plhds = futures[0].get();
log.info("plhds={}", ObjectUtils.toJson(plhds));
}
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
September 24, 2019
Array Parallel Sort
The sorting algorithm is a parallel sort-merge that breaks the array into sub-arrays that are themselves sorted and then merged. When the sub-array length reaches a minimum granularity, the sub-array is sorted using the appropriate Arrays.sort method. If the length of the specified array is less than the minimum granularity, then it is sorted using the appropriate Arrays.sort method. The algorithm requires a working space no greater than the size of the original array. The ForkJoin common pool is used to execute any parallel tasks.
private static void timeSort() {
int[] arraySizes = { 10000, 100000, 1000000, 10000000 };
for (int arraySize : arraySizes) {
System.out.println("When Array size = " + arraySize);
int[] intArray = new int[arraySize];
Random random = new Random();
for (int i = 0; i < arraySize; i++)
intArray[i] = random.nextInt(arraySize) + random.nextInt(arraySize);
int[] forSequential = Arrays.copyOf(intArray, intArray.length);
int[] forParallel = Arrays.copyOf(intArray, intArray.length);
long startTime = System.currentTimeMillis();
Arrays.sort(forSequential);
long endTime = System.currentTimeMillis();
System.out.println("Sequential Sort Milli seconds: " + (endTime - startTime));
startTime = System.currentTimeMillis();
Arrays.parallelSort(forParallel);
endTime = System.currentTimeMillis();
System.out.println("Parallel Sort Milli seconds: " + (endTime - startTime));
System.out.println("------------------------------");
}
}
private static void timeSort() {
int[] arraySizes = { 10000, 100000, 1000000, 10000000 };
for (int arraySize : arraySizes) {
System.out.println("When Array size = " + arraySize);
int[] intArray = new int[arraySize];
Random random = new Random();
for (int i = 0; i < arraySize; i++)
intArray[i] = random.nextInt(arraySize) + random.nextInt(arraySize);
int[] forSequential = Arrays.copyOf(intArray, intArray.length);
int[] forParallel = Arrays.copyOf(intArray, intArray.length);
long startTime = System.currentTimeMillis();
Arrays.sort(forSequential);
long endTime = System.currentTimeMillis();
System.out.println("Sequential Sort Milli seconds: " + (endTime - startTime));
startTime = System.currentTimeMillis();
Arrays.parallelSort(forParallel);
endTime = System.currentTimeMillis();
System.out.println("Parallel Sort Milli seconds: " + (endTime - startTime));
System.out.println("------------------------------");
}
}
Result:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
When Array size = 10000
Sequential Sort Milli seconds: 3
Parallel Sort Milli seconds: 6
------------------------------
When Array size = 100000
Sequential Sort Milli seconds: 11
Parallel Sort Milli seconds: 27
------------------------------
When Array size = 1000000
Sequential Sort Milli seconds: 148
Parallel Sort Milli seconds: 28
------------------------------
When Array size = 10000000
Sequential Sort Milli seconds: 873
Parallel Sort Milli seconds: 215
------------------------------
When Array size = 10000
Sequential Sort Milli seconds: 3
Parallel Sort Milli seconds: 6
------------------------------
When Array size = 100000
Sequential Sort Milli seconds: 11
Parallel Sort Milli seconds: 27
------------------------------
When Array size = 1000000
Sequential Sort Milli seconds: 148
Parallel Sort Milli seconds: 28
------------------------------
When Array size = 10000000
Sequential Sort Milli seconds: 873
Parallel Sort Milli seconds: 215
------------------------------
When Array size = 10000
Sequential Sort Milli seconds: 3
Parallel Sort Milli seconds: 6
------------------------------
When Array size = 100000
Sequential Sort Milli seconds: 11
Parallel Sort Milli seconds: 27
------------------------------
When Array size = 1000000
Sequential Sort Milli seconds: 148
Parallel Sort Milli seconds: 28
------------------------------
When Array size = 10000000
Sequential Sort Milli seconds: 873
Parallel Sort Milli seconds: 215
------------------------------
As you can see, when the array size is small sequential sorting performs better but when the array size is large parallel sorting performs better. So figure out which sorting algorithm to use you must know the size of the array and determine whether such size is small or large for your use case.
Also, you can sort an array partially meaning you can sort an array from a certain position to another certain position.
Thread Safety – The Date and Calendar classes are not thread safe, leaving developers to deal with the headache of hard to debug concurrency issues and to write additional code to handle thread safety. On the contrary the new Date and Time APIs introduced in Java 8 are immutable and thread safe, thus taking that concurrency headache away from developers.
APIs Design and Ease of Understanding – The Date and Calendar APIs are poorly designed with inadequate methods to perform day-to-day operations. The new Date/Time APIs is ISO centric and follows consistent domain models for date, time, duration and periods. There are a wide variety of utility methods that support the commonest operations.
ZonedDate and Time – Developers had to write additional logic to handle timezone logic with the old APIs, whereas with the new APIs, handling of timezone can be done withLocal and ZonedDate/Time APIs.
LocalDate is an immutable date-time object that represents a date, often viewed as year-month-day. Other date fields, such as day-of-year, day-of-week and week-of-year, can also be accessed. For example, the value “2nd October 2007” can be stored in a LocalDate. This class does not store or represent a time or time-zone.
How to create a LocalDate
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// use now() method
LocalDate now = LocalDate.now(ZoneId.systemDefault());//2019-09-10
// add days
LocalDate date2 = LocalDate.now().plusDays(2);//2016-08-18
// minus
date2 = date2.minus(1, ChronoUnit.MONTHS);//2016-07-18
// plus
//date2 = date2.plus(3, ChronoUnit.MONTHS);//2016-10-18
// add days
LocalDate date2 = LocalDate.now().plusDays(2);//2016-08-18
// minus
date2 = date2.minus(1, ChronoUnit.MONTHS);//2016-07-18
// plus
//date2 = date2.plus(3, ChronoUnit.MONTHS);//2016-10-18
LocalDateTime is an immutable date-time object that represents a date-time, often viewed as year-month-day-hour-minute-second. Other date and time fields, such as day-of-year, day-of-week, and week-of-year, can also be accessed. Time is represented to nanosecond precision. For example, the value “2nd October 2007 at 13:45.30.123456789” can be stored in a LocalDateTime. This class does not store or represent a time-zone.
How to create a LocalDateTime
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// use now() method
LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
// add days
LocalDateTime date1 = LocalDateTime.of(2019, 6, 20, 0, 0).plusDays(2);//2019-06-22T00:00
// minus
date1 = date1.minus(1, ChronoUnit.MONTHS);//2019-05-22T00:00
// plus
date1 = date1.plus(3, ChronoUnit.MONTHS);//2019-08-22T00:00
// add days
LocalDateTime date1 = LocalDateTime.of(2019, 6, 20, 0, 0).plusDays(2);//2019-06-22T00:00
// minus
date1 = date1.minus(1, ChronoUnit.MONTHS);//2019-05-22T00:00
// plus
date1 = date1.plus(3, ChronoUnit.MONTHS);//2019-08-22T00:00
LocalTime is an immutable date-time object that represents a time, often viewed as hour-minute-second. Time is represented to nanosecond precision. For example, the value “13:45.30.123456789” can be stored in a LocalTime.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
LocalTime now = LocalTime.now(Clock.systemDefaultZone());
Optional is a container object that may or may not contain a value. You can check if a value is present by calling the isPresent() method. If isPresent() returns true you can use the get() method to return the value.
Null pointer exception is a real problem in programming and that we must handle it with care.
How to create an Optional
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
String name = "Folau";
// name can't be null or else you will get a NullPointerException
Optional<String> opt = Optional.of(name);
String name = "Folau";
// name can't be null or else you will get a NullPointerException
Optional<String> opt = Optional.of(name);
String name = "Folau";
// name can't be null or else you will get a NullPointerException
Optional<String> opt = Optional.of(name);
If we expect null values, we can use the ofNullable method which does not throw a NullPointerException
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
String name = "Folau";
Optional<String> opt = Optional.ofNullable(name);
String name = null;
// this won't throw a NullPointerException
Optional<String> opt = Optional.ofNullable(name);
String name = "Folau";
Optional<String> opt = Optional.ofNullable(name);
String name = null;
// this won't throw a NullPointerException
Optional<String> opt = Optional.ofNullable(name);
String name = "Folau";
Optional<String> opt = Optional.ofNullable(name);
String name = null;
// this won't throw a NullPointerException
Optional<String> opt = Optional.ofNullable(name);
Check if Optional is empty or not
The Optional.isPresent() method is used to check if an Optional has a value or not. It returns true if the Optional has value otherwise it returns false.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
String name = "Folau";
Optional<String> opt = Optional.ofNullable(name);
if(opt.isPresent()){
System.out.println("Value available.");
}else{
System.out.println("Value not available.");
}
String name = "Folau";
Optional<String> opt = Optional.ofNullable(name);
if (opt.isPresent()) {
System.out.println("Value available.");
} else {
System.out.println("Value not available.");
}
String name = "Folau";
Optional<String> opt = Optional.ofNullable(name);
if (opt.isPresent()) {
System.out.println("Value available.");
} else {
System.out.println("Value not available.");
}
The Optional.ifPresent() method is used to execute a lambda function (on the value) if Optional is not empty. if Optional is empty, do nothing.
//when using orElse(), whether the wrapped value is present or not, the default object is created.
//So in this case, we have just created one redundant object that is never used.
String n = opt.orElse(getRealName());
System.out.println(n);
String na = opt.orElseGet(() ->getRealName());
System.out.println(na);
....
privateStringgetRealName(){
System.out.println("getRealName()");
return"Lisa";
}
// Run program result
getRealName()
Folau
Folau
//when using orElse(), whether the wrapped value is present or not, the default object is created.
//So in this case, we have just created one redundant object that is never used.
String n = opt.orElse(getRealName());
System.out.println(n);
String na = opt.orElseGet(() -> getRealName());
System.out.println(na);
....
private String getRealName() {
System.out.println("getRealName()");
return "Lisa";
}
// Run program result
getRealName()
Folau
Folau
//when using orElse(), whether the wrapped value is present or not, the default object is created.
//So in this case, we have just created one redundant object that is never used.
String n = opt.orElse(getRealName());
System.out.println(n);
String na = opt.orElseGet(() -> getRealName());
System.out.println(na);
....
private String getRealName() {
System.out.println("getRealName()");
return "Lisa";
}
// Run program result
getRealName()
Folau
Folau
Optional.filter(Predicate T) – If a value is present, and the value matches the given predicate, return an Optional describing the value, otherwise return an empty Optional.
Optional.map(Function mapper) – If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.
SStringJoiner is used to construct a sequence of characters separated by a delimiter and optionally starting with a supplied prefix and ending with a supplied suffix.
Prior to adding something to the StringJoiner, its sj.toString() method will, by default, return prefix + suffix. However, if the setEmptyValue method is called, the emptyValue supplied will be returned instead. This can be used, for example, when creating a string using set notation to indicate an empty set, i.e. "{}", where the prefix is "{", the suffix is "}" and nothing has been added to the StringJoiner.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import java.util.StringJoiner;
publicclass StringJoinerDemo {
publicstaticvoidmain(String[] args){
String delimeter = "-";
StringJoiner names = newStringJoiner(delimeter);
names.add("Laulau");
names.add("Kinga");
names.add("Fusi");
System.out.println(names);
}
}
import java.util.StringJoiner;
public class StringJoinerDemo {
public static void main(String[] args) {
String delimeter = "-";
StringJoiner names = new StringJoiner(delimeter);
names.add("Laulau");
names.add("Kinga");
names.add("Fusi");
System.out.println(names);
}
}
import java.util.StringJoiner;
public class StringJoinerDemo {
public static void main(String[] args) {
String delimeter = "-";
StringJoiner names = new StringJoiner(delimeter);
names.add("Laulau");
names.add("Kinga");
names.add("Fusi");
System.out.println(names);
}
}