Summary: Effective Java By Joshua Bloch

I have taken notes while reading the book “Effective Java 3rd edition”.

Refer below my github link to refer the same.

https://github.com/dkbalachandar/effective-java-notes

Advertisements

Wilson’s Theorem to find prime number

Wilson’s Theorem states that a natural number is p > 1 is a prime number if only if the below condition is met.


  (p - 1) ! ≡  -1   mod p 
 OR  (p - 1) ! ≡  (p-1) mod p

For example, Take p as 4
(4 – 1)! = 3 ! => 3 * 2 * 1 = 6
(6 % 4) != 3 => 6 not equals to 3
So p is not a prime number.

Take p as 5
(5-1)! = 4 ! => 4*3*2*1 = 24
24%5 == 4
4 == 4
So p is a prime number.

Refer the below code to know how to do with a java program.


import java.util.Scanner;

public class PrimeFInder {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        int number = scanner.nextInt();
        System.out.println("The entered number is "+number);

        //  (p - 1) ! ≡  (p-1) mod p
        int lhs = getFactorialValue(number- 1) % number;
        int rhs = number - 1;
        if(lhs == rhs){
            System.out.println("Its a prime number");
        }else{
           System.out.println("Its an non prime number");
        }
    }

    private static int getFactorialValue(int n) {
        int value = 1;
        for (int i = 1; i <= n; i++) {
            value *= i;
        }
        return value;
    }
}

The output is given below,


12
The entered number is 12
Its an non prime number


Unroll annotation in Spock Testing framework

Spock is a testing framework for Java and Groovy application. This is a best alternative to Junit. In this post, Let’s see how we can use Unroll annotation of spock framework with an example.

Let’s assume that we have a class called “MathOperation” contains methods to perform arithmetic operations and we have a spock test class to test those methods.

MathOperation.java


public class MathOperation {
    
    private MathOperation(){
        
    }

    public static int sum(int a, int b) {
        return a + b;
    }

    public static int divide(int a, int b) {
        return a / b;
    }

    public static int multiply(int a, int b) {
        return a * b;
    }

    public static int minus(int a, int b) {
        return a - b;
    }
}


The spock test for testing the ‘sum’ method is as below.


import spock.lang.Specification

class MathOperationSpec extends Specification {

    def "sum of two numbers"() {

        expect:
        int actual = MathOperation.sum(num1, num2);
        actual == expected

        where:

        num1 | num2 | expected
        1    | 2    | 3
        2    | 3    | 5
    }

When we run this test case, the test run will look like below,

spock-withouunroll

When an error happened, we are not sure which line caused the problem. It will report only the error method but would not give the information about the exact line. The Unroll annotation helps to fix this problem. Unroll annotation has no effect on how the method gets executed but its an alternation in reporting.

Lets rewrite the above test with Unroll annotation as below.


import spock.lang.Specification
import spock.lang.Unroll

class MathOperationSpec extends Specification {

    @Unroll
    def "sum of two numbers #num1 #num2"() {

        expect:
        int actual = MathOperation.sum(num1, num2);
        actual == expected

        where:

        num1 | num2 | expected
        1    | 2    | 3
        2    | 3    | 5
    }
}

When we run the above one, it will look like below,
spock-withunroll

Scala foldLeft and foldRight functions

In this post, I am going to give some examples which explain how to use foldLeft and foldRight functions.

def foldLeft[B](z: B)(op: (B, A) ⇒ B): B – Applies a binary operator to a start value and all elements of this sequence, going left to right.

def foldRight[B](z: B)(op: (A, B) ⇒ B): B – Applies a binary operator to all elements of this list and a start value, going right to left.

Assume that you have a list and you want to add/multiply all the elements. We can use foldLeft function to do that. The order of traversing a list is from left to right. We can specify the initial value as well. Refer the below example.


object ScalaEx {
  def main(args: Array[String]): Unit = {

    val list = List(10, 10, 5)
    val total = list.foldLeft(1) {
      _ * _
    }
    println(s"Total::$total")

    val names = List("name1", "name2", "name3")
    val allNames = names.foldLeft("")((x, y) => x + " " + y)
    println(s"allNames::$allNames")
  }

}

The output is given below,



Total::500
allNames:: name1 name2 name3

In the above example, we have used foldLeft to multiply the value of a list and then reduce it to a single value and join a list.

The foldRight works the same way but the order of traversing a list is from right to left. Refer the below example to know it.



object ScalaEx {
  def main(args: Array[String]): Unit = {

    val names = List("name1", "name2", "name3")
    val allNamesFR = names.foldRight("")( (elem, acc) => acc + " " + elem )
    println(s"allNames with foldRight::$allNamesFR")

    val allNamesFL = names.foldLeft("")( (acc, elem) => acc + " " + elem )
    println(s"allNames with foldLeft::$allNamesFL")

  }

}


The output is given below,


allNames with foldRight:: name3 name2 name1
allNames with foldLeft:: name1 name2 name3


Scala List

In this post, we are going to see how we can merge two lists, append/prepend an element to a list.

We have various functions available to play with Scala List.

1. ::: or ++ operator to join two lists.
2. :+ and +: operators are used for append/prepend a value to a list(This will return a new list instance)


object Scala {

  def main(args: Array[String]): Unit = {

    //With ::: operator
    val list1 = List(1, 2, 3)
    val list2 = List(4, 5, 6)

    val joinList1 = list1 ::: list2
    println("joinList1::" + joinList1)


    //With ++ operator
    val joinList2 = list1 ++ list2
    println("joinList2::" + joinList2)


    //To append a value to an existing list use :+
    val appendList = list2 :+ 7
    println("appendList::" + appendList)


    //To prepend a value to an existing list
    val prependList =  3 +: list2
    println("prependList::" + prependList)

  }

}


The output is given below,


joinList1::List(1, 2, 3, 4, 5, 6)
joinList2::List(1, 2, 3, 4, 5, 6)
appendList::List(4, 5, 6, 7)
prependList::List(3, 4, 5, 6)

Scala zip/unzip function

Zip function is used to aggregate the contents of two lists into a single list of pairs.

Consider that, we have two lists one contain the list of tasks and another contains list of person names. We want to create another list contains person and task pair. Let see how we can use zip function to do this.

Refer the below example,


object ScalaMain {

  def main(args: Array[String]): Unit = {

    val taskList = List("task1", "task2", "task3")
    val personList = List("Peter", "John", "Patrick")

    val personWithTaskList = personList zip taskList

    personWithTaskList.foreach {
      case (person, task) =>
        println(s"$task is assigned to $person")
    }
  }
}


The output is given below,


task1 is assigned to Peter
task2 is assigned to John
task3 is assigned to Patrick

Unzip function will work as reverse of zip. Refer the below code and its output.



    val unzippedList = personWithTaskList unzip

    println(s"list of persons:${unzippedList._1}")
    println(s"list of tasks:${unzippedList._2}")


Output:


list of persons:List(Peter, John, Patrick)
list of tasks:List(task1, task2, task3)

As the “zip” function creates a pair, it will omit all the unpaired elements. Refer the below example,


object ScalaMain {

  def main(args: Array[String]): Unit = {

    val taskList = List("task1", "task2", "task3")
    val personList = List("Peter", "John", "Patrick", "Joe")

    val personWithTaskList = personList zip taskList

    personWithTaskList.foreach {
      case (person, task) =>
        println(s"$task is assigned to $person")
    }
  }

}


The output of the above program is given below,


task1 is assigned to Peter
task2 is assigned to John
task3 is assigned to Patrick


Spark Cogroup

Spark Cogroup: When called on datasets of type (K, V) and (K, W), returns a dataset of (K, (Iterable, Iterable)) tuples. This operation is also called groupWith.

In this post, we are going to see how we can use Spark Cogroup with an example.

Cogroup can be used to join multiple pair RDD’s. Assume that we have three paid RDD’s such as employeeRdd contains the list of employee objects, addressRdd contains the list of address objects and departmentRdd contains the list of department objects. The key for these Rdd’s are empId. Now we want to join all these Rdd’s with a cogroup command.

case class declaration:


  case class Employee(name: String, empId: String)
  case class Address(streetAddress: String, city: String, zipCode:String, empId: String)
  case class Department(department: String, empId: String)


In the below code, we use the above case classes and a cogroup to join multiple Rdd’s. Here, the departmentRdd does not contain the department details for empId “4” so when we use a cogroup, it returns an empty list for department object and list of address object for empId “4”



 val employeeRdd = sc.parallelize(
        List(
          ("1", Employee(name = "John", empId = "1")),
          ("2", Employee(name = "Peter", empId = "2")),
          ("3", Employee(name = "Adam", empId = "3")),
          ("4", Employee(name = "Wade", empId = "4"))
        ))

      val addressRdd = sc.parallelize(List(
        ("1", Address("Walker St", "Columbus", "43202", "1")),
        ("2", Address("Runner St", "Columbus", "43202", "2")),
        ("3", Address("Long St", "Columbus", "43202", "3")),
        ("4", Address("River St", "Columbus", "43202", "4"))
      ))

      val departmentRdd = sc.parallelize(List(
        ("1", Department("Sales", "1")),
        ("2", Department("Engg", "2")),
        ("3", Department("Marketing", "3"))))

      val employeeDetails = employeeRdd.cogroup(addressRdd, departmentRdd)
        .mapValues { case (employees, addresses, departments) => (employees.head, addresses.toList, departments.toList) }

      employeeDetails.collect().foreach(println)


The output is given below,


(4,(Employee(Wade,4),List(Address(River St,Columbus,43202,4)),List()))
(1,(Employee(John,1),List(Address(Walker St,Columbus,43202,1)),List(Department(Sales,1))))
(2,(Employee(Peter,2),List(Address(Runner St,Columbus,43202,2)),List(Department(Engg,2))))
(3,(Employee(Adam,3),List(Address(Long St,Columbus,43202,3)),List(Department(Marketing,3))))