Design a site like this with WordPress.com
Get started

LocalDate class in java

Java 8 has introduced various classes to work with date and time objects. Lets see today LocalDate class in java 8 and how can we use it in our day to day coding.

Lets look at few of the useful methods provided and understand how it works

System.out.println("My Current TimeZone >> " + ZoneOffset.systemDefault());
System.out.println("Is same as zone >>"+LocalDate.now(Clock.system(ZoneOffset.of("+05:30"))));
		
		
System.out.println(LocalDate.now());
System.out.println(LocalDate.now(Clock.systemUTC()));
System.out.println(LocalDate.now(Clock.system(ZoneOffset.of("+10"))));
System.out.println(LocalDate.now(Clock.system(ZoneOffset.of("+0530"))));

line 1, will print my current timezone

line 2, will print my current timezone converted into UTC offset.

line 3, “LocalDate.now” will print my current date in my timezone.

line 4, will print current date in UTC

line 5, will print current date in time zone offset at +10 from UTC

line 6, will print current date in time zone offset at +05:30 from UTC

Lets look at the output

My Current TimeZone >> Asia/Calcutta
Is same as  >>+05:30
2021-08-06
2021-08-06
2021-08-07
2021-08-06

If you see, the date in time zone +10 is different than in UTC timezone or with offset +5:30. It is also possible to provide negative value of offset as well to the ZoneOffset method.

The “now” methods returns an object of type LocalDate. There are various other utility methods to find month, day of month, day of week, year etc.

Lets look at one useful method

System.out.println(LocalDate.now().get(ChronoField.DAY_OF_MONTH));
System.out.println(LocalDate.now().get(ChronoField.YEAR_OF_ERA));

So if you see above, one of the method accepts a class called TemporalField. ChronoField enum has various temporal fields that can be passed to this method. Output of the above is as below

6
2021

So day of month is 6 and year is 2021. If you pass any temporal field which the LocalDate does support then it will throw “UnsupportedTemporalTypeException”

So for a date object which does not have time, if you ask for temporalfield “ChronoField.AMPM_OF_DAY” then it will throw ” UnsupportedTemporalTypeException”

There are various other utility methods to add days, months, minutes to the current LocalDate object.

Lets look at how can you convert a simple string into a LocalDate object.

LocalDate.from(DateTimeFormatter.ofPattern("yyyy-MM-dd").parse("2021-01-01"));

Here I have used “DateTimeFormatter” to the utility class as formatter and passed the expected date string to the parse method of DateTimeFormatter. This will try to convert the string to the format and return us the LocalDate Object. It will throw Parsing exception if you do not provide correct string to the parse method.

I hope this will help you in some or other way. Thank you !

Advertisement

Java8 Streams – Convert List to Map

A lot of times we are required to convert one collection into another. It could be from list to set , set to map or otherwise. Before java introduced streams and functional programming, for doing such a transformation of collection was possible but then we had write a lot more code than we have to today with Java8 features.

Lets look at a simple example and transform a list to a map.

Lets say we have list of employee’s each having a name and id attribute. Our requirement is to convert the list into a map where key in the map is the “id” attribute of the employee and value is the employee object.

List<Employee> lstEmplyees = new ArrayList<>();
        lstEmplyees.add(new Employee(6606,"dipak"));
        lstEmplyees.add(new Employee(1212,"tony"));
        lstEmplyees.add(new Employee(779,"chetan"));

        Map<Integer,Employee> map =lstEmplyees.stream()
                                        .collect(Collectors.toMap(Employee::getId,Employee::get));
        System.out.println(map);

The above code creates a list 3 employee objects and then converts it into a map with help of streams.

Once you stream the collection, it provides us back with a stream of values in the list and then we can apply collect method to transform it into map. The collect method takes in Collector parameter, several of the implementations are already present in the “Collectors” class. For our use case we use Collectors.toMap. The toMap function takes two functions as input, first being the key mapper and second is the value mapper.

So as we know when we stream a collection, we are fed with stream of the objects inside the collection, one at a time.
In map function, we pass a function to identify the key from the employee object in our case. So for us it is the id attribute, so we return back the id attribute and the second parameter is the value function which return the value we want to associate with the streamed object.

Here is a simplified version of the above code

    List<Employee> lstEmplyees = new ArrayList<>();
        lstEmplyees.add(new Employee(6606,"dipak"));
        lstEmplyees.add(new Employee(1212,"tony"));
        lstEmplyees.add(new Employee(779,"chetan"));

        Function<Employee,Integer> keyMapper = (Employee employee) -> employee.getId();
        Function<Employee,Employee> valueMapper=  Function.identity();  // equvivaled to (Employee employee) -> employee;

        Map<Integer,Employee> map =lstEmplyees.stream()
                                        .collect(Collectors.toMap(keyMapper,valueMapper));
        System.out.println(map);

The above code works fine for just about any collection to convert to map. However, the above code will throw exception when there are duplicates in the collection. We haven’t told java what to do when there is a duplicate key. There is a third parameter that we can pass to tell java what do in case there is duplicate key.

The third parameter is the of the type – BinaryOperator which means it takes in 2 parameters of the same type and returns value of same type

Lets update our code to handle duplicates, in case of duplicates we want the new value to overwrite the old value.

List<Employee> lstEmplyees = new ArrayList<>();
        lstEmplyees.add(new Employee(6606,"dipak"));
        lstEmplyees.add(new Employee(1212,"tony"));
        lstEmplyees.add(new Employee(779,"chetan"));
        lstEmplyees.add(new Employee(779,"chetan1"));

        Function<Employee,Integer> keyMapper = (Employee employee) -> employee.getId();
        Function<Employee,Employee> valueMapper=  Function.identity();  // equvivaled to (Employee employee) -> employee;
        BinaryOperator<Employee> merge = (Employee oldVal,Employee newVal) -> newVal;

        Map<Integer,Employee> map =lstEmplyees.stream()
                                        .collect(Collectors.toMap(keyMapper,valueMapper));

Interesting to note here is that the merge function has parameter “Employee” instead of “Id attribute”. Its because the merge function is asking us to select the value to choose when there are duplicate keys.

There is one more variant of the “toMap” function. In the fourth parameter you can pass the map in which you would want to add the values.