Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Monday, August 16, 2021

Java 8: Time API with examples

Reasons for new Date API in Java8

Thread Safety: Date & Calendar classs are not thread safe, hence developers had to deal with complexity of debugging concurrency issues or handle thread safety in code. Whereas new Date & Time APIs in java8 are immutable & thread safe.

Ease of understanding: Date & Calendar classs are not designed well, that is, for doing day to day date operations there are no adequate methods. New Date & Time APIs follows consistent models of date, time, duration & period providing variety of utility methods for date calculations. 

Zoned Date & Time: For handling date time zones, developers had to write additional logic in the code. New Date & Time APIs hae Zoned Date & Time APIs. It provides 601 different time zones and zoneId represents these zones as shown in below examples 


A TemporalAmount represents an amount of time, which may be date-based or time-based, which this factory extracts to a Period.


Compatibility with Date and Calendar: In order to convert existing Date and Calendar from Java 7 (or earleir), Java 8 has provided toInstant method as follows


In earlier Java versions, ThreeTen & Joda-Time libraries can provide the similar capabilities as that Java8. Using these libraries will make migration in future easier.


Below are a few important classes from new Date & Time APIs from Java8


       
       

package java8.datetimeapi;

import java.time.*;
import java.time.temporal.*;
import java.util.*;
import java.time.format.DateTimeFormatter;
import java.util.stream.Collectors;

public class DateTimeAPIDemo {

public static void main(String[] args) {
	System.out.println("-------------LOCAL DATE Examples--------------");
	System.out.println("Create instance using .now()	:"+LocalDate.now());
	System.out.println("Create instance using .of() 	:"+LocalDate.of(2021, 8, 16));
	System.out.println("Create instance using .of() 	:"+LocalDate.of(2021, Month.AUGUST, 16));
	System.out.println("Create instance using .parse()	:"+LocalDate.parse("2021-08-16"));
	
	System.out.println("Adding a day 			:"+LocalDate.now().plusDays(1));
	System.out.println("Minus month 			:"+LocalDate.now().minusMonths(1));
	System.out.println("Minus month ChronoUnit		:"+LocalDate.now().minus(1, ChronoUnit.MONTHS));
	
	System.out.println("Day of week 			:"+LocalDate.now().getDayOfWeek());
	System.out.println("Day of month Integer		:"+LocalDate.now().getDayOfMonth());
	
	System.out.println("Local Date compareTo 		:"+ LocalDate.now().compareTo(LocalDate.of(2025, 01, 01)));
	System.out.println("Local Date isBefore 		:"+LocalDate.now().isBefore(LocalDate.of(2025, 01, 01)));
	System.out.println("Local Date isAfter 		:"+LocalDate.now().isAfter(LocalDate.of(2025, 01, 01)));
	
	System.out.println("Days untill 2025-01-01 		:"+LocalDate.now().until(LocalDate.of(2025, 01, 01), ChronoUnit.DAYS));
	System.out.println("Dates between 15-Aug to 20-Aug 	:"+LocalDate.of(2021, 8, 15).datesUntil(LocalDate.of(2021, 8, 20)).collect(Collectors.toList()));
	System.out.println("Dates bet 15 to 20 with step=2 	:"+LocalDate.of(2021, 8, 15).datesUntil(LocalDate.of(2021, 8, 20),Period.ofDays(2)).collect(Collectors.toList()));
	
	System.out.println("Is leap year? 			:"+LocalDate.now().isLeapYear());
	System.out.println("Length of Month 		:"+LocalDate.now().lengthOfMonth());
	System.out.println("At Start of this Day 		:"+LocalDate.now().atStartOfDay());
	
	System.out.println("-------------LOCAL TIME Examples--------------");
	System.out.println("Create instance using .now()	:"+LocalTime.now());
	System.out.println("Create instance using .of() 	:"+LocalTime.of(15, 31, 23));
	System.out.println("Local Time compareTo 		:"+LocalTime.of(15, 21, 15).compareTo(LocalTime.of(15, 31, 24)));
	System.out.println("Seconds until 			:"+LocalTime.of(15, 21, 15).until(LocalTime.of(15, 31, 25), ChronoUnit.SECONDS));
	System.out.println("Local Time isBefore 		:"+LocalTime.of(15, 21, 15).isBefore(LocalTime.of(15, 31, 25)));
	System.out.println("Local Time isAfter 		:"+LocalTime.of(15, 21, 15).isAfter(LocalTime.of(15, 31, 25)));
	System.out.println("Current time - 600 seconds 	:"+LocalTime.now().minus(600, ChronoUnit.SECONDS));
	System.out.println("Current time - 600 seconds 	:"+LocalTime.now().plus(600, ChronoUnit.SECONDS));
	System.out.println("Query using TemporalQueries 	:"+LocalTime.now().query(TemporalQueries.precision()));
	System.out.println("Query using Customized query 	:"+LocalTime.now().query(EarlyMorningHoursQuery));
	
	System.out.println("-------------LOCAL DATE TIME Examples--------------");
	System.out.println("Create instance using .now() 	:"+LocalDateTime.now());
	System.out.println("Create instance using .parse 	:"+LocalDateTime.parse("2021-08-16T16:45:34"));
	System.out.println("Using LocalDate & LocalTime 	:"+LocalDateTime.of(LocalDate.now(), LocalTime.now()));
	System.out.println("LocalDateTime compareTo 	:"+LocalDateTime.now().compareTo(LocalDateTime.of(LocalDate.of(2022, 8, 16), LocalTime.of(16, 30))));
	System.out.println("Days Until 16-08-2022 16:30 	:"+LocalDateTime.now().until(LocalDateTime.of(LocalDate.of(2025, 8, 16), LocalTime.of(16, 30)), ChronoUnit.DAYS));

	System.out.println("-------------ZONE DATE TIME Examples--------------");
	System.out.println("Using localDateTime & zoneId 	:"+ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Asia/Kolkata")));
	System.out.println("Using .parse() 			:"+ZonedDateTime.parse("2021-08-16T16:45:34+05:30[Europe/Paris]"));
	System.out.println("Zone Id of Asia-Kolkata is 	:"+ZoneId.of("Asia/Kolkata"));
	System.out.println("System defualt zone Id 		:"+ZoneId.systemDefault());
	System.out.println("Local time with offset 		:"+OffsetDateTime.of(LocalDateTime.now(), ZoneOffset.of("+02:00")));
	ZoneId.getAvailableZoneIds().stream().forEach(a-> System.out.println("Zone: "+a));
	
	System.out.println("-------------PERIOD Examples--------------");
	System.out.println("Adding 5 days to current date 	:"+LocalDate.now().plus(Period.ofDays(5)));
	System.out.println("Period between in Days		:"+Period.between(LocalDate.of(2021, 8, 16), LocalDate.of(2021, 4, 13)).getDays());
	System.out.println("Period from() 			:"+Period.from(Period.ofYears(2)));
	Period pr = Period.parse("P10Y-2M5D");
	System.out.println("Period parse() 			:"+ pr.getYears()+" Years, "+pr.getMonths()+" Months and "+pr.getDays()+" Days");
	System.out.println("Period multipliedBy 		:"+ pr.multipliedBy(2));
	System.out.println("Period negated 			:"+pr.negated());
	System.out.println("Period normalized 17M to 1Y & 5M:"+ Period.of(10, 17, 20).normalized());
	System.out.println("Period totalMonths 		:"+pr.toTotalMonths());
	
	System.out.println("-------------DURATION Examples--------------");
	Duration dr = Duration.of(30, ChronoUnit.MINUTES);
	System.out.println("Duration compareTo 		:"+dr.compareTo(Duration.of(10, ChronoUnit.SECONDS)));
	System.out.println("Duration dividedBy 		:"+dr.dividedBy(10));
	System.out.println("Duration addTo 			:"+dr.addTo(LocalDateTime.now()));
	System.out.println("Duration abs 			:"+dr.abs());
	
	System.out.println("-------------Compatibility Examples--------------");
	Date date = new Date();
	System.out.println("Conver Date to LocalDate 	:"+LocalDateTime.ofInstant(date.toInstant(), ZoneId.of("Asia/Kolkata")));
	Calendar cal = Calendar.getInstance();
	System.out.println("Conver Calendar to LocalDate 	:"+LocalDateTime.ofInstant(cal.toInstant(), ZoneId.of("Asia/Kolkata")));

	System.out.println("-------------Formatting Examples--------------");
	LocalDateTime ldt = LocalDateTime.of(LocalDate.now(), LocalTime.now());
	System.out.println("Current LocalDateTime 		:"+ldt);
	System.out.println("Format in ISO Date Time 	:"+ldt.format(DateTimeFormatter.ISO_DATE_TIME));
	System.out.println("Format pattern & locale 	:"+ldt.format(DateTimeFormatter.ofPattern("dd-MM-yyyy").withLocale(Locale.GERMANY)));
	System.out.println("Format pattern & locale 	:"+ldt.format(DateTimeFormatter.ofPattern("dd-MM-yyyy", Locale.US)));
	
}

private static final TemporalQuery<Boolean> EarlyMorningHoursQuery = 
		temporal -> {
			LocalTime lt = LocalTime.from(temporal);
			return (lt.compareTo(LocalTime.of(5, 0)) >=0 && (lt.compareTo(LocalTime.of(8, 0)) <0));
		};

}

Java 8: Streams API: map vs flapMap

Both map & flatMap are used for transforming the stream data which produces another stream as method output. Map transforms one input to one output value whereas flatMap produces arbitrary (zero, one or more) number of values for each input. Syntax for both is as follows

<R> Stream<R> map(Function<? super T, ? extends R> mapper)

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

method returns a Stream

T is type of stream elements

R is element type of the new stream (note that, flatMap takes in Stream of type R)

mapper is stateless function that is applied to each element



       


package java8;
import java.util.*;

public class EmployeeDB {
	public static List<Employee> getEmployeeList(){
		List<Employee> empList = Arrays.asList(
				//int eId, String fName, String lName, double salary, List<Integer> phNumbers
				new Employee(5, "Sonu", "Panjabi", 1000, Arrays.asList(1234, 2345)),
				new Employee(7, "Ganu", "Marathi", 1500, Arrays.asList(3456, 4567)),
				new Employee(8, "Manu", "Bangali", 2000, Arrays.asList(5678, 6789)),
				new Employee(4, "Tonu", "Bihari", 3000, Arrays.asList(7890, 8901)),
				new Employee(1, "Kanu", "Asami", 3500, Arrays.asList(9012, 1230)),
				new Employee(6, "Ranu", "Kashmiri", 4000, Arrays.asList(9876, 8765)),
				new Employee(2, "Janu", "Kannadi", 4500, Arrays.asList(7654, 6543)),
				new Employee(3, "Monu", "Gujrathi", 5000, Arrays.asList(5432, 4321))
				);
		return empList;
	}
}
package java8.mapvsflatmap;

import java.util.stream.Collectors;
import java.util.stream.Stream;

import java8.EmployeeDB;

public class MapVsFlatMap {

	public static void main(String[] args) {
		System.out.println(EmployeeDB.getEmployeeList().stream().map(e-> e.getPhNumbers()).collect(Collectors.toList()));
		//<R> Stream<R> map(Function<? super T, ? extends R> mapper)
		//<List<Integer>> Stream<List<Integer>> java.util.stream.Stream.map(Function<? super Employee, ? extends List<Integer>> mapper)
		System.out.println(EmployeeDB.getEmployeeList().stream().flatMap(e -> e.getPhNumbers().stream()).collect(Collectors.toList()));
		//<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
		//<Integer> Stream<Integer> java.util.stream.Stream.flatMap(Function<? super Employee, ? extends Stream<? extends Integer>> mapper)
		
		Stream.of("1", "2").mapToInt(s -> Integer.valueOf(s)).forEach(s -> System.out.print(", mapToInt: "+s));
		System.out.println();
		Stream.of("one", "two").flatMapToInt(s -> s.chars()).forEach(s -> System.out.print(", flatMapToInt: "+s));
		
		
	}

}

Sunday, August 15, 2021

Java 8: Streams API: Normal streams vs parallel streams

By default any Stream operations is performed in sequential way unless explicitly stated. The output of sequential operations is predictable i.e. elements will always be processed in their encounter order For example, see "Total Sequential Time Taken for IntStream example" or "Total Sequential Time Taken for Employee Example" in below code. In these examples, all the elements are processed in Main thread only.

Whereas parallel streams enable us to execute the code in parallel on separate cores. Output of each of the cores processing will then be combined to produce the final output. In this case, order of execution elements is NOT in our (developer) control, it may change every time we run the program. Please see below examples where parallel execution is using other threads from ForkJoinPool along with Main thread. ForkJoin framework (added in Java 7) is in charge of this parallel execution i.e. distributing the data and handling callbacks.

There are 2 ways to create a stream to execute in parallel using .parallel() method and .parallelStream() method. Below code shows both the examples. When I executed the code, below is the time taken for each of the executions

Total Sequential Time Taken for IntStream example :9

Total Parallel Time Taken using .parallel() for IntStream example : 31


Total Sequential Time Taken for Employee Example:34

Total Parallel Time Taken using .parallelStream() for Exmployee example :13

Total Parallel Time Taken using .parallel() for Exmployee example :4


If you observe, for IntStream converting the stream to execute in parallel has worsen the performance. The reason behind this is for simple streams and operations, sometimes managing the threads, sources and results (i.e. splitting & merging) is more expensive than executing it sequential way. If you see the examples with Employee time for sequential execution is more than with parallelStream() method stream which is again more than when using parallel() method.


So the question comes, when shall we use parallel streams

1. When there is actually a performance requirement: we should first measure performance using sequential stream and then consider parallel stream as one of the optimization strategy

2. Large data & complex computations 


       


package java8;
import java.util.*;

public class EmployeeDB {
	public static List<Employee> getEmployeeList(){
		List<Employee> empList = Arrays.asList(
				//int eId, String fName, String lName, double salary, List<Integer> phNumbers
				new Employee(5, "Sonu", "Panjabi", 1000, Arrays.asList(1234, 2345)),
				new Employee(7, "Ganu", "Marathi", 1500, Arrays.asList(3456, 4567)),
				new Employee(8, "Manu", "Bangali", 2000, Arrays.asList(5678, 6789)),
				new Employee(4, "Tonu", "Bihari", 3000, Arrays.asList(7890, 8901)),
				new Employee(1, "Kanu", "Asami", 3500, Arrays.asList(9012, 1230)),
				new Employee(6, "Ranu", "Kashmiri", 4000, Arrays.asList(9876, 8765)),
				new Employee(2, "Janu", "Kannadi", 4500, Arrays.asList(7654, 6543)),
				new Employee(3, "Monu", "Gujrathi", 5000, Arrays.asList(5432, 4321))
				);
		return empList;
	}
}
package java8.sequentialparallelstream;

import java.time.Duration;
import java.time.LocalTime;
import java.util.stream.IntStream;

import java8.EmployeeDB;

public class SequentialAndParallelStream {

	public static void main(String[] args) {
		
		IntStream seqStream = IntStream.range(1, 11);
		LocalTime startTime = LocalTime.now();
		seqStream.forEach(a-> System.out.println("Thread: "+Thread.currentThread().getName()+" value:"+a));
		LocalTime endtTime = LocalTime.now();
		Duration totalTime = Duration.between(startTime, endtTime);
		System.out.println("Total Sequential Time Taken for IntStream example :"+ totalTime.toMillis());
		
		IntStream parallelStream = IntStream.range(1, 11);
		startTime = LocalTime.now();
		parallelStream.parallel().forEach(a-> System.out.println("Thread: "+Thread.currentThread().getName()+" value:"+a));
		endtTime = LocalTime.now();
		totalTime = Duration.between(startTime, endtTime);
		System.out.println("Total Parallel Time Taken using .parallel() for IntStream example : "+ totalTime.toMillis());
		
		System.out.println("\n Let's check with employee example \n");
		
		long start = System.currentTimeMillis();
		EmployeeDB.getEmployeeList().stream().sorted((e1, e2) -> e1.getfName().compareTo(e2.getfName()))
			.forEach(a ->System.out.println("Thread: "+Thread.currentThread().getName()+" value:"+a));
		long end = System.currentTimeMillis();
		long total = end - start;
		System.out.println("Total Sequential Time Taken for Employee Example:"+ total);
		
		start = System.currentTimeMillis();
		EmployeeDB.getEmployeeList().parallelStream().sorted((e1, e2) -> e1.getfName().compareTo(e2.getfName()))
			.forEach(a ->System.out.println("Thread: "+Thread.currentThread().getName()+" value:"+a));
		end = System.currentTimeMillis();
		total = end - start;
		System.out.println("Total Parallel Time Taken using .parallelStream() for Exmployee example :"+ total);
		
		start = System.currentTimeMillis();
		EmployeeDB.getEmployeeList().stream().parallel().sorted((e1, e2) -> e1.getfName().compareTo(e2.getfName()))
			.forEach(a ->System.out.println("Thread: "+Thread.currentThread().getName()+" value:"+a));
		end = System.currentTimeMillis();
		total = end - start;
		System.out.println("Total Parallel Time Taken using .parallel() for Exmployee example :"+ total);
	}

}

SpringBoot: Features: SpringApplication

Below are a few SpringBoot features corresponding to SpringApplication StartUp Logging ·          To add additional logging during startup...