Tuesday, November 13, 2018

Java 8 - Streams - flatMap()

Greetings!

With stream API it is easy to iterate over a collection and do whatever operation we like to do. Let's say we have a number list which we would like to print power of 2 of each.


List<Integer> attempt1 = Arrays.asList(1, 2, 3, 4, 5);
attempt1.stream().map(x -> x * x).forEach(System.out::println);

// 1, 4, 9, 16, 25


What if we have a List of List? let's try that out.


List<List<Integer>> attempt2 = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(2, 5));
Stream<List<Integer>> attempt2Stream = attempt2.stream();
attempt2Stream.map(x -> x * x).forEach(System.out::println); // compile error
attempt2Stream.map(x -> x.stream().map(y -> y * y)).forEach(System.out::println);

// java.util.stream.ReferencePipeline$3@4c873330, java.util.stream.ReferencePipeline$3@119d7047


As you can see Stream.map() doesn't give us the expected result for the type Stream<List<Integer>>.

This is because map() operation is the type of Stream<T> and in this case it is like a stream of stream. Not only map() operation any other operation will not give us the desired result.

This is where the Stream.flatMap() is helpful.

Stream.flatMap()

Intermediate operation. Like map() operation this accepts the mapping function and apply it to all the elements in the stream and produce a new stream as the result. Difference is this can handle any type of stream. It Flattens the input T argument and merge all the elements into new stream of type R.


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


This can understand with few examples.


Stream<DataType[]>>
Stream<Set<DataType>>
Stream<List<DataType>>
Stream<Map<KEY, DataType>


This all can be easily mapped to Stream<DataType> with flatMa(). After flattening we can do any other operation.

Array - Stream<DataType[]>


import java.util.Arrays;
import java.util.stream.Stream;

public class FlatMapArray {

    public static void main(String[] args) {
        Integer[][] array = { { 1, 2, 3 }, { 4, 5 } };
        Stream<Integer[]> stream = Arrays.stream(array);

//        stream.flatMap(subarray -> Arrays.stream(subarray)).map(x -> x * x).forEach(System.out::println);
        stream.flatMap(Arrays::stream).map(x -> x * x).forEach(System.out::println);
    }

}

// 1, 4, 9, 16, 25


List - Stream<List<DataType>>


import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;

public class FlatMapList {

    public static void main(String[] args) {
        List<List<Integer>> lists = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(2, 5));
        Stream<List<Integer>> stream = lists.stream();

//        stream.flatMap(list -> list.stream()).distinct().map(x -> x * x).forEach(System.out::println);
        stream.flatMap(Collection::stream).distinct().map(x -> x * x).forEach(System.out::println);
    }

}

// 1, 4, 9, 25


Map - Stream<Map<Key, Datatype>>


import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

public class FlatMapMap {

    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "one");
        map.put(2, "two");
        map.put(3, "three");
        
        Stream<Map<Integer, String>> streamMap = Stream.of(map);
        
        streamMap.flatMap(m -> m.values().stream()).map(String::toUpperCase).forEach(System.out::println);
    }

}

// ONE, TWO, THREE


Set - Stream<Set<DataType>>


import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;

public class FlatMapSet {

    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("one");
        set.add("two");
        set.add("three");
        
        Stream<Set<String>> streamSet = Stream.of(set);
        
        streamSet.flatMap(Collection::stream).map(String::toUpperCase).forEach(System.out::println);
    }

}

// ONE, TWO, THREE


In summary these operations behave like this; (DataType is String here)

Stream<String> flatMap(Function<String[], Stream<String>> mapper)

Stream<String> flatMap(Function<List<String>, Stream<String>> mapper)

Stream<String> flatMap(Function<Set<String>, Stream<String>> mapper)

Stream<String> flatMap(Function<Map<Integer, String>, Stream<String>> mapper)




Java 8 - Streams - reduce()

Greetings!

Stream API provides several terminal operations for common tasks like count, min, max, sum and average.  These operations return a single value and do specific task. Stream.collect() operation is also a terminal operations but it return a Collection.
reduce() is a more-general purpose operations which can be used to combine the content of stream.

  • These terminal operations are called reduction operations.

Stream.reduce()

This method mainly has two forms.

  • With initial value.
  • Without initial value.

T reduce(T identity, BinaryOperator<T> accumulator);

Optional<T> reduce(BinaryOperator<T> accumulator);


reduce uses BinaryOperator (which extends BiFunction) functional interface which has the form below.

R apply(T t, U u);


How Does It Work

Let's consider below sum operation.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int result = 0;
for (Integer number : numbers) {
    result = result + number;
}
System.out.println(result);


We have a result variable with an initial value and during iteration we add current iteration value to result and assign the calculated value back to result.
Now, this is a reduce operation which fulfills reduce() methods contract.
So, this same operation can be written using reduce like this;

int result8 = numbers.stream().reduce(0, (a, b) -> a + b);
System.out.println(result8);

a - result, b - iteration value
When we are reducing a Collection using iteration which depends on the last calculated value, it is good time to use reduce().

More examples;

import java.util.Arrays;
import java.util.List;

public class ReduceApp {

    public static void main(String[] args) {
        // Java 7
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        int result = 0;
        for (Integer number : numbers) {
            result = result + number;
        }
        System.out.println(result);
        
        // Java 8
        int result8 = numbers.stream().reduce(0, (a, b) -> a + b);
        System.out.println(result8);
        
        int multiplication = numbers.stream().reduce(1, (a, b) -> a * b);
        System.out.println(multiplication);
        
        int evenPow = numbers.stream().filter(i -> i % 2 == 0).reduce(0, (a, b) -> a + b * b);
        System.out.println(evenPow);
        
        List<String> target = Arrays.asList("H", "e", "l", "l", "o");
        String reversed = target.stream().reduce("", (a, b) -> b + a);
        System.out.println(reversed);
    }

}





Monday, November 12, 2018

Hibernate - Basic Annotations

Greetings!

  • @Entity - Add in class level. Declares that this class is an entity

@Entity
public class Employee {
    // ...
}


  • @Table - Add in class level. Define table, schema, catalog. Use name property to add the name of the table unless class name is used as the table name.

@Entity
@Table(name = "tbl_employee")
public class Employee {
    // ...
}


  • @Column - Add column properties.

@Column(name = "first_name")
private String firstName;


  • @Id - Declares property as the identifier of this class.

@Id
private Long id;


  • @GeneratedValue - use along with @Id to generate primary key automatically. JPA defines 5 strategies.

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;


AUTO - select depending on the underlying database.
IDENTITY
SEQUENCE
TABLE
identity copy - identity is copied form another entity.

  • @Version - Adding this will add optimistic locking capability. For an update query Hibernate will automatically add version number validity in where clause. Numeric is preferred but a timestamp can also be used.

@Version
@Column(name="optimistic_lock")
private Integer version;


  • @Temporal - Use to mark date field format like DATE (date only), TIME (time only) or TIMESTAMP (date and time).

@Column(name = "dob")
@Temporal(TemporalType.DATE)
private Date dateOfBirth;


  • @Enumerated - Use to map enum. By default it used enum's ordinal and EnumType can be used to override default behaviour.

@Column(name = "employee_type")
@Enumerated(EnumType.STRING)
private EmployeeType employeeType;


  • @Embedded - Define to use value object inside the entity class.
  • @Embeddable - Define a value object to use in an entity.
  • @Transient - Skip persisting a property.



Hibernate - Value Types

Greetings!

When we design our domain models we can have more important classes and less important classes like Address, String, etc. In other word we have fine-grained object model which means more classes than tables.
For an example User can have an Address. We can create separate class for Address fields and add it as a property in User using composition.


public class User {
    private Long id;
    private String name;
    private Integer age;
    private Address address;
}


Here User is an entity. Name, Age, Address are value types.

  • Entity classes need an identifier.
  • Value type doesn't have an identifier because instances are identified through owning entity.

What is an Entity?

  • Has a database identity.
  • Has it's own life cycle.
  • Object reference is persisted in the database.

What is a Value Type?

  • Doesn't have own identity.
  • Embedded into owning entity.
  • Represent table columns.

How to map?

  • Basic types can be directly mapped using @Column. (String, Integer, etc)
  • Collection value types using collection mapping.
  • Composite value types can be mapped using @Embedable annotation.




Hibernate - Identity

Greetings!

Identity is the fact that being who or what a thing is.

In Java two objects are identical if they are referring to the same memory location.

object1 == object2


Equals means that they have the same value but may not have same memory location.

object1.equals(object2)


In relational databases, objects are identical if they share the same table and have same primary key. This is known as database identity in Java side.

@Id
@GeneratedValue
private Long id;

  • Because @Id on the field, hibernate use field access.
  • If we don't provide @GeneratedValue, JPA provider doesn't provide a key for us. We have to assign ourselves. These are called application-assigned identifiers.

Candidate Key

Column(s) we could use to identify a database row is called candidate keys.

  • Never null.
  • Unique.
  • Never changes.

Natural Key

A key with a business meaning is called a natural key. For an Employee table can have a employee number to represent employee's identity.
Practically, this will have side effects when the system grows.
- composite natural keys are keys combining two or more columns.

Synthetic Key / Surrogate Key

A unique, not null column generated by the database or the application with no business meaning is called surrogate key.
This is the preferred option.




Hibernate - Introduction

Greetings!

Problem in hand

Almost all the applications need to save data. This persistence storage most probably is a database. This storage is independence system which is called data independence. Here comes the problem. How do we convert relational data to Java objects? Sure we can convert one by one which is not convenient due to;
  • It takes lot of time to write code.
  • Difficult to maintain.
  • Need to write all SQL queries.
  • Need to handle transactions.
  • Have to maintain database connections.
  • Not portable.
To solve these kind of problems, Object Relational Mapping frameworks are born. Hibernate is the most popular among them.

In an era of Spring dominating most part of the application, Hibernate is almost hidden. Thanks to Spring Data most of the time we do not have write any SQL query. Spring help us to generate those.

JPA, Hibernate, Spring Data JPA

Java Persistence API is the specification. Hibernate is one of the implementations of JPA. Spring Data provides us another layer to hide JPA by giving magical interfaces to generate SQL.

Don't we have to learn SQL then?

Without knowing anything about SQL, still we can connect to database and save data, read them, etc. Working with databases is a complex topic and difficult to remember. But to get maximum from ORM framework we better know queries, how to optimize them, and so on. Unless we will end up poorly performing system. For an example, for a data set which we can select using single query, hibernate will generate multiple queries which is the famous N+1 problem.

As I mentioned earlier, we do not have to learn all the things about Hibernate either. Practically we are not going to use Hibernate along. Most of the time we are using Spring. We only have to mark our class as a database entity. Spring simplifies datasource management, transaction management, SQL generation for us.

What is important is, we need to learn Hibernate and JPA to map entities.

Hibernate ORM is an object relational mapping tool for Java.



Sunday, November 11, 2018

Java Concurrency - ThreadLocal

Greetings!

Protecting shared, mutable data is difficult. Easiest way to guarantee thread safety is not to share. This technique is called thread confinement.

One way to achieve this is using ThreadLocal class.
This uses internal thread-local variable to store data by the executing thread and provides get() and set() methods to access it.
It internally get the current thread (Thread.currentThread()) and a custom Map to assign data directly in Thread class.
This behaves like Map<Thread, T> object (though this is not how it is done).

ThreadLocal stores per-thread value and provides set(), get() methods to access it.


public class TimeHolder {

    private static ThreadLocal<Long> threadLocal = ThreadLocal.withInitial(() -> System.currentTimeMillis());
    
    public Long get() {
        return threadLocal.get();
    }
    
    public void set() {
        threadLocal.set(System.currentTimeMillis());
    }
    
    public void print() {
        System.out.println(Thread.currentThread().getName() + " : " + get());
    }
    
}


public class ThreadLocalApp {

    public static void main(String[] args) throws InterruptedException {
        TimeHolder timeHolder = new TimeHolder();
        
        timeHolder.print();
        
        Thread t1 = new Thread(() -> timeHolder.print());
        t1.start();
        t1.join();
        
        timeHolder.print();
        
        Thread t2 = new Thread(() -> {
            timeHolder.set();
            timeHolder.print();
        });
        t2.start();
        t2.join();
        
        timeHolder.print();
        
        timeHolder.set();
        timeHolder.print();
    }

}


This gave below output.

main : 1541956810082
Thread-0 : 1541956810085
main : 1541956810082
Thread-1 : 1541956810086
main : 1541956810082
main : 1541956810086


Notice how each thread is having it's own value meaning threads can't see each other's value.



Java Concurrency - Immutable

Greetings!

Problem with shared object is any thread can modify it. What if we have an object type which can not be changed? This is where immutable objects come into play.

Immutable object is an object that once created it's state can not be changed.

We can construct an immutable object by protecting the inner state by not sharing any setter method to change inner state.

How to construct an immutable class?


  • Do not provide setter methods.
  • Make all fields final and private.
  • Make the constructor private and use a factory method to create objects.
  • Do not share mutable objects.
  • If mutable objects need to be shared, share a copy.
  • If the constructor accepts external mutable objects as parameters create a copy of them.
  • Make the class final to avoid sub classing.


public final class Counter {
    
    private final int count;
    
    private Counter(int initialCount) {
        this.count = initialCount;
    }
    
    public static Counter newCounter(int initialCount) {
        return new Counter(initialCount);
    }
    
    public int getCount() {
        return this.count;
    }
    
    public Counter add(int value) {
        return new Counter(this.count + value);
    }

}


Java Built-in Immutable Classes

Java standard API includes many immutable classes. Most famous one is String. Below is a list of few of them.

  • String
  • Integer, Long, Float, Double, Boolean, Short, Char, Byte
  • java.math.BigInteger, java.math.BigDecimal
  • java.io.File
  • java.util.UUID


  • Note that assigned variable is not immutable and hence not thread safe. Other threads can replace the constructed object.






Java Concurrency - Visibility

Greetings!

Synchronization is not only protecting critical sections. It also provide memory visibility. That means, when one thread modify the state other threads should be able to see the changes without any issue.

We should not share objects without proper synchronization. Unless it will lead to stale data which causes;
  • Unexpected exceptions.
  • Infinite loops.
  • Corrupted data.
  • Inaccurate results.

Out of thin air safety

A thread can see some value of shared data which is updated by another thread (even it is stale) is called out-of-thin-air safety.

All threads should see most up-to-date values of shared mutable variables.

Volatile

It is a weaker form of synchronization.
  • Do not re-order.
  • Put in shared memory (not in cpu's cache).
  • Good for simple situations like maintaining a flag, completion flag.
  • Does not guarantee atomicity. Guarantee only visibility.

Publishing

Make an object available outside of its current scope.
  • public variables.
  • non private setters.

Escape

Publish an object when it should not.

Thread confinement

When data is not shared and accessible only form single thread it is called thread confinement.

Non-safe objects within the thread context is still thread-safe.

Java Concurrency - Volatile

Greetings!

volatile is a keyword in Java. When we declare a variable as volatile it doesn't store in CPU cache. Instead it is put in shared memory.
Because of that multiple threads can access the same memory location and get the updated value. Hence this is considered as a weaker synchronization mechanism.
volatile is not suitable for atomic operations. It is best suited for single operations like a flag.


private volatile boolean completed;


  • Store in main memory. never store in thread locally.
  • Guarantee visibility.
  • Not suitable for atomic operations like read-modify-write.
  • No lock involved.
  • Never block other threads.
  • Suitable for operations like having a flag.
  • Can be used if the value doesn't depend on previous value.
  • Have a performance hit because it doesn't store in cache.
  • Weaker form of synchronization.