Java notes

Table of Contents

This is my notes and learning materials for Java and the development environment around it. The setup is the following: Emacs, Maven, OpenJDK 8 and Arch GNU/Linux.

1 Install Java on Arch

Install OpenJDK and Maven, as Maven have dependencies to OpenJDK they will be installed at the same time.

pacman -S maven
pacman -Ss maven

2 Set up Java for Emacs

I havent got a good working Java environment in Emacs yet. But here are some of the resources that i am working with.

Org-babel with Java is working good.

Here is a small example on how to use Org-babel with Java:

#+HEADERS: :classname Main
#+BEGIN_SRC java :results output
  import java.util.function.Consumer;
  public class Main {
      public static void main(String [] args) {
          System.out.println("Hello World");
      }
  }
#+END_SRC

2.2 Eclim

Eclim bin is located in:

/usr/lib/eclipse/plugins/org.eclim_2.6.0/bin

3 Maven

Apache Maven is a project management tool for Java.

Create Maven project structure:

mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=lnu.jherrlin -DartifactId=assignment1

Install dependencies:

mvn eclipe:eclipse is used for eclim to recognize that its a eclipse project.

mvn install
mvn eclipse:eclipse

Run application:

mvn exec:java -Dexec.mainClass="lnu.jherrlin.App"

4 Open JavaFX

Install JavaFX.

pacman -Ss javafx
pacman -S javafx

Find where the jar is located.

find / -type f -name "*jfxrt.jar*" 2> /dev/null

In Intellij. Add the path to the jfxrt.jar

Project Structure -> SDKs -> Add

5 The Java Language

5.1 Compare objects

public class Main{
    public static void main(String [] args){
        // Create new objects, they will have different
        // hashes even if they looks the same.
        String a = new String("Hejsan");
        String b = new String("Hejsan");
        System.out.println(System.identityHashCode(a));  // Get object hash
        System.out.println(System.identityHashCode(b));  // Get object hash
        System.out.println(a == b);  // Compares hash, false
        System.out.println(a.equals(b));  // Compares data, true

        // Create new primitive data types
        int c = 5;
        int d = 5;
        System.out.println(System.identityHashCode(c));  // Get object hash
        System.out.println(System.identityHashCode(d));  // Get object hash
        System.out.println(c == d);  // Compares hash, true
    }
}

5.2 Elvis operator

The “Elvis” operator is a binay operator.

Example, if y - 1 is less than 0, set y to 6. else set y to y - 1.

public class Main{
    public static void main(String [] args){
        // Example 1
        int y = 0;
        y = ( y - 1 % 6 ) < 0 ? 6 : y - 1;
        System.out.println(y);

        // Example 2
        int a = 1;
        System.out.println(a == 1 ? true : false);  // true
        a = 2;
        System.out.println(a == 1 ? true : false);  // false
    }
}

5.3 Recursive functions

Recursive functions are functions that call them self. A recursive function always needs a base case that it will end with. If no base case is provided the function will call itself forever and the application will crash.

5.3.1 SumMain

public class Main {
    public static int SumRec(int start, int stop){
        if (stop == start){  // Base case
            return start;
        }
        return SumRec(start, (start + stop)/ 2) + SumRec(((start+stop)/2)+1, stop);
    }

    public static void main(String[] args){
        System.out.print(SumRec(1,5));
    }
}

5.3.2 Calculate a triangle’s area

Calculate a triangle’s area with recursion. Split the triangle into smaller triangles and add them.

public class Main{
    public static void main(String [] args){
        Triangle t = new Triangle(10);
        int area = t.getArea();
        System.out.println("Area: "+area);
        System.out.println("Expected: 55");
    }
}

class Triangle{
    private int width;

    public Triangle(int aWidth){
        width = aWidth;
    }

    public int getArea(){
        if (this.width <= 0)
            return 0;
        else if (this.width == 1)
            return 1;
        else {
            Triangle t = new Triangle(this.width - 1);
            int smallerArea = t.getArea();
            return smallerArea + this.width;
        }
    }
}

5.3.3 Palindrome

public class Main{
    private static boolean isPalindrome(String text){
        int length = text.length();
        if (length <= 1)
            return true;
        else{
            char first = Character.toLowerCase(text.charAt(0));
            char last = Character.toLowerCase(text.charAt(length - 1));
            if (Character.isLetter(first) && Character.isLetter(last)){
                if (first == last){
                    String shorter = text.substring(1, length -1);
                    return isPalindrome(shorter);
                }
                else{
                    return false;
                }
            }
            else if (!Character.isLetter(last)){
                String shorter = text.substring(0, length - 1);
                return isPalindrome(shorter);
            }
            else{
                String shorter = text.substring(1);
                return isPalindrome(shorter);
            }
        }
    }

    public static void main(String [] args){
        System.out.println(isPalindrome("aba"));
        System.out.println(isPalindrome("abba"));
        System.out.println(isPalindrome("A man, a plan, a canal, Panama!"));
        System.out.println(isPalindrome("Not a palindrome."));
    }
}

5.3.4 Recursive permutations

Calculate the permutations of “eat” with help of recursion.

import java.util.ArrayList;
public class Main{

    public static void main(String [] args){
        for (String s: permutations("eat")){
            System.out.println(s);
        }
    }

    public static ArrayList<String> permutations(String word){
        ArrayList<String> result = new ArrayList<String>();
        if (word.length() == 0){
            result.add(word);
            return result;
        }
        else{
            for (int i = 0; i < word.length(); i++){
                String shorter = word.substring(0, i) + word.substring(i + 1);
                ArrayList<String> shorterPermutations = permutations(shorter);
                for (String s: shorterPermutations){
                    result.add(word.charAt(i) + s);
                }
            }
        }
        return result;
    }
}

5.4 Lambdas and related

5.4.1 Introduction

Lambdas can be used on collections.

Here is a simple example of how to sum an array of doubles with the help of a stream:

import java.util.Arrays;

public class Main{
    public static void main(String [] args){
        double[] numbers = {1, 2, 3, 4, 5};

        // Old way
        double total = 0;
        for (double d : numbers)
            total += d;
        System.out.println(total);

        // Lambda way
        double total2 = Arrays.stream(numbers).sum();
        System.out.println(total2);
    }
}

5.4.2 Check out

What is boxed()?

public class Main{
    public static void main(String [] args){
        int[] ints = {1,2,3};
        List<Integer> list = IntStream.of(ints).boxed().collect(Collectors.toList());
    }
}

5.4.3 Runnable

Super small example using Runnable. We attach a lambda function to a Runnable variable called really. The lambda function will be evaluated but wont run until we call really.run(). Runnable is often used together with threads.

public class Main{
    public static void main(String [] args){
        Runnable really = () -> System.out.println("Really!");
        really.run();
    }
}

5.4.4 Comparator

A Comparator can be used together when sorting arrays.

Sort array by length of string, longest first:

import java.util.Comparator;
import java.util.Arrays;

public class Main{
    public static void main(String [] args){
        String[] COUNTRIES =  {"Afghanistan", "USA", "Sweden", "American Samoa", "Andorra"};
        Comparator<String> longestName = (s1,s2) -> Integer.compare(s2.length(), s1.length());
        Arrays.sort(COUNTRIES, longestName);
        for (String s: COUNTRIES)
            System.out.println(s);
    }
}

Sort array by length of string, smallest first:

import java.util.Comparator;
import java.util.Arrays;

public class Main{
    public static void main(String [] args){
        String[] COUNTRIES =  {"Afghanistan", "USA", "Sweden", "American Samoa", "Andorra"};
        Comparator<String> longestName = (s1,s2) -> Integer.compare(s1.length(), s2.length());
        Arrays.sort(COUNTRIES, longestName);
        for (String s: COUNTRIES)
            System.out.println(s);
    }
}

Sort array by most ’A’s:

import java.util.Arrays;
import java.util.Comparator;
import java.util.function.Function;

public class Main{
    public static void main(String [] args){
        String[] COUNTRIES =  {"Afghanistan", "USA", "Sweden", "American Samoa", "Andorra", "AAAAAA"};
        Function<String,Integer> numberOfAs = (x) ->
            x.toUpperCase().chars().filter(c -> (char) c == 'A').sum();
        Comparator<String> countAs = (s1,s2) -> Integer.compare(numberOfAs.apply(s2), numberOfAs.apply(s1));       // Must be updated
        Arrays.sort(COUNTRIES,countAs);
        System.out.println("Country names containing most As (either A or a)");
        for (String s: COUNTRIES)
            System.out.println(s);
    }
}

5.4.5 Consumer

accept
andThen

Consumer interface represents an operation that accepts a single input argument and returns no result. A Consumer does not return anything! In the example below we are printing the arguments to accept().

import java.util.function.Consumer;

public class Main {
    public static void main(String [] args) {
        Consumer<String> c = (x) -> System.out.println(x.toLowerCase());
        c.accept("HEJSAN");
        c.accept("KODKOLLEKTIVET\nLNU");
    }
}

A Consumer can even take method as reference. This does the same as above.

import java.util.function.Consumer;
import java.lang.Character;

public class Main {
    public static void main(String [] args) {
        Consumer<String> toPrint = (System.out::println);
        toPrint.accept("Hejsan");
        toPrint.accept("Kodkollektivet\nLNU");
    }
}

There are three principle cases here:

object::instanceMethod  
Class::staticMethod  
Class::instanceMethod  
::new Refer to the constructor

A Consumer can also take a lambda expression.

import java.util.function.Consumer;

public class Main {
    public static void main(String [] args) {
        Consumer<String> c = (x) -> System.out.println(x.toLowerCase());
        c.accept("HEJSAN");
        c.accept("KODKOLLEKTIVET\nLNU");
    }
}

A Consumer can be passed as an argument to a function. This way we can modify a list of Students very easy.

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class Main {
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(new Student("John", 1),
                                               new Student("Mark", 2));
        acceptAllEmployee(students, e -> System.out.println(e.name));
        acceptAllEmployee(students, e -> { e.age *= 2; });
        acceptAllEmployee(students, e -> System.out.println(e.name + ": " + e.age));
    }

    public static void acceptAllEmployee(List<Student> student, Consumer<Student> printer) {
        for (Student e : student) {
            printer.accept(e);
        }
    }
}
class Student {
    public String name;
    public Integer age;

    Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

5.4.6 Supplier

get

A Supplier dont have any arguments but returns an object. Here is a simple example with just String as return.

import java.util.function.Supplier;

public class Main {
  public static void main(String[] args) {
    Supplier<String> i  = ()-> "Kodkollektivet.se";
    System.out.println(i.get());
  }
}

5.4.7 Predicate

test
and
negate
or
isEqual

Predicate represents a predicate, which is boolean-valued function, of one argument.

import java.util.function.Predicate;

public class Main {
    public static void main(String[] args) {
        Predicate<String> isLongerThan5 = (s)-> s.length() > 5;
        System.out.println(isLongerThan5.test("abcd"));
        System.out.println(isLongerThan5.test("abcde"));
        System.out.println(isLongerThan5.test("abcdef"));

        Predicate<Integer> isBiggerThan5 = (s)-> s > 5;
        System.out.println(isBiggerThan5.test(4));
        System.out.println(isBiggerThan5.test(5));
        System.out.println(isBiggerThan5.test(6));

    }
}

5.4.8 Function

andThen
apply
compose
identity

Function need only ONE argument.

import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        Function<String,Integer> length = (x) -> {
            String removeA = x.replace("A","");
            String removea = removeA.replace("a","");
            return x.length() - removea.length();};
        System.out.println(length.apply("Aaodkollektivet.se"));
    }
}

5.4.9 BiFunction

apply
andThen

BiFunction represents a function that needs TWO arguments and produces a result. This is the two-arity specialization of Function.

import java.util.function.BiFunction;
public class Main {
    public static void main(String[] args) {
        BiFunction<String,String,Integer> length = (x,y) -> {return x.length()+y.length();};
        System.out.println(length.apply("abc", "def"));
    }
}

5.4.10 Bigger examples

import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Supplier;

public class Main {
    public static void main(String [] args) {
        BiFunction<String,String,Integer> comp = (str1, str2) ->
            Integer.compare(str1.length(),str2.length());
        int res = comp.apply("Anakin Skywalker","Darth Vader");

        Consumer<String> valueOutput = value -> System.out.println(value+"");
        valueOutput.accept(res+"");

        Supplier<String> output = () -> "The End!";
        valueOutput.accept(output.get());
        Runnable really = () -> System.out.println("Now, really -- The End!");
        really.run();
    }
}
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        System.out.println("Part 1: Apply predicates");
        List<Integer> list = Arrays.asList(45, 3, 24, 16, 1, 1, 3, 8, 7, 6, 10, 12, 17, 22, 30);

        System.out.print("Print all numbers: ");
        Predicate<Integer> all = n -> true;
        selectAndPrint(list, all);

        System.out.print("\nPrint all odd numbers: ");
        Predicate<Integer> odd = n -> n % 2 != 0;
        selectAndPrint(list, odd);

        System.out.print("\nPrint all numbers greater than 10: ");
        Predicate<Integer> aboveTen = n -> n > 10;
        selectAndPrint(list, aboveTen);

        System.out.println("\n\nPart 2: Apply functions");
        List<Double> numbers = Arrays.asList(1.0, 16.0, 25.0, 81.0);
        System.out.println("Original: "+numbers);
        System.out.println("Square root: "+applyFunction(numbers, Math::sqrt));
        System.out.println("Power of two: " + applyFunction(numbers, Main::powerOfTwo));
    }

    // Prints all elements in the list where predicate evaluates to true
    public static void selectAndPrint(List<Integer> list, Predicate<Integer> predicate) {
        list.stream().filter(n -> predicate.test(n)).forEach(x -> System.out.print(x+","));
    }

    // Returns a new list containing the numbers resulting from applying fx
    // on the input list numbers
    private static List<Double> applyFunction(List<Double> numbers, Function<Double, Double> fx) {
        return numbers.stream().map(x -> fx.apply(x)).collect(Collectors.toList());
    }

    private static Double powerOfTwo(Double d) {
        return d * d;
    }
}

5.4.11 Streams

Stream operations:

filter
distinct
limit
map
sorted
reduce

Common terminal stream operations:

forEach
average
count
min
max
collect
toArray
findFirst
findAny
anyMatch
allMatch

To make it easier to use lambdas on collections, the Stream API was introduced. Much esier to parallelise. With the Stream API an additional type is introduced, Optional , with is a safer null. A stream looks superficially like an iterator. A stream is never mutated, its always returns a new stream with the new result.

Working with streams it done in two stages:

  1. Create the Stream
  2. Specify intermediate operations for transformations.
  3. Apply a terminal operation that produces a result.

In the example below we calculat the items, sum and average of the int array.

import java.util.Arrays;
import java.util.stream.IntStream;

public class Main {
    public static void main(String [] args) {
        int[] calc = {1,2,3,4,5};
        System.out.println(IntStream.of(calc).count());
        System.out.println(IntStream.of(calc).sum());
        System.out.println(IntStream.of(calc).average().getAsDouble());
    }
}

In the example below we use a String array and get back strings that are bigger than length of 4.

import java.util.Arrays;

public class Main {
    public static void main(String [] args) {
        String[] strings = new String[]{"Hejsan", "Hoppsan", "Nu", "Ska"};
        System.out.println(Arrays.stream(strings).filter( w -> w.length() > 4).count());
    }
}

In this example we calculate the pow of the int’s in an array.

import java.util.Arrays;

public class Main {
    public static void main(String [] args) {
        String[] strings = new String[]{"Hejsan", "Hoppsan", "Nu", "Ska"};
        System.out.println(Arrays.stream(strings).filter( w -> w.length() > 4).count());
    }
}

5.5 Testing with cobertura

Install dependencies in pom.xml.

<dependency>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>cobertura-maven-plugin</artifactId>
  <version>2.7</version>
</dependency>

Run the tests:

cobertura:cobertura

Author: John Herrlin

Created: 2017-04-27 Thu 14:48

Validate