Angelika Langer - Training & Consulting
HOME | COURSES | TALKS | ARTICLES | GENERICS | LAMBDAS | IOSTREAMS | ABOUT | NEWSLETTER | CONTACT | Twitter | Lanyrd | Linkedin
About Angelika Langer  
HOME 
GENERICS 

LAMBDAS

    CONTENT
    FAQ
    LAMBDA TUTORIAL
    LAMBDA REFERENCE
    STREAM TUTORIAL
    STREAM REFERENCE
 
IOSTREAMS 
ABOUT 
NEWSLETTER 
CONTACT
Appendix

This is a webpage devoted to lambda expressions in Java (a new language feature) and streams (new abstractions in the JDK's collection framework) - both were added to Java on March 18, 2014 with release 8. If you want to provide feedback or have any questions regarding lambda expressions in Java feel free to send me EMAIL or use the LAMBDA QUESTION form.
The Lambda Tutorial is available in PDF format (330KB) and in EPUB format (410KB) .
The Lambda Reference (note: it is an incomplete draft version) is available in PDF format (1200KB) .


Keep in mind that part of the Lambda/Streams Tutorial & References is still in draft version.

Appendix

Appendix

Source Code of Fluent Programming Case Study

Abstractions Used in the Example
public interface Person {

    public enum Gender { MALE, FEMALE };

    public int    getAge();

    public String getName();

    public Gender getGender();

}

public interface Employee extends Person {

    public long   getSalary();

}

public interface Manager extends Employee {

}

public interface Department {

    public enum Kind {SALES, DEVELOPMENT, 

                      ACCOUNTING, HUMAN_RESOURCES}

    public Department.Kind getKind();

    public String          getName();

    public Manager         getManager();

    public Set<Employee>   getEmployees();

}

public interface Corporation {

    public Set<Department> getDepartments();

}


 
 
Imperative & Sequential
/*

*  find all managers of all departments with an employee 

*  older than 65

*/

Manager[] find(Corporation c) {

               List<Manager> result = new ArrayList<>();

               for (Department d : c.getDepartments()) {

                              for (Employee e : d.getEmployees()) {

                                             if (e.getAge() > 65) {

                                                            result.add(d.getManager());

                                             }

                              }

               }

               return result.toArray(new Manager[0]);

}


 
 
Declarative & Sequential
/*

*   find all managers of all departments with an employee 

*   older than 65

*/

Manager[] find(Corporation c) {

  return

  c.getDepartments().stream()                                // 1

                    .filter(d -> d.getEmployees().stream()   // 2

                                  .map(Employee::getAge)     // 3

                                  .anyMatch(a -> a>65))      // 4

                    .map(Department::getManager)             // 5

                    .collect(Collectors.toList())            // 6

                    .toArray(new Manager[0]);                // 7

}


 
 
Declarative & Parallel
/*

*   find all managers of all departments with an employee 

*   older than 65

*/

Manager[] find(Corporation c) {

  return

  c.getDepartments(). parallelStream ()                        // 1

                    .filter(

                      d -> d.getEmployees(). parallelStream () // 2

                    .map(Employee::getAge)                   // 3

                    .anyMatch(a -> a>65))                    // 4

  .map(Department::getManager)                               // 5

  .collect(Collectors.toList())                              // 6

  .toArray(new Manager[0]);                                  // 7

}


 
 
Imperative & Parallel
/*

*   find all managers of all departments with an employee 

*   older than 65

*/

    private static Manager[] find(Corporation c) {

        class FinderTask extends RecursiveTask<List<Manager>> {

            private final Department[] departments;

            private final int from, to;

            private final int targetBatchSize = 2;

            public FinderTask(Department[] departments,

                              int from, int to)   {

                this.departments = departments;

                this.from = from;

                this.to = to;

            }

            private List<Manager> findSequentially() {

                List<Manager> result = new ArrayList<>();

                 for (int i=from;i<to;i++) {

                     Department d =  departments[i];

                    for (Employee e : d.getEmployees()) {

                        if (e.getAge() > 65) {

                            result.add(d.getManager());

                        }

                    }

                }

                return result;

            }

            public List<Manager> compute() {

                if (to-from < targetBatchSize)  

                    return findSequentially();

                int half = (to-from)/2;

                FinderTask task1 

                  = new FinderTask(departments,from,from+half);

                FinderTask task2 

                  = new FinderTask(departments,from+half,to);

                invokeAll(task1,task2);

                try {

                    List<Manager> result = task1.get();

                    result.addAll(task2.get());

                    return result;

                } catch (final InterruptedException | 

                               ExecutionException e) {

                    throw new RuntimeException(e);

                }

            }

        }

        Department[] departments 

           = c.getDepartments().toArray(new Department[0]);

        return ForkJoinPool

              .commonPool()

              .invoke(new FinderTask(departments,0, 

                                     departments.length))

              .toArray(new Manager[0]);

    }


 

Source Code of Execute-Around-Method Pattern Case Study

Helper Methods and Functional Interfaces
public class Utilities {

    @FunctionalInterface

    public static interface VoidCriticalRegion {

        void apply();

    }

    public static void withLock(

       Lock lock, 

       VoidCriticalRegion region) {

        lock.lock();

        try {

            region.apply();

        } finally {

            lock.unlock();

        }

    }

    @FunctionalInterface

    public static i nterface IntCriticalRegion {

        int apply();

    }

    public static int withLock(

       Lock lock,

       IntCriticalRegion region)  {

        lock.lock();

        try {

            return region.apply();

        } finally {

            lock.unlock();

        }

    }

    @FunctionalInterface

    public static interface VoidIOECriticalRegion {

        void apply() throws IOException;

    }

    public static void withLockAndIOE(

       Lock lock,                   

       VoidIOECriticalRegion region) 

       throws IOException {

        lock.lock();

        try {

            region.apply();

        } finally {

            lock.unlock();

        }

    }

}


 
 
IntStack Class
public class IntStack {

        private Lock lock = new ReentrantLock();

        private int[] array = new int[16];

         private int sp = -1;

        private void resize() {

             // todo later - for now throw index out of bounds

            array[sp] = 0;

        }

        public void push(int e) {

            withLock(lock, () -> {

                if (++sp >= array.length)

                    resize();

                array[sp] = e;

            });

        }

        public int pop() {

            return withLock(lock, () -> {

                if (sp < 0)

                    throw new NoSuchElementException();

                else

                    return (array[sp--]);

            });

        }

}


CONTENT   NEXT     INDEX
  © Copyright 1995-2013 by Angelika Langer.  All Rights Reserved.    URL: < http://www.AngelikaLanger.com/Lambdas/LambdaTutorial/lambdatutorial_7.html  last update: 8 May 2013