Showing posts with label OCPJP. Show all posts
Showing posts with label OCPJP. Show all posts

Friday, September 2, 2016

Default Methods on Functional Interfaces

By definition, all functional interfaces have a single abstract method. This doesn’t mean that they have only one method, though. Several of the common functional interfaces provide a number of helpful default methods.
Suppose that we have these two Predicates:

Predicate<String> egg = s -> s.contains("egg");
Predicate<String> brown = s -> s.contains("brown");

Now we want a Predicate for brown eggs and another for all other colors of eggs:

Predicate<String> brownEggs = egg.and(brown);
Predicate<String> otherEggs = egg.and(brown.negate());

Neat! Now we are reusing the logic in the original Predicates to build two new ones. It’s shorter and clearer what the relationship is between the Predicates.

Wednesday, August 31, 2016

An Easier Way of Comparing Multiple Fields

Suppose that we have a Squirrel class and assume that the species name will never be null. We could write a constructor to enforce that if we wanted to:

public class Squirrel {
private int weight;
private String species;

public Squirrel(String theSpecies) {
if (theSpecies == null)
throw new IllegalArgumentException();
species = theSpecies;
}

public int getWeight() {
return weight;
}

public void setWeight(int weight) {
this.weight = weight;
}

public String getSpecies() {
return species;
}
}

We want to write a Comparator to sort by species name. If two squirrels are of the species, we want to sort the one that weighs the least first.
With the introduction of static and default methods on interfaces within Java 8, there are now some new helper methods on Comparator. The code could be written as this:

import java.util.Comparator;

public class ChainingComparator implements Comparator<Squirrel> {
@Override
public int compare(Squirrel s1, Squirrel s2) {
Comparator<Squirrel> c = Comparator.comparing(s -> s.getSpecies());
c = c.thenComparingInt(s -> s.getWeight());
return c.compare(s1, s2);
}
}

Tuesday, August 30, 2016

Design patterns: Singleton, Immutable object, Builder and Factory

A design pattern is an established general solution to a commonly occurring software development problem. The purpose of a design pattern is to leverage the wealth of knowledge of developers who have come before you in order to solve old problems that you might encounter easily. It also gives developers a common vocabulary in which they could discuss common problems and solutions. For example, if you say that you wrote getters/ setters or implemented the singleton pattern, most developers will understand the structure of your code without having to get into the low‐level details.

Singleton Pattern

The singleton pattern is a creational pattern focused on creating only one instance of an object in memory within an application, sharable by all classes and threads within the application. The globally available object created by the singleton pattern is referred to as a singleton. Singletons might also improve performance by loading reusable data that would otherwise be time-consuming to store and reload each time it is needed.
The following VisitorTicketTracker class represents an example of an implementation of the Singleton Pattern:

// Lazy instantiation
public class VisitorTicketTracker {
private static volatile VisitorTicketTracker instance;

private VisitorTicketTracker() {
}

public static VisitorTicketTracker getInstance() {
if (instance == null) {
synchronized (VisitorTicketTracker.class) {
if (instance == null) {
instance = new VisitorTicketTracker();
}
}
}
return instance;
}

// Data access methods
}

Immutable Objects

The immutable object pattern is a creational pattern based on the idea of creating objects whose state does not change after they are created and could be easily shared across multiple classes. Immutable objects go hand and hand with encapsulation, except that no setter methods exist that modify the object. Since the state of an immutable object never changes, they are inherently thread‐safe.
The following Animal class represents an example of an implementation of immutable object pattern:

import java.util.ArrayList;
import java.util.List;

public final class Animal {
private final String species;
private final int age;
private final List<String> favoriteFoods;

public Animal(String species, int age, List<String> favoriteFoods) {
this.species = species;
this.age = age;
if (favoriteFoods == null) {
throw new RuntimeException("favorite Foods is required");
}
this.favoriteFoods = new ArrayList<String>(favoriteFoods);
}

public String getSpecies() {
return species;
}

public int getAge() {
return age;
}

public int getFavoriteFoodsCount() {
return favoriteFoods.size();
}

public String getFavoriteFood(int index) {
return favoriteFoods.get(index);
}
}

Builder Pattern

The builder pattern is a creational pattern in which parameters are passed to a builder object, often through method chaining, and an object is generated with a final build call. It is often used with immutable objects, since immutable objects do not have setter methods and must be created with all of their parameters set, although it could be used with mutable objects as well.
The following AnimalBuilder class goes along with our previous class Animal and represents an example of an implementation of the builder pattern:


import java.util.List;

public class AnimalBuilder {
private String species;
private int age;
private List<String> favoriteFoods;

public AnimalBuilder setAge(int age) {
this.age = age;
return this;
}

public AnimalBuilder setSpecies(String species) {
this.species = species;
return this;
}

public AnimalBuilder setFavoriteFoods(List<String> favoriteFoods) {
this.favoriteFoods = favoriteFoods;
return this;
}

public Animal build() {
return new Animal(species, age, favoriteFoods);
}
}

Factory Pattern

The factory pattern sometimes referred to as the factory method pattern, is a creational pattern based on the idea of using a factory class to produce instances of objects based on a set of input parameters. It is similar to the builder pattern, although it is focused on supporting class polymorphism.
Less talk, here is an example:

abstract class Food {
private int quantity;

public Food(int quantity) {
this.quantity = quantity;
}

public int getQuantity() {
return quantity;
}

public abstract void consumed();
}

class Hay extends Food {
public Hay(int quantity) {
super(quantity);
}

@Override
public void consumed() {
System.out.println("Hay eaten: " + getQuantity());
}
}

class Pellets extends Food {
public Pellets(int quantity) {
super(quantity);
}

@Override
public void consumed() {
System.out.println("Pellets eaten: " + getQuantity());
}
}

public class FoodFactory {
public static Food getFood(String animalName) {
switch (animalName) {
case "zebra":
return new Hay(100);
case "rabbit":
return new Pellets(5);
case "goat":
return new Pellets(30);
}
// Good practice to throw an exception if no matching subclass could be
// found
throw new UnsupportedOperationException("Unsupported animal: " + animalName);
}
}

Wednesday, August 24, 2016

The Easy Way to Write toString(), equals() and hashCode() Methods

Once you’ve written a toString() method, it starts to get boring to write more especially if you want to include a lot of instance variables. Luckily, there is an open source library that takes care of it for you. Apache Commons Lang provides some methods that you might wish were in core Java.
This is all you have to write to have Apache Commons return all of the instance variables in a String:

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}

You might be wondering what this reflection thing is that is mentioned in the method name. Reflection is a technique used in Java to look at information about the class at runtime. This lets the ToString Builder class determine what are all of the instance variables and to construct a String with each.
When testing your code, there is a benefit to not having information in toString() that isn’t useful to your caller. Apache Commons accounts for this as well.
You could write

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}

There are a few other styles that support letting you choose to omit the class names or the instance variable names.


Like toString(), you could use Apache Commons Lang to do a lot of the work for you. If you want all of the instance variables to be checked, your equals() method could be one line:

@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}

This is nice. However, for equals(), it is common to look at just one or two instance variables rather than all of them.

@Override
public boolean equals(Object obj) {
if (!(obj instanceof LionEqualsBuilder))
return false;
Lion other = (Lion) obj;
return new EqualsBuilder().appendSuper(super.equals(obj)).append(idNumber, other.idNumber)
.append(name, other.name).isEquals();
}

Not quite as elegant, right? You have to remember to handle the null and instanceof guard conditions first. It is still better than having to code the whole thing by hand, though. Comparing the idNumber is easy because you could call ==. Comparing the name means checking that either both names are null or the names are the same. If either name is null, you need to return false. This logic is a bit messy if you write it out by hand.


You probably thought that this was going to be about the Apache Commons Lang class for hash code. There is one, but it isn’t the easiest way to write hash code.
It is easier to code your own. Just pick the key fields that identify your object (and don’t change during the program) and combine them:

@Override
public int hashCode() {
return keyField + 7 * otherKeyField.hashCode();
}

It is common to multiply by a prime number when combining multiple fields in the hash code. This makes the hash code more unique, which helps when distributing objects into buckets.

Wednesday, August 17, 2016

How to work with locales

In order to understand how to make use of locales in Java, let's try two useful examples. First, assume that you want to extract available locales speaking French which has the code "fr":

import java.util.Arrays;
import java.util.Locale;

class AvailableLocalesFrench {
public static void main(String[] args) {
Arrays.stream(Locale.getAvailableLocales()).filter(locale -> locale.getLanguage().equals("fr"))
.forEach(locale -> System.out.printf("Locale code: %s and it stands for %s %n", locale,
locale.getDisplayName()));
}
}

By running this you would get:

Locale code: fr_BE and it stands for French (Belgium) 
Locale code: fr_CH and it stands for French (Switzerland) 
Locale code: fr and it stands for French 
Locale code: fr_LU and it stands for French (Luxembourg) 
Locale code: fr_FR and it stands for French (France) 
Locale code: fr_CA and it stands for French (Canada)

The Second example, let's set the default locale within the system to France and get some details about it:

import java.util.Locale;

public class LocaleDetails {
public static void main(String args[]) {
Locale.setDefault(Locale.FRANCE);
Locale defaultLocale = Locale.getDefault();
System.out.printf("The default locale is %s %n", defaultLocale);
System.out.printf("The default language code is %s and the name is %s %n", defaultLocale.getLanguage(),
defaultLocale.getDisplayLanguage());
System.out.printf("The default country code is %s and the name is %s %n", defaultLocale.getCountry(),
defaultLocale.getDisplayCountry());
System.out.printf("The default variant code is %s and the name is %s %n", defaultLocale.getVariant(),
defaultLocale.getDisplayVariant());
}
}

Outputs:

The default locale is fr_FR 
The default language code is fr and the name is français 
The default country code is FR and the name is France 
The default variant code is  and the name is

Tuesday, August 16, 2016

How to make use of RecursiveTask and ForkJoinPool

RecursiveTask is a predefined class in the package java.util.concurrent. This class allows you to implement recursivity using multiple threads. To illustrate, let's assume that you want to calculate the sum of numbers from 1 to 1.000.000 making use of 10 threads at same time(parallelism) and exploiting efficiently processors available on the computer:

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

// This class illustrates how we can compute the sum of 1..N numbers using fork/join framework.
// The range of numbers are divided into half until the range can be handled by a thread.
// Once the range summation completes, the result gets summed up together.  

class SumOfNUsingForkJoin {

private static long N = 1000_000; // one million - we want to compute sum
// from 1 .. one million

private static final int NUM_THREADS = 10;
// number of threads to create for
// distributing the effort

// This is the recursive implementation of the algorithm; inherit from
// RecursiveTask
// instead of RecursiveAction since we're returning values.
static class RecursiveSumOfN extends RecursiveTask<Long> {
long from, to;
// from and to are range of values to sum-up

public RecursiveSumOfN(long from, long to) {
this.from = from;
this.to = to;
}

// the method performs fork and join to compute the sum if the range
// of values can be summed by a threadremember that we want to divide
// the summation task equally among NUM_THREADS) then, sum the range
// of numbers from..to using a simple for loop;
// otherwise, fork the range and join the results
@Override
public Long compute() {

if ((to - from) <= N / NUM_THREADS) {
// the range is something that can be handled
// by a thread, so do summation

long localSum = 0;
// add in range 'from' .. 'to' inclusive of the value 'to'
for (long i = from; i <= to; i++) {
localSum += i;
}

System.out.printf("\tSum of value range %d to %d is %d %n", from, to, localSum);
return localSum;
} else {
// no, the range is too big for a thread to handle,
// so fork the computation
// we find the mid-point value in the range from..to
long mid = (from + to) / 2;
System.out.printf("Forking computation into two ranges: " + "%d to %d and %d to %d %n", from, mid, mid,
to);

// determine the computation for first half
// with the range from..mid
RecursiveSumOfN firstHalf = new RecursiveSumOfN(from, mid);

// now, fork off that task
firstHalf.fork();
// determine the computation for second half
// with the range mid+1..to
RecursiveSumOfN secondHalf = new RecursiveSumOfN(mid + 1, to);
long resultSecond = secondHalf.compute();

// now, wait for the first half of computing sum to
// complete, once done, add it to the remaining part
return firstHalf.join() + resultSecond;
}
}
}

public static void main(String[] args) {
// Create a fork-join pool that consists of NUM_THREADS
ForkJoinPool pool = new ForkJoinPool(NUM_THREADS);

// submit the computation task to the fork-join pool
long computedSum = pool.invoke(new RecursiveSumOfN(0, N));

// this is the formula sum for the range 1..N
long formulaSum = (N * (N + 1)) / 2;

// Compare the computed sum and the formula sum
System.out.printf("Sum for range 1..%d; computed sum = %d, " + "formula sum = %d %n", N, computedSum,
formulaSum);
}
}

Executing the example will result in:

Forking computation into two ranges: 0 to 500000 and 500000 to 1000000 
Forking computation into two ranges: 500001 to 750000 and 750000 to 1000000 
Forking computation into two ranges: 0 to 250000 and 250000 to 500000 
Forking computation into two ranges: 500001 to 625000 and 625000 to 750000 
Forking computation into two ranges: 0 to 125000 and 125000 to 250000 
Forking computation into two ranges: 750001 to 875000 and 875000 to 1000000 
Forking computation into two ranges: 500001 to 562500 and 562500 to 625000 
Forking computation into two ranges: 125001 to 187500 and 187500 to 250000 
Forking computation into two ranges: 0 to 62500 and 62500 to 125000 
Sum of value range 187501 to 250000 is 13671906250 
Forking computation into two ranges: 625001 to 687500 and 687500 to 750000 
Sum of value range 500001 to 562500 is 33203156250 
Sum of value range 62501 to 125000 is 5859406250 
Sum of value range 625001 to 687500 is 41015656250 
Forking computation into two ranges: 250001 to 375000 and 375000 to 500000 
Forking computation into two ranges: 375001 to 437500 and 437500 to 500000 
Sum of value range 687501 to 750000 is 44921906250 
Sum of value range 0 to 62500 is 1953156250 
Sum of value range 562501 to 625000 is 37109406250 
Sum of value range 125001 to 187500 is 9765656250 
Forking computation into two ranges: 750001 to 812500 and 812500 to 875000 
Forking computation into two ranges: 875001 to 937500 and 937500 to 1000000 
Sum of value range 750001 to 812500 is 48828156250 
Sum of value range 937501 to 1000000 is 60546906250 
Sum of value range 812501 to 875000 is 52734406250 
Sum of value range 375001 to 437500 is 25390656250 
Sum of value range 437501 to 500000 is 29296906250 
Forking computation into two ranges: 250001 to 312500 and 312500 to 375000 
Sum of value range 875001 to 937500 is 56640656250 
Sum of value range 250001 to 312500 is 17578156250 
Sum of value range 312501 to 375000 is 21484406250 
Sum for range 1..1000000; computed sum = 500000500000, formula sum = 500000500000

How to make use of CyclicBarrier

The CyclicBarrier allows you to run some tasks on the condition that certain prior tasks complete. Let's suppose a mixed tennis game which requires the presence of 4 players in order to start, here is how you might implement this in Java using the predefined CyclicBarrier class:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

// The run() method in this thread should be called only when 
// four players are ready to start the game 
class MixedDoubleTennisGame extends Thread {
@Override
public void run() {
System.out.println("All four players ready, game starts \n Love all...");
}
}

// This thread simulates arrival of a player.
// Once a player arrives, he/she should wait for other players to arrive
class Player extends Thread {
CyclicBarrier waitPoint;

public Player(CyclicBarrier barrier, String name) {
this.setName(name);
waitPoint = barrier;
this.start();
}

@Override
public void run() {
System.out.println("Player " + getName() + " is ready ");
try {
waitPoint.await(); // await for all four players to arrive
} catch (BrokenBarrierException | InterruptedException exception) {
System.out.println("An exception occurred while waiting... " + exception);
}
}
}

// Creates a CyclicBarrier object by passing the number of threads and the
// thread to run
// when all the threads reach the barrier
class CyclicBarrierTest {
public static void main(String[] args) {
// a mixed-double tennis game requires four players;
// so wait for four players
// (i.e., four threads) to join to start the game
System.out.println("Reserving tennis court \n" + "As soon as four players arrive, game will start");
CyclicBarrier barrier = new CyclicBarrier(4, new MixedDoubleTennisGame());
new Player(barrier, "G I Joe");
new Player(barrier, "Dora");
new Player(barrier, "Tintin");
new Player(barrier, "Barbie");
}
}

Running this outputs:

Reserving tennis court 
As soon as four players arrive, game will start
Player Dora is ready 
Player G I Joe is ready 
Player Tintin is ready 
Player Barbie is ready 
All four players ready, game starts 
 Love all...

Monday, August 15, 2016

How to process binary data

Sometimes, in real world cases, you might have to deal with binary data which is a little bit different in processing from text based data. The examples bellow show you how to simply deal with this type of flows.

Example 1:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

// A simple class to illustrate data streams; write constants 0 and 1 in different 
// data type values into a file and read the results back and print them 
class DataStreamExample {
public static void main(String[] args) {
// write some data into a data file with hard-coded name "temp.data"
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("temp.data"))) {
// write values 1 to 10 as byte, short, int, long, float and double
// omitting boolean type because an int value cannot
// be converted to boolean
for (int i = 0; i < 10; i++) {
dos.writeByte(i);
dos.writeShort(i);
dos.writeInt(i);
dos.writeLong(i);
dos.writeFloat(i);
dos.writeDouble(i);
}
} catch (FileNotFoundException fnfe) {
System.err.println("cannot create a file with the given file name ");
System.exit(-1); // don’t proceed – exit the program
} catch (IOException ioe) {
System.err.println("an I/O error occurred while processing the file");
System.exit(-1); // don’t proceed – exit the program
}
// the DataOutputStream will auto-close, so don't have to worry about it
// now, read the written data and print it to console
try (DataInputStream dis = new DataInputStream(new FileInputStream("temp.data"))) {
// the order of values to read is byte, short, int, long, float and
// double since we've written from 0 to 10,
// the for loop has to run 10 times
for (int i = 0; i < 10; i++) {
// %d is for printing byte, short, int or long
// %f, %g, or %e is for printing float or double
// %n is for printing newline
System.out.printf("%d %d %d %d %g %g %n", dis.readByte(), dis.readShort(), dis.readInt(),
dis.readLong(), dis.readFloat(), dis.readDouble());
}
} catch (FileNotFoundException fnfe) {
System.err.println("cannot create a file with the given file name ");
} catch (IOException ioe) {
System.err.println("an I/O error occurred while processing the file");
} // the DataOutputStream will auto-close, so don't have to worry about
// it
}
}

Outputs:

0 0 0 0 0.00000 0.00000 
1 1 1 1 1.00000 1.00000 
2 2 2 2 2.00000 2.00000 
3 3 3 3 3.00000 3.00000 
4 4 4 4 4.00000 4.00000 
5 5 5 5 5.00000 5.00000 
6 6 6 6 6.00000 6.00000 
7 7 7 7 7.00000 7.00000 
8 8 8 8 8.00000 8.00000 
9 9 9 9 9.00000 9.00000 

Example 2:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;

// A simple class to illustrate object streams: fill a data structure, write it to a 
// temporary file and read it back and print the read data structure 
class ObjectStreamExample {
public static void main(String[] args) {
Map<String, String> presidentsOfUS = new HashMap<>();
presidentsOfUS.put("Barack Obama", "2009 to --, Democratic Party, 56th term");
presidentsOfUS.put("George W. Bush", "2001 to 2009, Republican Party, 54th and 55th terms");
presidentsOfUS.put("Bill Clinton", "1993 to 2001, Democratic Party, 52nd and 53rd terms");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.data"))) {

oos.writeObject(presidentsOfUS);
} catch (FileNotFoundException fnfe) {
System.err.println("cannot create a file with the given file name ");
} catch (IOException ioe) {
System.err.println("an I/O error occurred while processing the file");
} // the ObjectOutputStream will auto-close, so don't have to worry
// about it

try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.data"))) {

Object obj = ois.readObject();
// first check if obj is of type Map
if (obj != null && obj instanceof Map) {
Map<?, ?> presidents = (Map<?, ?>) obj;
System.out.println("President name \t Description");
for (Map.Entry<?, ?> president : presidents.entrySet()) {
System.out.printf("%s \t %s %n", president.getKey(), president.getValue());
}
}
} catch (FileNotFoundException fnfe) {
System.err.println("cannot create a file with the given file name ");
} catch (IOException ioe) {
System.err.println("an I/O error occurred while processing the file");
} catch (ClassNotFoundException cnfe) {
System.err.println("cannot recognize the class of the object - is the file corrupted?");
}
}
}

Outputs:

President name Description
Barack Obama 2009 to --, Democratic Party, 56th term 
George W. Bush 2001 to 2009, Republican Party, 54th and 55th terms 
Bill Clinton 1993 to 2001, Democratic Party, 52nd and 53rd terms