PANAYA

kn0wl3d93 sH4RIn'

14-07-2015

Something before we start...

Fun fact of the day

JAVA Stupidity... or not ?

for(int i = 0; i < 1000 ; ++i)
{
    Integer x = i;
    Integer y = i;

    if(x == y) {
        System.out.println("True");
    } else {
        System.out.println("False");        
    }
}

a "for" loop - assigning same iteration number to two seemingly different objects

Guess ?

So apparently...

for i

What does "cached" means

The same object ("reference") would be returned from "new" operation for those Integers !

Actually - this is a guaranty  by the JRE - but it's possible some JRE implementations would cache a bigger portion

-128 < i < 127 : Integers are "cached" by the JRE
   128 < i       : Integers are not "cached"

Moral

Obviously - use ".equals", or get the int value

Java supports implementation based bugs :)

{CSS}

<html>

(javascript)

$jQuery

Java 8

a small intro into features...

or - How I wish it was c#

Lambda Expressions

λ

So... we have a "Person" Class

  • We have a bunch of them in a list
  • We want to do something with them - let's say - PRINT :)
public class Person {

    public enum Sex {
        MALE, FEMALE
    }

    String name;
    LocalDate birthday;
    Sex gender;
    String emailAddress;

    public int getAge() {
        // ...
    }

    public void printPerson() {
        // ...
    }
}

Approach 1

public static void printPersonsOlderThan(List<Person> roster, int age) {
    for (Person p : roster) {
        if (p.getAge() >= age) {
            p.printPerson();
        }
    }
}

Method...

  • Readability - seems OK
  • Extentiability - No

Approach 2

public static void printPersonsWithinAgeRange(List<Person> roster, int low, int high) {
    for (Person p : roster) {
        if (low <= p.getAge() && p.getAge() < high) {
            p.printPerson();
        }
    }
}

Method - generalized...

  • Readability - same as before
  • Extentiability - Still no

Approach 3

public static void printPersons(List<Person> roster, CheckPerson tester) {
    for (Person p : roster) {
        if (tester.test(p)) {
            p.printPerson();
        }
    }
}

Let's Class it (Specify Search Criteria Code in a Local Class)

  • Readability - getting cumbersome
    • So many classes...
  • Extentiability - to some extent
    • less rewrite for changes...
interface CheckPerson {
    boolean test(Person p);
}
class CheckPersonEligibleForService implements CheckPerson {
    public boolean test(Person p) {
        return p.gender == Person.Sex.MALE &&
            p.getAge() >= 18 &&
            p.getAge() <= 25;
    }
}
printPersons(roster, new CheckPersonEligibleForSelectiveService());

And finally

Approach 4

printPersons(
    roster,
    new CheckPerson() {
        public boolean test(Person p) {
            return p.getGender() == Person.Sex.MALE
                && p.getAge() >= 18
                && p.getAge() <= 25;
        }
    }
);

Let's Class it (Specify Search Criteria Code in an Anonymous Class)

  • Readability - less code
    • still bulky - remember that the interface has only ONE method 
  • Extentiability - Still no
interface CheckPerson {
    boolean test(Person p);
}

Still need this:

Approach 5

printPersons(
    roster,
    (Person p) -> p.getGender() == Person.Sex.MALE
        && p.getAge() >= 18
        && p.getAge() <= 25
);

The Lambda way (Specify Search Criteria Code with a Lambda Expression)

  • Readability - NO CLASS !!
    • ​but why do we need the interface ?
  • Extentiability - YES
interface CheckPerson {
    boolean test(Person p);
}

Still need this:

Approach 6

public static void printPersonsWithPredicate(
    List<Person> roster, Predicate<Person> tester) {
    for (Person p : roster) {
        if (tester.test(p)) {
            p.printPerson();
        }
    }
}

The Lambda way (Use Standard Functional Interfaces with Lambda Expressions)

  • Readability - NO CLASS & no INTERFACE
  • Extentiability - YES, but we can do better
interface Predicate<T> {
    boolean test(T t);
}

JDK defines several standard functional interfaces:

look in java.util.function

Change the print method:

use same approach as "5" to invoke

Approach 7

public static void processPersons(
   List<Person> roster,
   Predicate<Person> tester,
   Consumer<Person> block) {
        for (Person p : roster) {
            if (tester.test(p)) {
                block.accept(p);
            }
        }
}

MORE LAMBDAS (...)

  • Readability - err... ok...
  • Extentiability - over kill ;)
processPersons(
     roster,
     p -> p.getGender() == Person.Sex.MALE
         && p.getAge() >= 18
         && p.getAge() <= 25,
     p -> p.printPerson()
);
public static void processPersonsWithFunction(
    List<Person> roster,
    Predicate<Person> tester,
    Function<Person, String> mapper,
    Consumer<String> block) {
    for (Person p : roster) {
        if (tester.test(p)) {
            String data = mapper.apply(p);
            block.accept(data);
        }
    }
}
processPersonsWithFunction(
    roster,
    p -> p.getGender() == Person.Sex.MALE
        && p.getAge() >= 18
        && p.getAge() <= 25,
    p -> p.getEmailAddress(),
    email -> System.out.println(email)
);

Approach 8

Some Generics (...)

  • Readability - err... yicks...
  • Extentiability - same
public static <X, Y> void processElements(
    Iterable<X> source,
    Predicate<X> tester,
    Function <X, Y> mapper,
    Consumer<Y> block) {
    for (X p : source) {
        if (tester.test(p)) {
            Y data = mapper.apply(p);
            block.accept(data);
        }
    }
}
processElements(
    roster,
    p -> p.getGender() == Person.Sex.MALE
        && p.getAge() >= 18
        && p.getAge() <= 25,
    p -> p.getEmailAddress(),
    email -> System.out.println(email)
);

Approach 9

Aggregate Operations

  • Readability - YES
  • Extentiability - YES
roster
    .stream()
    .filter(
        p -> p.getGender() == Person.Sex.MALE
            && p.getAge() >= 18
            && p.getAge() <= 25)
    .map(p -> p.getEmailAddress())
    .forEach(email -> System.out.println(email));

The operations filtermap, and forEach are aggregate operations.

Aggregate operations process elements from a stream - a "pipeline" of elements

Parallel Sorting

Speed up sorting !!!

The Concurrent way

// the normal way
Array.sort(myArray);
// the awesome way
Arrays.parallelSort(myArray);

The normal way

What will happen ?

  • automatically break up the target collection into several parts
  • each part sorted independently across number of cores
  • than - group back togeteher

PROS

Use more cores/threads

CONS

In highly multi-threaded environments (App-Server) - context-switch is not a friend...

but in the Utils-Server - this might be cool

Date API

java.util.date

one of the most hated classes...

ever...

adding to the "sasspool" - SimpleDateFormatter, Calander and many more

old API

  • No thread safety
  • poor API design - confusing
    • years start at 1900, months at 1, days at 0
    • "Date" class refers to a date ?
    • Date is actually a wrapper around number of milliseconds (UNIX epoch) - call ".toString" - the result suggests it has a TZ ?

new API

  • Immutable-value classes
    • value is saved internally
    • API of class does not support change of internal value
    • invoking a method - returns new instance
  • Domain-Driven design
    • "Date"/"Time" class

We'll not go over it

Let's just say

  • it's better
  • it's functional
  • there's a "bridge" from old Date to new Date

Optional References

Optional<User> tryFindUser(int userID) {
...
}

Tired of null-pointer exceptions ?

if(person.isPresent()){
  System.out.println(person.get());
}

Default Methods

NEXT LECTURE...

PANAYA - KNLG-SHRNG - 14/07/2015

By Amir Gal-Or

PANAYA - KNLG-SHRNG - 14/07/2015

Java 8 - new Date API - Optional References - Lambda expressions - Virtual Interface - Parallel Ops

  • 890