├── .classpath ├── .project ├── README.md └── src └── com └── madhusudhan └── wr └── allaboutlambdas ├── advancedlambdas ├── ArrayReferences.java ├── Employee.java ├── ReferenceUtil.java └── References.java ├── advancedstreams ├── CustomCollector.java ├── GroupingAndPartitioning.java └── Stats.java ├── domain ├── Actor.java ├── Address.java ├── Book.java ├── Employee.java ├── EncryptedTrade.java ├── Manager.java ├── Movie.java ├── Patient.java ├── Student.java ├── Teacher.java ├── Trade.java └── Vehicle.java ├── functions ├── Consumers.java ├── Functions.java ├── Predicates.java ├── RecurringFunctions.java └── Suppliers.java ├── interfaces ├── Diner.java ├── DinerImpl.java ├── InheritanceRules.java ├── InheritanceRules2.java ├── InheritingBehaviour.java ├── Interfaces.java └── IntersectionTypes.java ├── introducinglambdas ├── DissectingLambda.java ├── GreetingExample.java ├── LambdaTasters.java └── TradeMerger.java ├── introduction ├── Examples.java ├── Runnables.java └── Streaming.java ├── newfeatures ├── Component.java ├── Finder.java ├── ParallelStreamsFeature.java ├── StreamsFeature.java ├── TradableLambda.java └── TradableLambdaUsingPredicate.java ├── parallellstreams ├── ParallelStreams.java └── PerformanceMeasurement.java ├── specialisedfunctions ├── BiConsumers.java ├── BiFunctions.java ├── BiPredicates.java ├── Primitives.java └── SpecialisedFunctions.java ├── streamoperations ├── OptionalType.java └── StreamCommonOperations.java ├── streams ├── DissectingStreams.java └── StreamsBasics.java ├── util ├── EmployeeUtil.java ├── MovieUtil.java └── TradeUtil.java ├── workingwithlambdas ├── CapturingLambda.java ├── EffectivelyFinalLambda.java ├── LambdaAnonymousScope.java ├── LambdaRedeclaringVariables.java ├── LambdaThisStaticSuperAccess.java └── SuperScope.java └── workingwithstreams ├── CreatingStreams.java ├── IterationStrategy.java ├── LazyAndEagerStreams.java └── PrimitiveStreams.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | AllAboutLambdas 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # All About Lambdas -- A Weekend Read 2 | All About Java 8 Lambdas Book Source Code 3 | 4 | Available on Amazon.com here http://www.amazon.com/All-About-Java-Lambdas-Introducing/dp/1517534585/ 5 | or Amazon.co.uk here: http://www.amazon.co.uk/All-About-Java-Lambdas-Introducing/dp/1517534585/ 6 | 7 | The project is a standalone Java project. Just import into your favourite IDE and start learning to code Java 8. Do note that you need Java 8 SDK required for compiling/running the code examples. Make sure you download the latest and great version of Java 8 as well as an IDE (I am currently using Eclipse MARS). 8 | 9 | The package structure is maintained such way that any code discussed in a chapter is attached/associated in the same package with the chapter name. For example, all the parallel processing code will reside in com.madhusudhan.wr.allaboutlambdas.parallellstreams where the last part is the chapter name. 10 | 11 | Please get in touch with me for any suggestions or recommendations in getting this reposiotry uptoday. Also please refer to my friend Mani's repo too(https://github.com/neomatrix369/LambdaExamples) should you require to work with more examples. 12 | 13 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/advancedlambdas/ArrayReferences.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.advancedlambdas; 2 | 3 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 4 | 5 | /** 6 | * Class that shows us how to use array references 7 | * @author mkonda 8 | * 9 | */ 10 | public class ArrayReferences { 11 | // Interface creating an array of Strings 12 | interface StringArray { 13 | String[] create(int size); 14 | } 15 | 16 | // Lambda without references 17 | StringArray sArrayLambda = (size) -> new String[size]; 18 | 19 | StringArray sArrayLambdaMethodRef = String[]::new; 20 | 21 | // Trades array 22 | interface TradeArray { 23 | Trade[] create(int size); 24 | } 25 | 26 | // Lambda using array references 27 | TradeArray tradesLambdaMethodRef = Trade[]::new; 28 | } 29 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/advancedlambdas/Employee.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.advancedlambdas; 2 | 3 | /** 4 | * Class to demonstrate the usage of constructor references 5 | * 6 | * @author mkonda 7 | * 8 | */ 9 | public class Employee { 10 | 11 | /** 12 | * An Employee created using an id 13 | * @param id 14 | */ 15 | public Employee(int id) { 16 | // Logic for creating an employee with an id 17 | } 18 | 19 | /** 20 | * An Employee created using an id and a name 21 | * @param id 22 | * @param name 23 | */ 24 | public Employee(int id, String name) { 25 | // Logic for creating an employee with an id and name. 26 | } 27 | 28 | /** 29 | * Interface representing the first constructor 30 | * @author mkonda 31 | * 32 | */ 33 | interface EmployeeById { 34 | public Employee create(int id); 35 | } 36 | 37 | /** 38 | * Interface representing the second constructor 39 | * @author mkonda 40 | * 41 | */ 42 | interface EmployeeByName { 43 | public Employee create(int id, String employee); 44 | } 45 | 46 | /** 47 | * Lambdas without using constructor references 48 | */ 49 | public void normalLambdaExpressions(){ 50 | // Lambda invoking the first constructor - no const refs 51 | EmployeeById empLambda = id -> new Employee(id); 52 | 53 | // Lambda invoking the second constructor - no const refs 54 | EmployeeByName empNameLambda = 55 | (id, name) -> new Employee(id, name); 56 | } 57 | 58 | /** 59 | * Lambdas with constructor references 60 | */ 61 | public void constructorReferencedLambdas(){ 62 | // Both have the same constructor reference 63 | 64 | // Constructor reference invocation for first constructor 65 | EmployeeById empLambdaConstRef = Employee::new; 66 | // Constructor reference invocation for second constructor 67 | EmployeeByName empNameLambdaConstRef = Employee::new; 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/advancedlambdas/ReferenceUtil.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.advancedlambdas; 2 | 3 | public class ReferenceUtil { 4 | 5 | public boolean isClassic(int movieId) { 6 | boolean isClassic = false; 7 | if (movieId < 1000) { 8 | isClassic = true; 9 | } 10 | return isClassic; 11 | } 12 | 13 | public static boolean isHorror(int movieId) { 14 | boolean isHorror = false; 15 | if (movieId > 10000 && movieId < 20000) { 16 | isHorror = true; 17 | } 18 | return isHorror; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/advancedlambdas/References.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.advancedlambdas; 2 | 3 | /** 4 | * Class to demonstrate the usage of method and constructor references 5 | * @author mkonda 6 | * 7 | */ 8 | public class References { 9 | 10 | /** 11 | * Movie checker functional interface 12 | * @author mkonda 13 | * 14 | */ 15 | interface MovieChecker { 16 | boolean check(int movieId); 17 | } 18 | 19 | 20 | interface Greeting { 21 | public String sayHello(String g); 22 | } 23 | 24 | /** 25 | * To check instance method reference 26 | */ 27 | private void instanceMethodRef() { 28 | ReferenceUtil util = new ReferenceUtil(); 29 | // Lambda version 30 | MovieChecker isClassic = movieId -> util.isClassic(movieId); 31 | // Instance Method Ref version 32 | MovieChecker isClassicLambda = util::isClassic; 33 | 34 | 35 | } 36 | 37 | private String greet(String s) { 38 | return null; 39 | } 40 | 41 | /** 42 | * Examples of method references 43 | */ 44 | private void exampleMethodReferences() { 45 | // Another example of a normal lambda 46 | Greeting greetingLambdaReference = s -> { 47 | return greet(s); 48 | }; 49 | 50 | // Lambda using a method reference. 51 | Greeting greetingLambdaReference2 = this::greet; 52 | 53 | // Or 54 | 55 | Runnable r = () -> print(); 56 | 57 | // using method references 58 | r = this::print; 59 | } 60 | 61 | private void print() { 62 | System.out.println(); 63 | } 64 | 65 | /** 66 | * To check static method 67 | */ 68 | private void staticMethodRef() { 69 | // Lambda version 70 | MovieChecker isClassic = movieId -> ReferenceUtil.isHorror(movieId); 71 | // Static Method Ref version 72 | MovieChecker isClassicLambda = ReferenceUtil::isHorror; 73 | } 74 | 75 | /** 76 | * To check arbitrary method reference functionality 77 | */ 78 | private void arbitraryMethodRef() { 79 | // Lambda version 80 | MovieChecker boxofficeHit = ArbitraryClass::isBoxOfficeHit; 81 | // Static Method Ref version 82 | MovieChecker isClassicLambda = ReferenceUtil::isHorror; 83 | 84 | } 85 | 86 | /** 87 | * An existing instance method to check if the movie falls in classic 88 | * category 89 | * 90 | * @param movieId 91 | * @return 92 | */ 93 | public boolean isClassic(int movieId) { 94 | boolean isClassic = false; 95 | if (movieId < 1000) { 96 | isClassic = true; 97 | } 98 | return isClassic; 99 | } 100 | 101 | /** 102 | * An existing instance method for checking if the movie is a horror movie 103 | * 104 | * @param movieId 105 | * @return 106 | */ 107 | 108 | } 109 | 110 | /** 111 | * Some arbitrary class that gets used by a lambda 112 | * @author mkonda 113 | * 114 | */ 115 | class ArbitraryClass { 116 | 117 | public static boolean isBoxOfficeHit(int movieId) { 118 | // logic in finding the box office collections goes here. 119 | return true; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/advancedstreams/CustomCollector.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.advancedstreams; 2 | import java.util.List; 3 | import java.util.function.BiConsumer; 4 | import java.util.function.Supplier; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 7 | import com.madhusudhan.wr.allaboutlambdas.util.TradeUtil; 8 | 9 | /** 10 | * Class demonstrating the functionality to create custom collectors 11 | * @author mkonda 12 | * 13 | */ 14 | public class CustomCollector { 15 | List trades = TradeUtil.createTrades(); 16 | 17 | /** 18 | * Create own collector of csv strings 19 | */ 20 | private void collectToCustomCollector() { 21 | // A supplier 22 | Supplier supplier = StringBuilder::new; 23 | 24 | // An accumulator 25 | BiConsumer accumulator = 26 | (sb, trade) -> sb.append(trade.getInstrument()).append(","); 27 | 28 | // A combiner 29 | BiConsumer combiner = 30 | (s1, s2) -> s1.append(s2.toString()); 31 | 32 | // Putting all together 33 | StringBuilder results = trades 34 | .stream() 35 | .collect(supplier, accumulator, combiner); 36 | 37 | System.out.println(results); 38 | 39 | } 40 | 41 | public static void main(String[] args) { 42 | new CustomCollector().collectToCustomCollector(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/advancedstreams/GroupingAndPartitioning.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.advancedstreams; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.stream.Collectors; 6 | 7 | import static java.util.stream.Collectors.groupingBy; 8 | import static java.util.stream.Collectors.partitioningBy; 9 | 10 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 11 | import com.madhusudhan.wr.allaboutlambdas.util.EmployeeUtil; 12 | 13 | /** 14 | * This class demonstrates the usage of groupingBy function 15 | * 16 | * @author mkonda 17 | * 18 | */ 19 | public class GroupingAndPartitioning { 20 | 21 | List employees = EmployeeUtil.createDetailedEmployees(); 22 | 23 | /** 24 | * Grouping by department function 25 | */ 26 | private void groupingByDepartment() { 27 | Map> deptEmployees = employees 28 | .stream() 29 | .collect(groupingBy(e -> e.getDepartment())); 30 | 31 | System.out.println(deptEmployees); 32 | } 33 | 34 | /** 35 | * Grouping by city 36 | */ 37 | private void groupingByCity() { 38 | Map> cityEmployees = employees 39 | .stream() 40 | .collect(Collectors.groupingBy(Employee::getCity)); 41 | System.out.println(cityEmployees); 42 | } 43 | 44 | /** 45 | * Multi-level grouping usage: group employees by department and city 46 | */ 47 | private void groupingByDeptAndCity() { 48 | Map>> deptAndCityEmployees = 49 | employees.stream() 50 | .collect(groupingBy((Employee::getDepartment), groupingBy(Employee::getCity))); 51 | System.out.println(deptAndCityEmployees); 52 | } 53 | 54 | private void partitionByExecutives() { 55 | Map> empPartition = employees 56 | .stream() 57 | .collect(Collectors.partitioningBy(Employee::isExecutive)); 58 | 59 | System.out.println(empPartition); 60 | } 61 | 62 | private void partitioningAndGrouping() { 63 | Map>> execEmployees = employees 64 | .stream() 65 | .collect(partitioningBy((Employee::isExecutive), groupingBy(Employee::getDepartment))); 66 | 67 | for(Boolean b: execEmployees.keySet()){ 68 | System.out.println(b+" --> "+execEmployees.get(b)); 69 | } 70 | } 71 | 72 | private void multiLevelPartitioning() { 73 | Map>> execEmployees = employees 74 | .stream() 75 | .collect( 76 | partitioningBy((Employee::isExecutive), 77 | partitioningBy(Employee::isSenior))); 78 | 79 | for(Boolean b: execEmployees.keySet()){ 80 | System.out.println(b+":"+execEmployees.get(b)); 81 | } 82 | 83 | } 84 | public static void main(String[] args) { 85 | // new GroupingAndPartitioning().groupingByDepartment(); 86 | // new GroupingAndPartitioning().groupingByCity(); 87 | // new GroupingAndPartitioning().groupingByDeptAndCity(); 88 | // new GroupingAndPartitioning().partitionByExecutives(); 89 | // new GroupingAndPartitioning().partitioningAndGrouping(); 90 | new GroupingAndPartitioning().multiLevelPartitioning(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/advancedstreams/Stats.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.advancedstreams; 2 | 3 | import java.util.IntSummaryStatistics; 4 | import java.util.List; 5 | import java.util.OptionalDouble; 6 | import java.util.OptionalInt; 7 | import java.util.stream.Collectors; 8 | import java.util.stream.IntStream; 9 | 10 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 11 | import com.madhusudhan.wr.allaboutlambdas.util.TradeUtil; 12 | 13 | public class Stats { 14 | IntStream streamOfInts = IntStream.range(1, 100); 15 | 16 | private void summaryOfTrades() { 17 | List trades = TradeUtil.createTrades(); 18 | IntSummaryStatistics s = trades 19 | .stream() 20 | .collect(Collectors.summarizingInt(Trade::getQuantity)); 21 | System.out.println(s); 22 | } 23 | 24 | private void usingRange() { 25 | IntStream ints = IntStream.range(10, 20); 26 | 27 | ints.forEach(s -> System.out.print(s+",")); 28 | } 29 | 30 | private void usingRangeClosed() { 31 | IntStream ints = IntStream.rangeClosed(10, 20); 32 | ints.forEach(s -> System.out.print(s+",")); 33 | } 34 | //Min, Max and Average 35 | private void minMaxAndAverage() { 36 | IntStream ints = IntStream.rangeClosed(10, 20); 37 | OptionalInt max = ints.max(); 38 | System.out.println("Max: "+max.getAsInt()); 39 | 40 | ints = IntStream.rangeClosed(10, 20); 41 | OptionalInt min = ints.min(); 42 | System.out.println("Min: "+min.getAsInt()); 43 | 44 | ints = IntStream.rangeClosed(10, 20); 45 | OptionalDouble avg = ints.average(); 46 | System.out.println("Min: "+avg.getAsDouble()); 47 | 48 | 49 | } 50 | 51 | public static void main(String[] args) { 52 | new Stats().summaryOfTrades(); 53 | // new Stats().usingRange(); 54 | new Stats().usingRangeClosed(); 55 | // new Stats().testMaxAndMin(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Actor.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | public class Actor { 4 | private String name = null; 5 | 6 | public Actor(String name) { 7 | setName(name); 8 | } 9 | 10 | public String getName() { 11 | return name; 12 | } 13 | 14 | public void setName(String name) { 15 | this.name = name; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return name; 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Address.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | public class Address { 4 | 5 | private String addressLine1 = null; 6 | private String addressLine2= null; 7 | private String country = null; 8 | private String code = null; 9 | public String getAddressLine1() { 10 | return addressLine1; 11 | } 12 | public void setAddressLine1(String addressLine1) { 13 | this.addressLine1 = addressLine1; 14 | } 15 | public String getAddressLine2() { 16 | return addressLine2; 17 | } 18 | public void setAddressLine2(String addressLine2) { 19 | this.addressLine2 = addressLine2; 20 | } 21 | public String getCountry() { 22 | return country; 23 | } 24 | public void setCountry(String country) { 25 | this.country = country; 26 | } 27 | public String getCode() { 28 | return code; 29 | } 30 | public void setCode(String code) { 31 | this.code = code; 32 | } 33 | @Override 34 | public String toString() { 35 | return "Address [addressLine1=" + addressLine1 + ", addressLine2=" 36 | + addressLine2 + ", country=" + country + ", code=" + code 37 | + "]"; 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Book.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | public class Book { 4 | 5 | private String isbn = null; 6 | private String title = null; 7 | private String author = null; 8 | 9 | public Book(String isbn) { 10 | setTitle("All About Lambdas"); 11 | setAuthor("Madhusudhan Konda"); 12 | setIsbn(isbn); 13 | } 14 | 15 | public String getIsbn() { 16 | return isbn; 17 | } 18 | 19 | public void setIsbn(String isbn) { 20 | this.isbn = isbn; 21 | } 22 | 23 | public String getTitle() { 24 | return title; 25 | } 26 | 27 | public void setTitle(String title) { 28 | this.title = title; 29 | } 30 | 31 | public String getAuthor() { 32 | return author; 33 | } 34 | 35 | public void setAuthor(String author) { 36 | this.author = author; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "Book [isbn=" + isbn + ", title=" + title + ", author=" + author 42 | + "]"; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Employee.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | public class Employee { 4 | 5 | private int id = 0; 6 | private String name = null; 7 | private String department = null; 8 | private String city = null; 9 | private Address address = null; 10 | private Manager manager = null; 11 | private boolean isExecutive = false; 12 | private boolean senior = false; 13 | private int ratings = 10; 14 | 15 | public int getRatings() { 16 | return ratings; 17 | } 18 | 19 | public void setRatings(int ratings) { 20 | this.ratings = ratings; 21 | } 22 | 23 | public Employee(int id) { 24 | this.id = id; 25 | this.name = "Mars Man"; 26 | address = new Address(); 27 | 28 | address.setAddressLine1("11"); 29 | address.setAddressLine2("Spacelane"); 30 | address.setCountry("Mars"); 31 | address.setCode("12AB102D1"); 32 | } 33 | 34 | public Employee(int id, String name, String department) { 35 | setId(id); 36 | setName(name); 37 | setDepartment(department); 38 | } 39 | 40 | public Employee(int id, String name, String department, boolean isExec) { 41 | setId(id); 42 | setName(name); 43 | setDepartment(department); 44 | setExecutive(isExec); 45 | } 46 | 47 | public Employee(int id, String name, String department, String city) { 48 | setId(id); 49 | setName(name); 50 | setDepartment(department); 51 | setSenior(true); 52 | setCity(city); 53 | } 54 | 55 | public int getId() { 56 | return id; 57 | } 58 | 59 | public void setId(int id) { 60 | this.id = id; 61 | } 62 | 63 | public String getName() { 64 | return name; 65 | } 66 | 67 | public void setName(String name) { 68 | this.name = name; 69 | } 70 | 71 | public Address getAddress() { 72 | return address; 73 | } 74 | 75 | public void setAddress(Address address) { 76 | this.address = address; 77 | } 78 | 79 | public void setManager(Manager manager) { 80 | this.manager = manager; 81 | } 82 | 83 | public Manager getManager() { 84 | return manager; 85 | } 86 | 87 | @Override 88 | public String toString() { 89 | // return "Employee [id=" + id + ", name=" + name + ", address=" + 90 | // address 91 | // + "]"; 92 | 93 | return "Employee " + id; 94 | } 95 | 96 | public String getDepartment() { 97 | return department; 98 | } 99 | 100 | public void setDepartment(String department) { 101 | this.department = department; 102 | } 103 | 104 | public boolean isExecutive() { 105 | return isExecutive; 106 | } 107 | 108 | public void setExecutive(boolean isExecutive) { 109 | this.isExecutive = isExecutive; 110 | } 111 | 112 | public boolean isManager(Employee manager) { 113 | return getManager().equals(manager); 114 | } 115 | 116 | public boolean isSenior() { 117 | return senior; 118 | } 119 | 120 | public void setSenior(boolean senior) { 121 | this.senior = senior; 122 | } 123 | 124 | public String getCity() { 125 | return city; 126 | } 127 | 128 | public void setCity(String city) { 129 | this.city = city; 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/EncryptedTrade.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | /** 4 | * An encrypted trade 5 | * @author mkonda 6 | * 7 | */ 8 | public class EncryptedTrade { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Manager.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | public class Manager { 4 | private String name = null; 5 | 6 | private Employee personalAssistant = null; 7 | public Manager() { 8 | personalAssistant = new Employee(99); 9 | setPersonalAssistant(personalAssistant); 10 | } 11 | 12 | public Manager(String name) { 13 | personalAssistant = new Employee(99); 14 | setPersonalAssistant(personalAssistant); 15 | setName(name); 16 | } 17 | 18 | public void setPersonalAssistant(Employee personalAssistant) { 19 | this.personalAssistant = personalAssistant; 20 | } 21 | 22 | public Employee getPersonalAssistant() { 23 | return personalAssistant; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "Manager [personalAssistant=" + personalAssistant + "]"; 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public void setName(String name) { 36 | this.name = name; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Movie.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Movie { 7 | 8 | String name = null; 9 | boolean isClassic = false; 10 | String director = null; 11 | private List actors = new ArrayList(); 12 | 13 | public Movie(String name, boolean isClassic) { 14 | setName(name); 15 | setClassic(isClassic); 16 | } 17 | 18 | public Movie(String name, boolean isClassic, String director) { 19 | setName(name); 20 | setClassic(isClassic); 21 | setDirector(director); 22 | } 23 | 24 | public Movie(String name, List actors) { 25 | setName(name); 26 | setActors(actors); 27 | } 28 | public String getName() { 29 | return name; 30 | } 31 | 32 | public void setName(String name) { 33 | this.name = name; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "Movie [name=" + name + "]"; 39 | } 40 | public boolean isClassic() { 41 | return isClassic; 42 | } 43 | 44 | public String getDirector() { 45 | return director; 46 | } 47 | 48 | public void setDirector(String director) { 49 | this.director = director; 50 | } 51 | 52 | public void setClassic(boolean isClassic) { 53 | this.isClassic = isClassic; 54 | } 55 | 56 | public Movie(String name) { 57 | setName(name); 58 | } 59 | 60 | public List getActors() { 61 | return actors; 62 | } 63 | 64 | public void setActors(List actors) { 65 | this.actors = actors; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Patient.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | public class Patient { 4 | long patientId = 0; 5 | private int seriousFactor = 0; 6 | public Patient(long id) { 7 | patientId = id; 8 | } 9 | public boolean isSerious(){ 10 | return seriousFactor > 3; 11 | } 12 | public int getSeriousFactor() { 13 | return seriousFactor; 14 | } 15 | public void setSeriousFactor(int seriousFactor) { 16 | this.seriousFactor = seriousFactor; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Student.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | import java.util.Optional; 4 | 5 | public class Student { 6 | 7 | public String getName() { 8 | return name; 9 | } 10 | public void setName(String name) { 11 | this.name = name; 12 | } 13 | public Teacher getTeacher() { 14 | return teacher; 15 | } 16 | public void setTeacher(Teacher teacher) { 17 | this.teacher = teacher; 18 | } 19 | private String name = null; 20 | private Teacher teacher = null; 21 | 22 | public boolean hasTeacher() { 23 | return teacher!=null?true:false; 24 | } 25 | @Override 26 | public String toString() { 27 | return "Student [name=" + name + ", teacher=" + teacher + "]"; 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Teacher.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | import java.util.Optional; 4 | 5 | 6 | public class Teacher { 7 | private String name = null; 8 | private Optional student = null; 9 | public Teacher(String name) { 10 | setName(name); 11 | } 12 | public String getName() { 13 | return name; 14 | } 15 | public void setName(String name) { 16 | this.name = name; 17 | } 18 | public Optional getStudent() { 19 | return student; 20 | } 21 | public void setStudent(Optional student) { 22 | this.student = student; 23 | } 24 | @Override 25 | public String toString() { 26 | return "Teacher [name=" + name + "]"; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Trade.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | public class Trade { 6 | 7 | private AtomicInteger tradeId = new AtomicInteger(); 8 | 9 | private int id = 0; 10 | private String instrument = null; 11 | 12 | private String status = null; 13 | 14 | private int quantity = 0; 15 | 16 | public Trade(int id){ 17 | setId(tradeId.getAndIncrement()); 18 | } 19 | public Trade(String instrument, int quantity, String status) { 20 | setId(tradeId.getAndIncrement()); 21 | setQuantity(quantity); 22 | setStatus(status); 23 | setInstrument(instrument); 24 | } 25 | 26 | public Trade(int id, String instrument, int quantity, String status) { 27 | setId(id); 28 | setQuantity(quantity); 29 | setStatus(status); 30 | setInstrument(instrument); 31 | } 32 | 33 | public Trade() { 34 | tradeId.getAndIncrement(); 35 | } 36 | 37 | public Trade(Trade t) { 38 | // TODO Auto-generated constructor stub 39 | } 40 | 41 | public int getTradeId() { 42 | return tradeId.intValue(); 43 | } 44 | 45 | public String getInstrument() { 46 | return instrument; 47 | } 48 | 49 | public void setInstrument(String instrument) { 50 | this.instrument = instrument; 51 | } 52 | 53 | public String getStatus() { 54 | return status; 55 | } 56 | 57 | public void setStatus(String status) { 58 | this.status = status; 59 | } 60 | 61 | public int getQuantity() { 62 | return quantity; 63 | } 64 | 65 | public void setQuantity(int quantity) { 66 | this.quantity = quantity; 67 | } 68 | 69 | public void setTradeId(AtomicInteger tradeId) { 70 | this.tradeId = tradeId; 71 | } 72 | 73 | 74 | @Override 75 | public String toString() { 76 | return "Trade [id=" + id + ", instrument=" + instrument + ", status=" 77 | + status + ", quantity=" + quantity + "]"; 78 | } 79 | 80 | public void setPrice(double price) { 81 | // TODO Auto-generated method stub 82 | 83 | } 84 | 85 | public boolean isOpen() { 86 | return true; 87 | } 88 | 89 | public boolean isBigTrade() { 90 | return getQuantity() > 1000000; 91 | } 92 | 93 | public boolean isNew() { 94 | return getStatus().equals("NEW"); 95 | } 96 | 97 | public boolean isPending() { 98 | return getStatus().equals("PENDING"); 99 | } 100 | 101 | public boolean isCancelledTrade() { 102 | return getStatus().equals("CANCEL") ; 103 | } 104 | 105 | @Override 106 | public int hashCode() { 107 | final int prime = 31; 108 | int result = 1; 109 | result = prime * result 110 | + ((instrument == null) ? 0 : instrument.hashCode()); 111 | result = prime * result + quantity; 112 | result = prime * result + ((status == null) ? 0 : status.hashCode()); 113 | result = prime * result + ((tradeId == null) ? 0 : tradeId.hashCode()); 114 | return result; 115 | } 116 | 117 | @Override 118 | public boolean equals(Object obj) { 119 | if (this == obj) 120 | return true; 121 | if (obj == null) 122 | return false; 123 | if (getClass() != obj.getClass()) 124 | return false; 125 | Trade other = (Trade) obj; 126 | if (instrument == null) { 127 | if (other.instrument != null) 128 | return false; 129 | } else if (!instrument.equals(other.instrument)) 130 | return false; 131 | if (quantity != other.quantity) 132 | return false; 133 | if (status == null) { 134 | if (other.status != null) 135 | return false; 136 | } else if (!status.equals(other.status)) 137 | return false; 138 | return true; 139 | } 140 | 141 | public int getId() { 142 | return id; 143 | } 144 | 145 | public void setId(int id) { 146 | this.id = id; 147 | } 148 | 149 | public boolean copy(EncryptedTrade t1) { 150 | //Copy t1 to this trade 151 | // logic of copying the Encrypted trade to this trade goes here 152 | return true; 153 | } 154 | 155 | 156 | 157 | } 158 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/domain/Vehicle.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.domain; 2 | 3 | public class Vehicle { 4 | 5 | public Vehicle(int i) { 6 | } 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/functions/Consumers.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.functions; 2 | 3 | import java.util.function.Consumer; 4 | 5 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 6 | 7 | /** 8 | * Class to demonstrate Consumer function 9 | * @author mkonda 10 | * 11 | */ 12 | public class Consumers { 13 | 14 | /** 15 | * A lambda with Consumer target type for persistence 16 | */ 17 | Consumer persistMovie = this::persist; 18 | 19 | private void persist(Movie m) { 20 | System.out.println("Persisting "+m); 21 | } 22 | 23 | /** 24 | * A lambda for auditing movies 25 | */ 26 | 27 | Consumer auditMovie = this::audit; 28 | 29 | private void audit(Movie m) { 30 | System.out.println("Auditing "+m); 31 | } 32 | 33 | Consumer distributeMovie = t -> distribute(t); 34 | 35 | private void distribute(Movie m) { 36 | System.out.println("Distributing "+m); 37 | } 38 | /** 39 | * Invoke the composed consumer by passing a movie 40 | * @param movie 41 | */ 42 | private void andThenTest(Movie movie) { 43 | // The composed consumer auditing and persisting a movie 44 | Consumer andThenConsumer = auditMovie.andThen(persistMovie); 45 | andThenConsumer.accept(movie); 46 | } 47 | 48 | /** 49 | * Chaining Consumers 50 | */ 51 | private void ChainingConsumers(Movie movie) { 52 | Consumer chainedConsumer = auditMovie 53 | .andThen(persistMovie) 54 | .andThen(distributeMovie); 55 | 56 | // invoke the chained consumer 57 | chainedConsumer.accept(movie); 58 | } 59 | 60 | public static void main(String[] args) { 61 | Movie m = new Movie("Mission Impossible"); 62 | new Consumers().andThenTest(m); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/functions/Functions.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.functions; 2 | 3 | import java.util.List; 4 | import java.util.function.Function; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Book; 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 8 | import com.madhusudhan.wr.allaboutlambdas.domain.Manager; 9 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 10 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 11 | import com.madhusudhan.wr.allaboutlambdas.util.TradeUtil; 12 | 13 | /** 14 | * Class to demonstrate the Function function 15 | * 16 | * @author mkonda 17 | * 18 | */ 19 | public class Functions { 20 | 21 | // Function that given a String, produces a Movie 22 | Function movieFunction = movieName -> new Movie(movieName); 23 | 24 | /** 25 | * Method that given a string, returns a movie (String->Movie) 26 | */ 27 | public Movie useFunction(String movieName) { 28 | // Use our movie function to create a Movie 29 | Movie movie = movieFunction.apply(movieName); 30 | System.out.println("Movie created:" + movie); 31 | return movie; 32 | 33 | } 34 | 35 | List trades = TradeUtil.createTrades(); 36 | 37 | Function tradeFinder = (id) -> { 38 | // Run through all trades checking against the given one 39 | Trade trade = new Trade(); 40 | for (Trade t : trades) { 41 | if (t.getId() == id) 42 | trade = t; 43 | } 44 | return trade; 45 | }; 46 | 47 | public void tradeFinder(Integer id) { 48 | Trade trade = tradeFinder.apply(id); 49 | 50 | System.out.println("Fetched a trade: " + trade); 51 | } 52 | 53 | public void tradeFinderJava8(Integer tradeId) { 54 | List trades = TradeUtil.createTrades(); 55 | 56 | Trade trade = trades.stream().filter(t -> t.getId() == tradeId) 57 | .findFirst().get(); 58 | 59 | System.out.println("Fetched a trade (using Streams): " + trade); 60 | } 61 | 62 | public void usingAndThenAndCompose() { 63 | 64 | Function bookFinder = this::fetchBook; 65 | Function rankFinder = this::rankFinder; 66 | 67 | System.out.println(bookFinder.apply("ISBN123")); 68 | // andThen composed function 69 | Function bookRankFinder = bookFinder 70 | .andThen(rankFinder); 71 | 72 | Function rankBookFinder = rankFinder 73 | .compose(bookFinder); 74 | 75 | System.out.println(bookRankFinder.apply("All About Lambdas")); 76 | System.out.println(rankBookFinder.apply("ISBN123")); 77 | 78 | } 79 | 80 | public void usingAndThenAndCompose2() { 81 | 82 | Function principalInterest = amount -> amount*2; 83 | 84 | Function factoredInterest = amount -> amount+10; 85 | 86 | Integer amount1 = principalInterest.andThen(factoredInterest).apply(10); 87 | Integer amount2 = principalInterest.compose(factoredInterest).apply(10); 88 | 89 | System.out.println("Apply interest first before factoring it:"+amount1); 90 | System.out.println("Factor the amount and then apply interest:"+amount2); 91 | } 92 | 93 | public void usingIdFunction(){ 94 | Function idFunction = Function.identity(); 95 | 96 | String result = idFunction.apply("LAMBDAS"); 97 | System.out.println(result); 98 | } 99 | private Book fetchBook(String isbn) { 100 | // fetch it from our database 101 | return new Book(isbn); 102 | } 103 | 104 | private Integer rankFinder(Book book) { 105 | // fetch the rank from external sources 106 | return 1; 107 | } 108 | 109 | public static void main(String[] args) { 110 | new Functions().tradeFinder(1); 111 | new Functions().tradeFinderJava8(1); 112 | 113 | new Functions().usingAndThenAndCompose(); 114 | 115 | new Functions().usingAndThenAndCompose2(); 116 | 117 | new Functions().usingIdFunction(); 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/functions/Predicates.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.functions; 2 | 3 | import java.util.List; 4 | import java.util.function.Predicate; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Patient; 8 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 9 | 10 | /** 11 | * Class that demonstrates Predicate function usage 12 | * 13 | * @author mkonda 14 | * 15 | */ 16 | public class Predicates { 17 | 18 | interface Triage{ 19 | // Is the condition of the patient critical 20 | boolean evaluate(Patient patient); 21 | } 22 | 23 | interface Hospital{ 24 | void admit(Patient patient); 25 | } 26 | 27 | /** 28 | * Does the Employee has enough rating 29 | */ 30 | Predicate bonusEligible = emp -> emp.getRatings() > 10; 31 | 32 | 33 | 34 | Triage t = patient -> patient.isSerious(); 35 | Hospital h = p -> System.out.println(p); 36 | 37 | Predicate hospital = patient -> { 38 | return patient.isSerious(); 39 | }; 40 | 41 | 42 | /** 43 | * AND function 44 | */ 45 | 46 | Predicate cancelledTrade = Trade::isCancelledTrade; 47 | Predicate bigTrade =Trade::isBigTrade; 48 | 49 | // A cancelled & big trade predicate 50 | PredicatecomposedLambda = cancelledTrade.and(bigTrade); 51 | 52 | /** 53 | * OR function 54 | */ 55 | 56 | // Predicate for NEW status 57 | Predicate newTrade = Trade::isNew; 58 | 59 | // Predicate for PENDING status 60 | Predicate pendingTrade = Trade::isPending; 61 | 62 | // Either new or pending trade 63 | Predicate orLambda = newTrade.or(pendingTrade); 64 | 65 | // New or pending but big trade 66 | Predicate newOrPendingButBigTrade = newTrade.or(pendingTrade).and(bigTrade); 67 | 68 | // We know there's a predicate for new trade: 69 | //And this becomes a predicate for anything but new: 70 | Predicate notNewTrade = newTrade.negate(); 71 | 72 | private void isEqualMethod(List trades) { 73 | // Reference trade 74 | Trade t1 = new Trade("GOOGLE", 200000, "CANCEL"); 75 | Predicate p1 = Predicate.isEqual(t1); 76 | // Predicate which compares the given trades 77 | for(Trade tr: trades){ 78 | if(p1.test(tr)){ 79 | System.out.println("Found a matching trade: "+tr); 80 | } 81 | } 82 | // using streams 83 | if(trades.stream().anyMatch(p1)){ 84 | 85 | } 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/functions/RecurringFunctions.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.functions; 2 | 3 | import java.util.List; 4 | import java.util.Properties; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Patient; 7 | 8 | 9 | public class RecurringFunctions { 10 | 11 | // Check if the movies belongs to thriller genre 12 | interface Movie{ 13 | boolean isThriller(int movieId); 14 | } 15 | 16 | // Get an employee given an id 17 | interface Employee{ 18 | Employee fetch(int empId); 19 | } 20 | 21 | // Admit the patient 22 | interface Hospital{ 23 | void admit(Patient patient); 24 | } 25 | 26 | // Supply the properties required to seed the system 27 | interface Seeder{ 28 | List seed(String system); 29 | } 30 | 31 | // Custom functions 32 | 33 | // Interface for checking conditionality 34 | interface Tester{ 35 | boolean test(T t); 36 | } 37 | 38 | // Interface for Producing objects 39 | interface Producer{ 40 | T produce(int id); 41 | } 42 | 43 | // Interface for consuming elements 44 | interface Consumer{ 45 | void consume(T t); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/functions/Suppliers.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.functions; 2 | 3 | import java.util.List; 4 | import java.util.ArrayList; 5 | import java.util.function.Supplier; 6 | 7 | /** 8 | * Class for Supplier's functionality 9 | * @author mkonda 10 | * 11 | */ 12 | public class Suppliers { 13 | 14 | /** 15 | * A supplier of soft drinks 16 | */ 17 | 18 | Supplier> drinksSupplier = () -> { 19 | List drinks = new ArrayList(); 20 | 21 | drinks.add("Orange Juice"); 22 | drinks.add("Pineapple"); 23 | drinks.add("Custard Apple"); 24 | 25 | return drinks; 26 | }; 27 | 28 | public void getDrinks(){ 29 | List softDrinks = drinksSupplier.get(); 30 | softDrinks.stream().forEach(System.out::println); 31 | } 32 | public static void main(String[] args) { 33 | new Suppliers().getDrinks(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/interfaces/Diner.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.interfaces; 2 | 3 | @FunctionalInterface 4 | public interface Diner { 5 | 6 | String order(String order); 7 | 8 | default String getCoffee() { 9 | return "Cappuccino "; 10 | } 11 | 12 | default String getIndianBreakfast() { 13 | return "Idly, Sambar and a Dosa"; 14 | } 15 | 16 | default String getEnglishBreakfast() { 17 | return "Eggs, Sausages, Beans and a Toast"; 18 | } 19 | 20 | static String payBill(double billAmount) { 21 | return "Thank you for your custom, see you next time!"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/interfaces/DinerImpl.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.interfaces; 2 | 3 | public class DinerImpl implements Diner{ 4 | 5 | public String order(String order, Diner lambda) { 6 | return lambda.order(order); 7 | } 8 | 9 | @Override 10 | public String order(String order) { 11 | 12 | StringBuilder breakfastCoffeeOrder = new StringBuilder(); 13 | 14 | String coffee = getCoffee(); 15 | String breakfast = getEnglishBreakfast(); 16 | return breakfastCoffeeOrder 17 | .append(coffee) 18 | .append(" with ") 19 | .append(breakfast).toString(); 20 | } 21 | 22 | public static void main(String[] args) { 23 | DinerImpl impl = new DinerImpl(); 24 | String breakfast = impl.order("Breakfast"); 25 | System.out.println(breakfast); 26 | 27 | Diner dineOrder = s -> { 28 | return "Breakfast on its way for "+s; 29 | }; 30 | String lambdaOrder = impl.order("Mr Harry", dineOrder); 31 | Diner.payBill(24.50); 32 | System.out.println(lambdaOrder); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/interfaces/InheritanceRules.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.interfaces; 2 | 3 | import com.madhusudhan.wr.allaboutlambdas.domain.Patient; 4 | 5 | public class InheritanceRules { 6 | 7 | /** 8 | * A general physician operating a patient 9 | * @author mkonda 10 | * 11 | */ 12 | interface Doctor{ 13 | default String operate(Patient p){ 14 | return "Patient is being operated by a general physician"; 15 | } 16 | } 17 | 18 | /** 19 | * A patient being operated by a specialist 20 | * @author mkonda 21 | * 22 | */ 23 | interface Surgeon{ 24 | default String operate(Patient p){ 25 | return "Patient is being operated by a specialist"; 26 | } 27 | } 28 | 29 | /** 30 | * This class compilation fails as compiler is thoroughly confused as to whose method it shoudl pick 31 | * @author mkonda 32 | * 33 | */ 34 | // class Hospital implements Doctor, Surgeon{ 35 | // private String admitAndOperate(Patient p){ 36 | // return operate(p); 37 | // } 38 | // } 39 | 40 | /** 41 | * Create a method to provide the specific logic 42 | * @author mkonda 43 | * 44 | */ 45 | class Hospital1 implements Doctor, Surgeon{ 46 | // Overriding with own implementation 47 | public String operate(Patient p){ 48 | return "Patient operated"; 49 | } 50 | } 51 | 52 | /** 53 | * If we wish to grab one of the interface's implementations, use super keyword 54 | * @author mkonda 55 | * 56 | */ 57 | class Hospital2 implements Doctor, Surgeon{ 58 | public String operate(Patient p){ 59 | return Doctor.super.operate(p); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/interfaces/InheritanceRules2.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.interfaces; 2 | 3 | import com.madhusudhan.wr.allaboutlambdas.domain.Patient; 4 | 5 | public class InheritanceRules2 { 6 | 7 | /** 8 | * A patient being operated by a specialist 9 | * @author mkonda 10 | * 11 | */ 12 | interface Surgeon{ 13 | default String operate(Patient p){ 14 | return "Patient is being operated by a specialist"; 15 | } 16 | } 17 | 18 | /** 19 | * A general physician operating a patient 20 | * @author mkonda 21 | * 22 | */ 23 | interface Doctor extends Surgeon{ 24 | default String operate(Patient p){ 25 | return "Patient is being operated by a general physician"; 26 | } 27 | } 28 | 29 | 30 | /** 31 | * This class demonstrates that sub-interfaces win during multiple inheritance war. 32 | * @author mkonda 33 | * 34 | */ 35 | public class Hospital implements Doctor, Surgeon{ 36 | /** 37 | * As Doctor is close to the Hospital in the object graph, it's operate method gets picked up 38 | * @param p 39 | * @return 40 | */ 41 | public String admitAndOperate(Patient p){ 42 | return operate(p); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/interfaces/InheritingBehaviour.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.interfaces; 2 | /** 3 | * A class that shows us how we can inherit behavior implementing various default methods 4 | * @author mkonda 5 | * 6 | */ 7 | public class InheritingBehaviour { 8 | 9 | /** 10 | * An Engine interface 11 | * @author mkonda 12 | * 13 | */ 14 | interface Engine { 15 | default String make() { 16 | return "DEFAULT MAKE"; 17 | } 18 | } 19 | 20 | interface Vehicle { 21 | default String model() { 22 | return "DEFAULT MODEL"; 23 | } 24 | } 25 | 26 | class Car implements Engine, Vehicle { 27 | public String getMakeAndModel() { 28 | return Engine.super.make() + ":" + Vehicle.super.model(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/interfaces/Interfaces.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.interfaces; 2 | 3 | import com.madhusudhan.wr.allaboutlambdas.domain.Patient; 4 | import com.madhusudhan.wr.allaboutlambdas.domain.Vehicle; 5 | 6 | /** 7 | * A functional interface for admitting a patient. 8 | * @author mkonda 9 | * 10 | */ 11 | @FunctionalInterface 12 | interface Hospital { 13 | void admit(Patient patient); 14 | } 15 | 16 | /** 17 | * An interface that may or may be not used as a functional interface 18 | * @author mkonda 19 | * 20 | */ 21 | //@FunctionalInterface 22 | interface Factory { 23 | Vehicle create(int id); 24 | 25 | // Additional abstract method 26 | // uncomment this method to find out that all lambda expressions will be broken 27 | // boolean scrap(int id); 28 | 29 | } 30 | 31 | public class Interfaces { 32 | 33 | // Lambda for a general patient 34 | Hospital generalAdmittance = (p) -> { 35 | System.out.println("Admitting patient to a general ward: "+p); 36 | general(p); 37 | }; 38 | 39 | // Same as above lambda, this time using method ref 40 | Hospital generalAdmittanceMethodRef = this::general; 41 | 42 | // Lambda for an emergency admittance 43 | Hospital emergencyAddmittance = (p) -> System.out.println("Admitting patient to A&E: "+p); 44 | Factory factory = id -> new Vehicle(id); 45 | 46 | 47 | private void general(Patient p) { 48 | System.out.println("General ward admitted patient: "+p); 49 | } 50 | 51 | private void emergency(Patient p) { 52 | System.out.println("Patient admitted to A&E: "+p); 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/interfaces/IntersectionTypes.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.interfaces; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Class demonstrating the intersection types. 7 | * @author mkonda 8 | * 9 | */ 10 | public class IntersectionTypes { 11 | 12 | // Marker interface (no methods) 13 | interface Shape { 14 | } 15 | 16 | /** 17 | * A functional interface 18 | * @author mkonda 19 | * 20 | */ 21 | @FunctionalInterface 22 | interface Ball { 23 | void bounce(); 24 | } 25 | 26 | Ball b = () -> System.out.println("Bouncing.."); 27 | 28 | Ball ball = 29 | (Ball & Shape)() -> System.out.println("Bouncing shape.."); 30 | 31 | Ball serializableBallLambda = (Ball&Serializable)() -> System.out.println("Bouncing serializable ball"); 32 | } 33 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/introducinglambdas/DissectingLambda.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.introducinglambdas; 2 | 3 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 4 | 5 | public class DissectingLambda { 6 | 7 | /** 8 | * Functional interface for checking various characteristics 9 | * of a trade. 10 | * 11 | * @param 12 | */ 13 | interface Tradable{ 14 | boolean check(T t); 15 | } 16 | 17 | private void checkCharecteristics(Tradable tradableLambda, Trade trade){ 18 | tradableLambda.check(trade); 19 | } 20 | 21 | // Big trade lambda expression 22 | Tradable bigTradeLambda =(t) -> t.isBigTrade(); 23 | 24 | public static void main(String[] args) { 25 | DissectingLambda client = new DissectingLambda(); 26 | Trade trade = new Trade(1,"APPLE",15000000,"NEW"); 27 | 28 | // Is this a cancelled trade 29 | client.checkCharecteristics ((t) -> t.isCancelledTrade(), trade); 30 | 31 | // multiline code 32 | client.checkCharecteristics (t -> { 33 | return t.isCancelledTrade(); 34 | }, trade); 35 | 36 | // Is this a risky trade 37 | client.checkCharecteristics 38 | ((t)-> client.isRisky(t), trade); 39 | 40 | // use method references 41 | client.checkCharecteristics(client::isRisky, trade); 42 | } 43 | 44 | private boolean isRisky(Trade t) { 45 | boolean riskyFlag = false; 46 | 47 | if((t.getQuantity() > 5000000) || (getRiskIndicator() > 5)) 48 | riskyFlag = true; 49 | 50 | return riskyFlag; 51 | } 52 | 53 | private int getRiskIndicator() { 54 | return 5; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/introducinglambdas/GreetingExample.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.introducinglambdas; 2 | 3 | public class GreetingExample { 4 | 5 | interface Greeting { 6 | public String sayHello(String g); 7 | } 8 | 9 | // Greeting greetingLambda = s -> { 10 | // return "Hello, " + s; 11 | // }; 12 | 13 | Greeting greetingLambdaReference = s -> { 14 | return greet(s); 15 | }; 16 | 17 | Greeting greetingLambdaReference2 = this::greet; 18 | 19 | private void invokeAGreeting(Greeting greeting){ 20 | 21 | } 22 | 23 | private String greet(String s) { 24 | return "Hello, "+s; 25 | } 26 | 27 | public static void main(String[] args) { 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/introducinglambdas/LambdaTasters.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.introducinglambdas; 2 | 3 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 4 | 5 | /** 6 | * This class defines few lambda expressions. 7 | * @author mkonda 8 | * 9 | */ 10 | public class LambdaTasters { 11 | 12 | interface Quote{ 13 | void quoteOfTheDay(); 14 | } 15 | 16 | interface Instrument{ 17 | String extract(T t); 18 | } 19 | 20 | // Lambda printing out a quote 21 | Quote quoteLambda = () ->System.out.println("Hello, Lambdas!"); 22 | 23 | // Lambda fetching the instrument of a Trade 24 | Instrument instrumentLambda = ( t ) -> t.getInstrument(); 25 | 26 | public static void main(String[] args) { 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/introducinglambdas/TradeMerger.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.introducinglambdas; 2 | 3 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 4 | 5 | public class TradeMerger { 6 | 7 | /** 8 | * Functional interface for merging trades 9 | * @author mkonda 10 | * 11 | */ 12 | interface Merger { 13 | Trade merge(Trade t1, Trade t2); 14 | } 15 | 16 | public static void main(String[] args) { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/introduction/Examples.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.introduction; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.Callable; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 8 | import com.madhusudhan.wr.allaboutlambdas.util.MovieUtil; 9 | 10 | /** 11 | * This class defines few lambda expressions. 12 | * @author mkonda 13 | * 14 | */ 15 | public class Examples { 16 | 17 | /** 18 | * A callable lambda 19 | */ 20 | 21 | Callable c = () -> { 22 | Trade t = new Trade("GOOGLE", 2000, "OPEN"); 23 | encrypt(t); 24 | persist(t); 25 | return t; 26 | }; 27 | 28 | /** 29 | * fetching movies directed by a specific director 30 | * 31 | * @param movies 32 | * @param director 33 | */ 34 | private void fetchMovies(List movies, String director) { 35 | movies 36 | .stream() 37 | .filter(m -> m.getDirector().equals(director)) 38 | .map(Movie::getName) 39 | .distinct() 40 | .forEach(System.out::println); 41 | } 42 | 43 | public static void main(String[] args) { 44 | 45 | List movies = MovieUtil.createMovies(); 46 | new Examples().fetchMovies(movies, "Steven Spielberg"); 47 | } 48 | 49 | private void persist(Trade t) { 50 | System.out.println("Persisting the trade .."); 51 | } 52 | 53 | private void encrypt(Trade t) { 54 | System.out.println("Encrypting the trade.."); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/introduction/Runnables.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.introduction; 2 | 3 | /** 4 | * Class demonstrating the various approaches of developing a Runnable and 5 | * executing it in a new Thread. The point of interest is the lambda approach. 6 | * 7 | * @author mkonda 8 | * 9 | */ 10 | public class Runnables { 11 | 12 | public static void main(String[] args) { 13 | Runnables client = new Runnables(); 14 | // client.instanceRunnable(); 15 | // client.anonymousRunnable(); 16 | client.usingLambda(); 17 | } 18 | 19 | /** 20 | * This method demonstrates the executing the logic 21 | * via an instance of a Runnable provided to a Thread 22 | */ 23 | public void instanceRunnable() { 24 | Runnable oldRunnable = new Runnable() { 25 | @Override 26 | public void run() { 27 | System.out.println("Using traditional Runnable!"); 28 | runErrands(); 29 | } 30 | }; 31 | 32 | new Thread(oldRunnable).start(); 33 | } 34 | /** 35 | * We create the runnable in-line 36 | */ 37 | public void anonymousRunnable() { 38 | 39 | new Thread(new Runnable() { 40 | @Override 41 | public void run() { 42 | System.out.println("Using anonymous Runnable!"); 43 | runErrands(); 44 | } 45 | }).start(); 46 | } 47 | 48 | public void usingLambda() { 49 | Runnable runnableLambdaSimple = () -> runErrands(); 50 | Runnable runnableLambda = () -> { 51 | System.out.println("Using a Lambda Expression"); 52 | runErrands(); 53 | }; 54 | 55 | new Thread(runnableLambdaSimple).start(); 56 | 57 | new Thread(() -> { 58 | System.out.println("Using a Lambda Expression"); 59 | listErrands(); 60 | runErrands(); 61 | }).start(); 62 | // Or using method references 63 | new Thread(this::runErrands).start(); 64 | 65 | // Or chilling off 66 | new Thread(() -> stayRelax()).start(); 67 | 68 | // Chilling off using method references 69 | new Thread(this::stayRelax).start(); 70 | 71 | } 72 | 73 | private void listErrands() { 74 | System.out.println("Listing the errands!"); 75 | } 76 | 77 | private void runErrands() { 78 | System.out.println("Running errands!"); 79 | } 80 | 81 | private void stayRelax() { 82 | System.out.println("Chilling off!"); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/introduction/Streaming.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.introduction; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 7 | import com.madhusudhan.wr.allaboutlambdas.util.TradeUtil; 8 | /** 9 | * This class shows the usage of basic streams functionality. 10 | * 11 | * @author mkonda 12 | * 13 | */ 14 | public class Streaming { 15 | private int ONE_MILLION = 1000000; 16 | 17 | /** 18 | * Finding large trades 19 | * @param trades 20 | */ 21 | private void findLargeTrades(List trades) { 22 | trades.stream() 23 | .filter(trade -> trade.getQuantity() > ONE_MILLION) 24 | .forEach(System.out::println);; 25 | } 26 | /** 27 | * Finding large trades - execution is run in parallel mode 28 | * @param trades 29 | * @return 30 | */ 31 | private List findLargeTradesInParallel(List trades) { 32 | List bigTrades = trades 33 | .stream() 34 | .parallel() 35 | .filter(trade -> trade.getQuantity() > ONE_MILLION) 36 | .collect(Collectors.toList()); 37 | 38 | return bigTrades; 39 | } 40 | 41 | 42 | public static void main(String[] args) { 43 | List trades = TradeUtil.createTrades(); 44 | new Streaming().findLargeTrades(trades); 45 | List bigTrades = new Streaming().findLargeTradesInParallel(trades); 46 | bigTrades.forEach(System.out::println); 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/newfeatures/Component.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.newfeatures; 2 | 3 | /** 4 | * An interface with one abstract method 5 | * (so it can represent lambda) and concrete 6 | * methods of static and default type 7 | * @author mkonda 8 | * 9 | */ 10 | public interface Component { 11 | /** 12 | * Get the name of the component 13 | * @return 14 | */ 15 | String getName(); 16 | 17 | /** 18 | * Get the default name 19 | * @return 20 | */ 21 | default String getDefaultName(){ 22 | return "Default Component"; 23 | } 24 | 25 | /** 26 | * Get the region 27 | * @return 28 | */ 29 | static String getRegion(){ 30 | return "United Kingdom"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/newfeatures/Finder.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.newfeatures; 2 | 3 | /** 4 | * A functional interface 5 | * 6 | * @author mkonda 7 | * 8 | */ 9 | 10 | public class Finder { 11 | 12 | @FunctionalInterface 13 | public interface IFinder { 14 | 15 | /** 16 | * An abstract method 17 | * 18 | * @param find 19 | * @return 20 | */ 21 | String find(String criteria); 22 | 23 | default String criteria() { 24 | return "Search criteria:"; 25 | } 26 | } 27 | 28 | public static void main(String[] args) { 29 | IFinder finder = (s) -> "result"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/newfeatures/ParallelStreamsFeature.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.newfeatures; 2 | 3 | import java.util.List; 4 | 5 | import static java.util.stream.Collectors.toList; 6 | 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 8 | import com.madhusudhan.wr.allaboutlambdas.util.MovieUtil; 9 | 10 | /** 11 | * Example for demontrating streams feature 12 | * @author mkonda 13 | * 14 | */ 15 | public class ParallelStreamsFeature { 16 | 17 | /** 18 | * Finding classics running parallel 19 | * @param movies 20 | * @return 21 | */ 22 | public List findClassics(List movies) { 23 | return movies 24 | .stream() 25 | .parallel() 26 | .filter(m -> m.isClassic()) 27 | .collect(toList()); 28 | } 29 | 30 | /** 31 | * Finding classics using parallelStream 32 | * @param movies 33 | * @return 34 | */ 35 | public List findClassics2(List movies) { 36 | return movies 37 | .parallelStream() 38 | .filter(m -> m.isClassic()) 39 | .collect(toList()); 40 | } 41 | 42 | public static void main(String[] args) { 43 | List movies = MovieUtil.createMovies(); 44 | List classics = new ParallelStreamsFeature().findClassics(movies); 45 | classics.forEach(System.out::println); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/newfeatures/StreamsFeature.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.newfeatures; 2 | 3 | import java.util.List; 4 | 5 | import static java.util.stream.Collectors.toList; 6 | 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 8 | import com.madhusudhan.wr.allaboutlambdas.util.MovieUtil; 9 | 10 | /** 11 | * Example for demontrating streams feature 12 | * @author mkonda 13 | * 14 | */ 15 | public class StreamsFeature { 16 | 17 | /** 18 | * Finding classics 19 | * @param movies 20 | * @return 21 | */ 22 | public List findClassics(List movies) { 23 | return movies 24 | .stream() 25 | .filter(m -> m.isClassic()) 26 | .collect(toList()); 27 | } 28 | 29 | public static void main(String[] args) { 30 | List movies = MovieUtil.createMovies(); 31 | List classics = new StreamsFeature().findClassics(movies); 32 | classics.forEach(System.out::println); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/newfeatures/TradableLambda.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.newfeatures; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.Callable; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Manager; 8 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 9 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 10 | import com.madhusudhan.wr.allaboutlambdas.util.MovieUtil; 11 | 12 | /** 13 | * This class defines few lambda expressions. 14 | * @author mkonda 15 | * 16 | */ 17 | public class TradableLambda { 18 | 19 | /** 20 | * a functional interface for checking conditions on a given trade, 21 | * returning boolean value 22 | * 23 | * @param 24 | */ 25 | interface Tradable{ 26 | boolean check(Trade t); 27 | } 28 | 29 | /** 30 | * A method that accepts a Tradable (lambda) along with a Trade instance 31 | * @param tradable 32 | * @param trade 33 | */ 34 | public void checkTrade(Tradable tradable, Trade trade){ 35 | System.out.println("Check: "+tradable.check(trade)); 36 | } 37 | 38 | public static void main(String[] args) { 39 | 40 | Trade trade = new Trade(1,"APPLE",15000000,"NEW"); 41 | 42 | // Check for a big trade 43 | Tradable bigTradeLambda = (t)-> t.isBigTrade(); 44 | new TradableLambda().checkTrade(bigTradeLambda, trade); 45 | 46 | // Check for a cancelled trade 47 | Tradable cancelledLambda = (t)-> t.isCancelledTrade(); 48 | new TradableLambda().checkTrade(cancelledLambda, trade); 49 | 50 | // Check for a new or unknown trade 51 | Tradable newOrUnknownTrade = (t)-> { 52 | return t.getStatus().equals("NEW") || t.getStatus().equals("UNKNOWN"); 53 | }; 54 | new TradableLambda().checkTrade(newOrUnknownTrade, trade); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/newfeatures/TradableLambdaUsingPredicate.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.newfeatures; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.Callable; 5 | import java.util.function.Predicate; 6 | 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 8 | import com.madhusudhan.wr.allaboutlambdas.domain.Manager; 9 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 10 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 11 | import com.madhusudhan.wr.allaboutlambdas.util.MovieUtil; 12 | 13 | /** 14 | * This class defines few lambda expressions. 15 | * @author mkonda 16 | * 17 | */ 18 | public class TradableLambdaUsingPredicate { 19 | 20 | /** 21 | * a functional interface for checking conditions on a given trade, 22 | * returning boolean value 23 | * 24 | * @param 25 | */ 26 | interface Tradable{ 27 | boolean check(Trade t); 28 | } 29 | 30 | /** 31 | * A method that accepts a Tradable (lambda) along with a Trade instance 32 | * @param tradable 33 | * @param trade 34 | */ 35 | public void checkTrade(Predicate tradable, Trade trade){ 36 | System.out.println("Check: "+tradable.test(trade)); 37 | } 38 | 39 | public static void main(String[] args) { 40 | 41 | Trade trade = new Trade(1,"APPLE",15000000,"NEW"); 42 | 43 | // Check for a big trade 44 | Predicate bigTradeLambda = (t)-> t.isBigTrade(); 45 | new TradableLambdaUsingPredicate().checkTrade(bigTradeLambda, trade); 46 | 47 | // Check for a cancelled trade 48 | Predicate cancelledLambda = (t)-> t.isCancelledTrade(); 49 | new TradableLambdaUsingPredicate().checkTrade(cancelledLambda, trade); 50 | 51 | // Check for a new or unknown trade 52 | Predicate newOrUnknownTrade = (t)-> { 53 | return t.getStatus().equals("NEW") || t.getStatus().equals("UNKNOWN"); 54 | }; 55 | new TradableLambdaUsingPredicate().checkTrade(newOrUnknownTrade, trade); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/parallellstreams/ParallelStreams.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.parallellstreams; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.concurrent.ForkJoinPool; 6 | import java.util.function.Function; 7 | import java.util.function.Predicate; 8 | import java.util.stream.IntStream; 9 | import java.util.stream.Stream; 10 | 11 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 12 | import com.madhusudhan.wr.allaboutlambdas.util.TradeUtil; 13 | 14 | //Parallel Streams 15 | public class ParallelStreams { 16 | List trades = TradeUtil.createTrades(); 17 | 18 | // Filter predicate with print statement 19 | Predicate filterPredicate = t -> { 20 | System.out.printf("Id: %d Filter Thread: %s:\n", t.getId(), 21 | Thread.currentThread().getName()); 22 | return t.isBigTrade(); 23 | }; 24 | 25 | // Map function with print statement 26 | Function mapFunction = t -> { 27 | System.out.printf("Id: %d Map Thread: %s:\n", t.getId(), 28 | Thread.currentThread().getName()); 29 | return t.getQuantity(); 30 | }; 31 | 32 | /** 33 | * The pipeline is executed in a single-thread (serial mode) 34 | */ 35 | private void serialStream() { 36 | 37 | Optional sumOfTrades = trades 38 | .stream() 39 | .filter(filterPredicate) 40 | .map(mapFunction) 41 | .reduce(Integer::sum); 42 | 43 | System.out.println(sumOfTrades.get()); 44 | 45 | } 46 | 47 | /** 48 | * Executing the pipeline in parallel mode 49 | */ 50 | private void parallelStream() { 51 | Optional sumOfTrades = trades 52 | .stream() 53 | .parallel() 54 | .filter(Trade::isBigTrade) 55 | .peek(t -> System.out.printf( 56 | "Trade Id=%d (Filter Thread Name=%s)\n", t.getId(), 57 | Thread.currentThread().getName())) 58 | .map(t -> t.getQuantity()) 59 | .peek(t -> System.out.printf("(Mapper Thread Name=%s)\n", 60 | Thread.currentThread().getName())).reduce(Integer::sum); 61 | 62 | System.out.println(sumOfTrades.get()); 63 | } 64 | 65 | 66 | /** 67 | * We can also invoke parallelStream on a collection to fetch the stream 68 | */ 69 | private void collectionParallelStream() { 70 | Stream parallelStreams = trades.parallelStream(); 71 | parallelStreams.forEach(System.out::println); 72 | } 73 | 74 | private void howManyThreads() { 75 | ForkJoinPool p = new ForkJoinPool(10); 76 | int allocatedThreads = p.getParallelism(); 77 | System.out.println("Thread count: "+allocatedThreads); 78 | } 79 | 80 | private void changeParallellism(){ 81 | IntStream intStream = IntStream.rangeClosed(0, 5); 82 | System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "10"); 83 | intStream.parallel().forEach(i -> { 84 | System.out.println(Thread.currentThread().getName()); 85 | }); 86 | } 87 | public static void main(String[] args) { 88 | // new ParallelStreams().serialStream(); 89 | // new ParallelStreams().parallelStream(); 90 | // new ParallelStreams().collectionParallelStream(); 91 | // new ParallelStreams().howManyThreads(); 92 | new ParallelStreams().changeParallellism(); 93 | 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/parallellstreams/PerformanceMeasurement.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.parallellstreams; 2 | import java.time.Duration; 3 | import java.time.Instant; 4 | import java.util.List; 5 | import java.util.Optional; 6 | import java.util.concurrent.TimeUnit; 7 | import java.util.stream.IntStream; 8 | 9 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 10 | import com.madhusudhan.wr.allaboutlambdas.util.TradeUtil; 11 | 12 | //Measurement of parallel operations 13 | public class PerformanceMeasurement { 14 | 15 | public void sumTradesInSerial(){ 16 | List trades = TradeUtil.createTrades(100); 17 | Instant start = Instant.now(); 18 | // Sequential mode 19 | trades.stream() 20 | .map(Trade::getQuantity) 21 | .reduce(Integer::sum); 22 | 23 | Instant end = Instant.now(); 24 | Duration d = Duration.between(start, end); 25 | System.out.printf("%s %d %s" , "Aggregating trades took ", d.toMillis()," ms in Seqential mode"); 26 | } 27 | 28 | public void sumTradesInParallell(){ 29 | List trades = TradeUtil.createTrades(100); 30 | Instant start = Instant.now(); 31 | trades 32 | .stream() 33 | .parallel() 34 | .map(Trade::getQuantity) 35 | .reduce(Integer::sum); 36 | 37 | Instant end = Instant.now(); 38 | Duration d = Duration.between(start, end); 39 | System.out.printf("%s %d %s" , "\nAggregating trades took ", d.toMillis()," ms in Parallel mode"); 40 | } 41 | 42 | 43 | 44 | /** 45 | * @param args 46 | */ 47 | public static void main(String[] args) { 48 | new PerformanceMeasurement().sumTradesInSerial(); 49 | new PerformanceMeasurement().sumTradesInParallell(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/specialisedfunctions/BiConsumers.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.specialisedfunctions; 2 | 3 | import java.util.function.BiConsumer; 4 | 5 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 6 | 7 | /** 8 | * Class that demonstrates Predicate function usage 9 | * 10 | * @author mkonda 11 | * 12 | */ 13 | public class BiConsumers { 14 | 15 | BiConsumer empBonusConsumer = 16 | (emp, bonus) -> System.out.printf("Employee %s is set of %d pct of bonus:", emp, bonus); 17 | 18 | BiConsumer empSalHikeConsumer = (emp, sal) -> 19 | System.out.printf("Employee %s is receiving %d hike in salary", emp, sal); 20 | 21 | 22 | 23 | private void testBiConsumer(Employee emp, Integer bonus, Integer salaryHike) { 24 | empBonusConsumer.accept(emp, bonus); 25 | } 26 | 27 | private void usingAndThen() { 28 | // BiConsumer 29 | BiConsumer empBonusAndHikeConsumer = empBonusConsumer.andThen(empSalHikeConsumer); 30 | } 31 | 32 | public static void main(String[] args) { 33 | Employee emp = new Employee(10); 34 | int bonus = 5; 35 | int salaryHike = 15; 36 | new BiConsumers().testBiConsumer(emp, bonus, salaryHike); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/specialisedfunctions/BiFunctions.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.specialisedfunctions; 2 | 3 | import java.util.function.BiFunction; 4 | import java.util.function.Function; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Manager; 8 | 9 | /** 10 | * Class that demonstrates Predicate function usage 11 | * 12 | * @author mkonda 13 | * 14 | */ 15 | public class BiFunctions { 16 | 17 | 18 | BiFunction empManagerBiFunction = (emp, manager) ->{ 19 | Employee employee = null; 20 | if(emp.getManager().equals(manager)) 21 | employee = manager.getPersonalAssistant(); 22 | return employee; 23 | }; 24 | 25 | Function emplManagerFunction = emp -> emp.getManager().getPersonalAssistant(); 26 | 27 | // Single argument function 28 | Function empManagerFunction = emp -> emp.getManager().getPersonalAssistant(); 29 | 30 | private void biFunction(Employee emp, Manager manager) { 31 | Employee employee = empManagerBiFunction.apply(emp, manager); 32 | System.out.println("Employee"+employee); 33 | } 34 | 35 | private void testAndThen(Employee emp, Manager manager) { 36 | BiFunction personalAssistant= empManagerBiFunction.andThen(empManagerFunction); 37 | } 38 | 39 | public static void main(String[] args) { 40 | Employee emp = new Employee(99); 41 | Manager manager = new Manager(); 42 | emp.setManager(manager); 43 | manager.setPersonalAssistant(emp); 44 | new BiFunctions().biFunction(emp, manager); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/specialisedfunctions/BiPredicates.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.specialisedfunctions; 2 | 3 | import java.util.List; 4 | import java.util.function.BiPredicate; 5 | import java.util.function.Predicate; 6 | 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 8 | import com.madhusudhan.wr.allaboutlambdas.domain.EncryptedTrade; 9 | import com.madhusudhan.wr.allaboutlambdas.domain.Manager; 10 | import com.madhusudhan.wr.allaboutlambdas.domain.Patient; 11 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 12 | 13 | /** 14 | * Class that demonstrates Predicate function usage 15 | * 16 | * @author mkonda 17 | * 18 | */ 19 | public class BiPredicates { 20 | 21 | BiPredicate empManagerPredicate = (emp, manager) -> emp 22 | .getManager().equals(manager); 23 | 24 | BiPredicate managerHasAssistantPredicate = (emp, manager) -> manager 25 | .getPersonalAssistant().equals(emp) ? true : false; 26 | 27 | BiPredicate tradeCopier = (trade1, trade2) -> { 28 | boolean copySuccess = false; 29 | if (!trade1.isOpen()) { 30 | copySuccess = trade1.copy(trade2); 31 | } 32 | return copySuccess; 33 | }; 34 | 35 | BiPredicate tradeComparer = (t1, t2) -> t1.getId() == t1 36 | .getId(); 37 | 38 | BiPredicate stringComparer = (s1, s2) -> s1 39 | .equalsIgnoreCase(s2); 40 | 41 | /** 42 | * Using AND function 43 | */ 44 | public void usingAnd() { 45 | // BiPredicate statusPredicate = (trade, status) -> 46 | // trade.getStatus() == status; 47 | // BiPredicate quantityPredicate = (trade, value) -> 48 | // trade.getInstrument().equals(value); 49 | // 50 | // BiPredicate isOpenAndGoogleTrade = 51 | // statusPredicate.and(quantityPredicate); 52 | 53 | // Composed function using and method 54 | BiPredicate isPersonalAssistant = empManagerPredicate 55 | .and(managerHasAssistantPredicate); 56 | } 57 | 58 | /** 59 | * Using OR function 60 | */ 61 | public void usingOr() { 62 | // Using OR method 63 | BiPredicate isPersonalAssistant = empManagerPredicate 64 | .or(managerHasAssistantPredicate); 65 | 66 | } 67 | 68 | /** 69 | * Using negate function 70 | */ 71 | public void usingNegate() { 72 | // Negating the existing predicate 73 | BiPredicate notAManagerPredicate = empManagerPredicate 74 | .negate(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/specialisedfunctions/Primitives.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.specialisedfunctions; 2 | 3 | import java.util.function.BiConsumer; 4 | import java.util.function.BinaryOperator; 5 | import java.util.function.Function; 6 | import java.util.function.UnaryOperator; 7 | 8 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 9 | 10 | /** 11 | * Class that demonstrates Predicate function usage 12 | * 13 | * @author mkonda 14 | * 15 | */ 16 | public class Primitives { 17 | 18 | int tradeQuantity = 0; 19 | 20 | // Two types must be specified 21 | Function tradeQuantityLambda = id -> { 22 | // Fetch the quantity 23 | Trade t = getTrade(id); 24 | return t.getQuantity(); 25 | }; 26 | 27 | // The redundant type vanishes 28 | private UnaryOperator unaryOperator = (id) -> { 29 | return tradeQuantity; 30 | }; 31 | 32 | private Trade getTrade(Integer id) { 33 | return new Trade(id); 34 | } 35 | 36 | 37 | private void binaryOp() { 38 | BinaryOperator sumOfQuantities = (quantity1, quantity2) -> quantity1+quantity2; 39 | int result = sumOfQuantities.apply(30000, 44000); 40 | System.out.println("Sum total: "+result); 41 | } 42 | 43 | public static void main(String[] args) { 44 | new Primitives().binaryOp(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/specialisedfunctions/SpecialisedFunctions.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.specialisedfunctions; 2 | 3 | import java.util.function.DoubleConsumer; 4 | import java.util.function.DoubleFunction; 5 | import java.util.function.DoublePredicate; 6 | import java.util.function.DoubleSupplier; 7 | import java.util.function.DoubleToIntFunction; 8 | import java.util.function.DoubleUnaryOperator; 9 | import java.util.function.Function; 10 | import java.util.function.IntConsumer; 11 | import java.util.function.IntFunction; 12 | import java.util.function.IntPredicate; 13 | import java.util.function.IntSupplier; 14 | import java.util.function.IntToLongFunction; 15 | import java.util.function.IntUnaryOperator; 16 | import java.util.function.LongConsumer; 17 | import java.util.function.LongFunction; 18 | import java.util.function.LongPredicate; 19 | import java.util.function.LongSupplier; 20 | import java.util.function.LongToIntFunction; 21 | import java.util.function.LongUnaryOperator; 22 | import java.util.function.Predicate; 23 | 24 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 25 | import com.madhusudhan.wr.allaboutlambdas.domain.Patient; 26 | 27 | /** 28 | * Class that demonstrates specialised functions for primitives usage 29 | * 30 | * @author mkonda 31 | * 32 | */ 33 | public class SpecialisedFunctions { 34 | 35 | /** 36 | * Method to check an even number function 37 | * @param number 38 | */ 39 | private void checkEvenNumber(int number) { 40 | Predicate evenNumber = x -> x % 2 == 0; 41 | 42 | // Testing the lambda 43 | System.out.println("The number is even?: "+evenNumber.test(number)); 44 | } 45 | 46 | private void checkEvenNumberUsingIntPredicate(int number) { 47 | IntPredicate evenNumber = x -> x % 2 == 0; 48 | 49 | // Testing the lambda 50 | System.out.println("The number is even?: "+evenNumber.test(number)); 51 | } 52 | 53 | /** 54 | * Examples of double and long predicates 55 | * 56 | */ 57 | private void specialisedPredicates(){ 58 | DoublePredicate doublePredicate = x -> x*0.01 < 1; 59 | LongPredicate longPredicate = x -> x < 10; 60 | } 61 | 62 | private void specialisedConsumers(){ 63 | IntConsumer intConsumer = x -> doSomething(x); 64 | intConsumer.accept(10); 65 | DoubleConsumer doubleConsumer = x -> doSomething(x); 66 | doubleConsumer.accept(20.50); 67 | LongConsumer longConsumer = x -> doSomething(x); 68 | longConsumer.accept(100l); 69 | } 70 | 71 | private void specialisedSuppliers(){ 72 | IntSupplier intSupplier= () -> 2; 73 | int value = intSupplier.getAsInt(); 74 | System.out.println("Supplier supplied with (int)"+value); 75 | 76 | DoubleSupplier doubleSupplier = () -> Math.PI; 77 | double piValue = doubleSupplier.getAsDouble(); 78 | System.out.println("Supplier supplied with (double)"+piValue); 79 | 80 | LongSupplier lognSupplier = () -> 100l; 81 | long longValue = lognSupplier.getAsLong(); 82 | System.out.println("Supplier supplied with (long) "+longValue); 83 | } 84 | 85 | /** 86 | * Functions specialised for primitives 87 | */ 88 | private void specialisedFunctions(){ 89 | // Using non-specialised function 90 | Function empFunction = null; 91 | // Converting to a specialised function 92 | IntFunction empFunction2 = null; 93 | 94 | 95 | // A double is provided and a String is returned 96 | DoubleFunction doubleFunction = d -> "PI is "+d; 97 | doubleFunction.apply(3.14); 98 | 99 | // Given a long id, a patient is returned 100 | LongFunction longFunction = id -> new Patient(id); 101 | longFunction.apply(10L); 102 | } 103 | 104 | private void primitiveConversionFunctions(){ 105 | 106 | LongToIntFunction longToInt = x -> Math.round(x); 107 | 108 | // Given a double value, return an integer 109 | DoubleToIntFunction doubleToInt = x -> 1; 110 | IntToLongFunction intToLongFunction = id -> { 111 | // Populate long value 112 | long encryptedId = 385038204;// prepare an encrypted id 113 | return encryptedId; 114 | }; 115 | } 116 | 117 | private void unitypeSpecialisedFunctions() { 118 | DoubleUnaryOperator doubleUnaryOperator = d -> d*0.01; 119 | IntUnaryOperator intUnaryOperator = i -> i*100; 120 | LongUnaryOperator longUnaryOperator = l-> l+l; 121 | 122 | double d = doubleUnaryOperator.applyAsDouble(10); 123 | int i = intUnaryOperator.applyAsInt(10); 124 | long l = longUnaryOperator.applyAsLong(10); 125 | 126 | System.out.println(d+","+i+", "+l); 127 | } 128 | 129 | IntSupplier intSupplier= () -> 2; 130 | private void doSomething(int x) { 131 | System.out.println("Consuming (int): "+x); 132 | } 133 | private void doSomething(double x) { 134 | System.out.println("Consuming (double): "+x); 135 | } 136 | private void doSomething(long x) { 137 | System.out.println("Consuming (long): "+x); 138 | } 139 | 140 | public static void main(String[] args) { 141 | new SpecialisedFunctions().checkEvenNumber(91); 142 | new SpecialisedFunctions().specialisedConsumers(); 143 | new SpecialisedFunctions().unitypeSpecialisedFunctions(); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/streamoperations/OptionalType.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.streamoperations; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Optional; 6 | import java.util.function.Supplier; 7 | 8 | import com.madhusudhan.wr.allaboutlambdas.domain.Student; 9 | import com.madhusudhan.wr.allaboutlambdas.domain.Teacher; 10 | 11 | /** 12 | * This class demonstrates the usage of the Optional type 13 | * 14 | * @author mkonda 15 | * 16 | */ 17 | public class OptionalType { 18 | 19 | /** 20 | * Find the sum of attendees but access the optional appropriately 21 | */ 22 | private void sumOfAttendees() { 23 | // List of attendees to various talks 24 | List attendees = Arrays.asList(22, 10, 13, 9); 25 | 26 | // Total attendees at the conference 27 | Optional totalAttendees = attendees.stream().reduce( 28 | Integer::sum); 29 | 30 | // Use the isPresent on the optional before accessing the value 31 | int total = totalAttendees.isPresent() ? totalAttendees.get() : 0; 32 | 33 | System.out.println("Total attendees: " + total); 34 | } 35 | 36 | private void noAttendeesOptional() { 37 | List attendees = Arrays.asList(); 38 | Optional noAttendees = attendees.stream().reduce(Integer::sum); 39 | 40 | if (noAttendees.isPresent()) 41 | System.out.println(noAttendees.get()); 42 | 43 | } 44 | 45 | private void creatingOptionals() { 46 | Student student = new Student(); 47 | Optional studentOptional = Optional.of(student); 48 | studentOptional.ifPresent(System.out::println); 49 | 50 | student = null; 51 | Optional studentOptional2 = Optional.ofNullable(student); 52 | 53 | System.out.println("Student can't be null:" + studentOptional2); 54 | 55 | } 56 | 57 | private void usingIfPresent() { 58 | Student student = new Student(); 59 | Optional studentOptional = Optional.of(student); 60 | studentOptional.ifPresent(System.out::println); 61 | } 62 | 63 | /** 64 | * Using orElse function 65 | */ 66 | private void usingOrElse() { 67 | Student student = null; 68 | Student defaultStudent = new Student(); 69 | defaultStudent.setName("Default John"); 70 | 71 | // We know that following optional is an issue 72 | Optional studentOptional = Optional.ofNullable(student); 73 | 74 | // Accessing the above will throw a NoSuchElementException 75 | // System.out.println(studentOptional.get()); 76 | 77 | // To avoid such issues, use the orElse that acts as a safe guard 78 | String name = studentOptional.orElse(defaultStudent).getName(); 79 | System.out.println("Get Name: " + name); 80 | 81 | } 82 | /** 83 | * Use orElseThrow to throw an exception if we are expecting an exception 84 | * @throws Exception 85 | */ 86 | 87 | private void usingOrElseThrow() throws Exception { 88 | Optional studentOptional = null; 89 | studentOptional.orElseThrow(Exception::new); 90 | } 91 | 92 | private void filteringAndMapping() { 93 | Student s = new Student(); 94 | s.setName("John Lingham"); 95 | s.setTeacher(new Teacher("Prof. Pandit")); 96 | 97 | Optional studentOptional = Optional.of(s); 98 | studentOptional 99 | .filter(student -> student.hasTeacher()) 100 | .ifPresent(System.out::println); 101 | 102 | studentOptional 103 | .map(student -> student.getName()) 104 | .ifPresent(System.out::println); 105 | } 106 | 107 | public static void main(String[] args) { 108 | /** 109 | * Uncomment these invocations as required 110 | */ 111 | // new OptionalType().sumOfAttendees(); 112 | // new OptionalType().noAttendeesOptional(); 113 | // new OptionalType().creatingOptionals(); 114 | // new OptionalType().usingIfPresent(); 115 | // new OptionalType().usingOrElse(); 116 | 117 | // try { 118 | // new OptionalType().usingOrElseThrow(); 119 | // } catch (Exception e) { 120 | // System.out.println("Expected exception: "); 121 | // e.printStackTrace(); 122 | // } 123 | // 124 | // new OptionalType().filteringAndMapping(); 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/streamoperations/StreamCommonOperations.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.streamoperations; 2 | 3 | import static java.util.stream.Collectors.toList; 4 | import static java.util.stream.Collectors.toMap; 5 | import static java.util.stream.Collectors.toSet; 6 | 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Optional; 12 | import java.util.OptionalInt; 13 | import java.util.Set; 14 | import java.util.stream.Collectors; 15 | import java.util.stream.Stream; 16 | 17 | import com.madhusudhan.wr.allaboutlambdas.domain.Actor; 18 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 19 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 20 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 21 | import com.madhusudhan.wr.allaboutlambdas.util.EmployeeUtil; 22 | import com.madhusudhan.wr.allaboutlambdas.util.MovieUtil; 23 | import com.madhusudhan.wr.allaboutlambdas.util.TradeUtil; 24 | 25 | /** 26 | * This class represents the filtering functionality 27 | * 28 | * @author mkonda 29 | * 30 | */ 31 | public class StreamCommonOperations { 32 | 33 | /** 34 | * Method to find executives from a list of employees 35 | */ 36 | private void findExecutives(List employees) { 37 | Stream empStream = employees.stream().filter( 38 | Employee::isExecutive); 39 | 40 | empStream.forEach(System.out::println); 41 | } 42 | 43 | /** 44 | * Method to demonstrate chaining of the filters. 45 | */ 46 | private void chainingFilters(List employees) { 47 | Stream empStream = employees.stream() 48 | .filter(e -> e.getDepartment().equals("Marketing")) 49 | .filter(Employee::isExecutive).filter(Employee::isSenior); 50 | 51 | empStream.forEach(System.out::println); 52 | } 53 | 54 | /** 55 | * Method for mapping functionality 56 | */ 57 | private void mapEmployeeName(List employees) { 58 | Stream empStream = employees.stream().map(Employee::getName) 59 | .map(String::toUpperCase); 60 | 61 | empStream.forEach(System.out::println); 62 | } 63 | 64 | /** 65 | * Method for mapping functionality 66 | */ 67 | private void upperCaseEmployees(List employees) { 68 | Stream employeeStream = employees.stream() 69 | .map(Employee::getName).map(String::toUpperCase); 70 | 71 | employeeStream.forEach(System.out::println); 72 | } 73 | 74 | /** 75 | * Method for mapping functionality 76 | */ 77 | private void actorStream(List movies) { 78 | Stream> actorStream = movies.stream().map(Movie::getActors); 79 | 80 | actorStream.forEach(System.out::println); 81 | } 82 | 83 | /** 84 | * Flattening a stream of list of actors to a stream of actors using flatMap function 85 | * 86 | * @param movies 87 | */ 88 | private void flatMapMovieActors(List movies) { 89 | 90 | Stream> actorsListStream = movies 91 | .stream() 92 | .map(Movie::getActors); 93 | actorsListStream.forEach(System.out::println); 94 | 95 | // Stream of Actors not Stream of List of Actors! 96 | Stream actorsStream = movies 97 | .stream() 98 | .flatMap(m -> m.getActors().stream()); 99 | 100 | actorsStream.forEach(System.out::println); 101 | 102 | } 103 | /** 104 | * Using flatMap function to flatten a stream of list of movies to stream of movies 105 | * @param movies 106 | */ 107 | private void flatMapMovies(List movies) { 108 | 109 | String[] action = new String[] { "Mission Impossible", "Sky Fall" }; 110 | String[] comedy = new String[] { "Johnny English", "Gods Must Be Crazy" }; 111 | String[] thriller = new String[] { "Bourne Identity", 112 | "The Ghost Writer", "Clear and Present Danger" }; 113 | 114 | List actionMoviesList = Arrays.asList(action); 115 | List comedyMoviesList = Arrays.asList(comedy); 116 | List thrillerMoviesList = Arrays.asList(thriller); 117 | 118 | Stream> actionMoviesStream = Stream.of(actionMoviesList, 119 | comedyMoviesList, thrillerMoviesList); 120 | 121 | // NOTE: make sure one of the blocks 122 | // is always commented - else you 123 | // will get an exception related to stream exhaustion 124 | 125 | // Movies Without Flattening 126 | // actionMoviesStream 127 | // .forEach(System.out::println); 128 | 129 | // With Flattening 130 | actionMoviesStream 131 | .flatMap(s -> s.stream()) 132 | .forEach(System.out::println); 133 | 134 | } 135 | 136 | /** 137 | * Collecting big trades to a list 138 | * @param args 139 | */ 140 | private void collectingToAList(List trades) { 141 | List bigTrades = 142 | trades 143 | .stream() 144 | .filter(Trade::isBigTrade) 145 | .collect(Collectors.toList()); 146 | 147 | bigTrades.forEach(System.out::println); 148 | } 149 | 150 | /** 151 | * This method demontrates the mechanism of collecting big trades to a set 152 | * @param trades 153 | */ 154 | private void collectingToASet(List trades) { 155 | Set bigTrades = trades 156 | .stream() 157 | .filter(Trade::isBigTrade) 158 | .collect(toSet()); 159 | 160 | bigTrades.forEach(System.out::println); 161 | } 162 | 163 | /** 164 | * This method creates a map of movie names against movie actors 165 | * 166 | * @param movies 167 | */ 168 | private void collectingToAMap(List movies) { 169 | 170 | Map> movieActorsMap = movies 171 | .stream() 172 | .collect(toMap(Movie::getName, movie -> movie.getActors())); 173 | 174 | movieActorsMap.forEach((name, actors) -> System.out.println(name+actors)); 175 | } 176 | 177 | /** 178 | * This method is used to find the distinct data set (removing duplicates) 179 | * @param employees 180 | */ 181 | private void distinctEmployees(List employees) { 182 | Stream employeesNamesStream = 183 | employees 184 | .stream() 185 | .map(Employee::getName); 186 | // .distinct(); 187 | 188 | employeesNamesStream.forEach(System.out::println); 189 | 190 | } 191 | 192 | /** 193 | * This method helps to understand the limit operation 194 | * @param employees 195 | */ 196 | private void limitOutput(List employees) { 197 | Stream employeesNamesStream = 198 | employees 199 | .stream() 200 | .map(Employee::getName) 201 | .limit(3); 202 | 203 | employeesNamesStream.forEach(System.out::println); 204 | } 205 | 206 | /** 207 | * This method demonstrates the skipping function 208 | * @param employees 209 | */ 210 | private void skipEmployees(List employees) { 211 | Stream employeesNamesStream = 212 | employees 213 | .stream() 214 | .skip(2) 215 | .map(Employee::getName); 216 | 217 | employeesNamesStream.forEach(System.out::println); 218 | } 219 | 220 | /** 221 | * This function finds the first big trade off the list. 222 | */ 223 | private void findFirst(List trades) { 224 | 225 | Optional firstBigTrade = trades 226 | .stream() 227 | .filter(Trade::isBigTrade) 228 | .findFirst(); 229 | 230 | System.out.println("First trade (using findFirst function): "+firstBigTrade.get()); 231 | } 232 | 233 | /** 234 | * Method that demonstrates the findAny function 235 | * @param trades 236 | */ 237 | private void findAny(List trades) { 238 | Optional anyTrade = trades 239 | .stream() 240 | .filter(Trade::isBigTrade) 241 | .findAny(); 242 | 243 | System.out.println("First trade (uisng findAny function): "+anyTrade.get()); 244 | 245 | } 246 | 247 | private void anyMatch(List trades) { 248 | boolean cancelledTrade = trades 249 | .stream() 250 | .anyMatch(t -> t.getStatus().equals("CANCELLED")); 251 | System.out.println("Cancelled trade (using anyMatch function) ?:"+cancelledTrade); 252 | } 253 | 254 | private void allMatch(List trades) { 255 | boolean ibmTrade = trades.stream() 256 | .allMatch(t -> t.getInstrument().equals("IBM")); 257 | 258 | System.out.println("IBM trade?(using allMatch function):"+ibmTrade); 259 | } 260 | 261 | private void noneMatch(List trades) { 262 | 263 | boolean cancelledTrade = trades 264 | .stream() 265 | .noneMatch(Trade::isCancelledTrade); 266 | System.out.println("Is cancelled trade present (using noneMatch function)?: "+cancelledTrade); 267 | } 268 | /** 269 | * Aggregating the sum of all trades using reduce function 270 | * @param trades 271 | */ 272 | private void reducingTradeQuantity(List trades) { 273 | Optional totalQuantity = trades 274 | .stream() 275 | .map(Trade::getQuantity) 276 | .reduce((a,b) -> a+b); 277 | System.out.println("Total quantity: "+totalQuantity.get()); 278 | } 279 | 280 | /** 281 | * Reducing the sum of all trades using primitives 282 | * @param trades 283 | */ 284 | private void reducingPrimitiveVersion(List trades) { 285 | OptionalInt totalQuantity = trades 286 | .stream() 287 | .mapToInt(Trade::getQuantity) 288 | .reduce(Integer::sum); 289 | System.out.println("Total quantity (unboxed version): "+totalQuantity.getAsInt()); 290 | } 291 | 292 | /** 293 | * Concatenating the instruments using reduction (no seed value given) 294 | * @param trades 295 | */ 296 | private void reduceNoSeed(List trades) { 297 | Optional instList = trades 298 | .stream() 299 | .map(Trade::getInstrument) 300 | .reduce((a,b)-> a+","+b); 301 | 302 | System.out.println("Comma separated instruments: "+instList); 303 | } 304 | 305 | /** 306 | * This method reduces a sum using a seed value 307 | * 308 | */ 309 | private void reduceUsingSeed() { 310 | List ints = Arrays.asList(11, 13, 12, 15); 311 | 312 | int sum = ints 313 | .stream() 314 | .reduce(10, (i,j) -> i+j); 315 | 316 | System.out.println("Total: "+sum); 317 | 318 | } 319 | public static void main(String[] args) { 320 | List movies = MovieUtil.createMoviesAndActors(); 321 | List trades = TradeUtil.createTrades(); 322 | List employees = EmployeeUtil.createEmployees(); 323 | 324 | // new StreamCommonOperations().findExecutives(employees); 325 | // new StreamCommonOperations().chainingFilters(employees); 326 | // new StreamCommonOperations().mapEmployeeName(employees); 327 | // new StreamCommonOperations().upperCaseEmployees(employees); 328 | // new StreamCommonOperations().actorStream(movies); 329 | 330 | // Flattening function 331 | // new StreamCommonOperations().flatMapMovieActors(movies); 332 | // new StreamCommonOperations().flatMapMovies(movies); 333 | 334 | // Collection function 335 | // new StreamCommonOperations().collectingToAList(trades); 336 | // new StreamCommonOperations().collectingToASet(trades); 337 | // new StreamCommonOperations().collectingToAMap(movies); 338 | 339 | // Distinct, Limit and Skip 340 | // new StreamCommonOperations().distinctEmployees(employees); 341 | // new StreamCommonOperations().limitOutput(employees); 342 | // new StreamCommonOperations().skipEmployees(employees); 343 | 344 | // Finder methods 345 | // new StreamCommonOperations().findFirst(trades); 346 | // new StreamCommonOperations().findAny(trades); 347 | // Match Methods 348 | // new StreamCommonOperations().anyMatch(trades); 349 | // new StreamCommonOperations().allMatch(trades); 350 | // new StreamCommonOperations().noneMatch(trades); 351 | 352 | // Reduce methods 353 | new StreamCommonOperations().reduceNoSeed(trades); 354 | new StreamCommonOperations().reduceUsingSeed(); 355 | } 356 | 357 | } 358 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/streams/DissectingStreams.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.streams; 2 | import java.util.List; 3 | 4 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 5 | import com.madhusudhan.wr.allaboutlambdas.util.MovieUtil; 6 | 7 | /** 8 | * This class represents some of the functionality of streams 9 | * 10 | * @author mkonda 11 | * 12 | */ 13 | public class DissectingStreams { 14 | 15 | List movies = MovieUtil.createMovies(); 16 | 17 | /** 18 | * A method to find the movies directed by a specific director 19 | * 20 | * @param director 21 | */ 22 | private void findMoviesByDirector(String director) { 23 | movies.stream() 24 | .filter(m-> m.getDirector().equals(director)) 25 | .map(Movie::getName) 26 | .forEach(System.out::println); 27 | } 28 | 29 | 30 | public static void main(String[] args) { 31 | new DissectingStreams().findMoviesByDirector("Steven Spielberg"); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/streams/StreamsBasics.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.streams; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 8 | import com.madhusudhan.wr.allaboutlambdas.util.TradeUtil; 9 | 10 | /** 11 | * This class is used to explain the differences in pre-Java8 and Java 8 style 12 | * of programming 13 | * 14 | * @author mkonda 15 | * 16 | */ 17 | public class StreamsBasics { 18 | private int ONE_MILLION = 1000000; 19 | List trades = TradeUtil.createTrades(); 20 | 21 | private List findLargeTradesPreJava8(List trades) { 22 | List largeTrades = new ArrayList(); 23 | 24 | for (Trade trade : trades) { 25 | if (trade.getQuantity() > ONE_MILLION && trade.isCancelledTrade()) { 26 | largeTrades.add(trade); 27 | } 28 | } 29 | return largeTrades; 30 | } 31 | 32 | private List findLargeTradesUsingStreams(List trades) { 33 | return trades.stream().filter(trade -> trade.getQuantity() > ONE_MILLION) 34 | .filter(Trade::isCancelledTrade).collect(Collectors.toList()); 35 | } 36 | 37 | private List findLargeTradesUsingParallelStreams(List trades) { 38 | return trades.parallelStream() 39 | .filter(trade -> trade.getQuantity() > ONE_MILLION) 40 | .filter(Trade::isCancelledTrade) 41 | .collect(Collectors.toList()); 42 | } 43 | 44 | private List findLargeTradesUsingParallelStreams2(List trades) { 45 | return trades.parallelStream() 46 | .filter(trade -> trade.getQuantity() > ONE_MILLION) 47 | .filter(trade -> trade.getInstrument().equals("IBM")) 48 | .collect(Collectors.toList()); 49 | } 50 | 51 | public static void main(String[] args) { 52 | List trades = TradeUtil.createTrades(); 53 | List largeTrades = new StreamsBasics() 54 | .findLargeTradesPreJava8(trades); 55 | System.out.println("Using pre-Java8:"+largeTrades); 56 | 57 | largeTrades = new StreamsBasics() 58 | .findLargeTradesUsingStreams(trades); 59 | 60 | System.out.println("Using streams:"+largeTrades); 61 | 62 | largeTrades = new StreamsBasics() 63 | .findLargeTradesUsingParallelStreams(trades); 64 | 65 | System.out.println("Using parallel streams:"+largeTrades); 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/util/EmployeeUtil.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Employee; 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Manager; 8 | 9 | 10 | public class EmployeeUtil { 11 | public static List createEmployees() { 12 | 13 | List employees = new ArrayList<>(); 14 | 15 | Manager manager1 = new Manager("Sarah James"); 16 | Manager manager2 = new Manager("Elizabeth Williamson"); 17 | 18 | Employee emp1 = new Employee(0,"Harry Barry", "Finance", true); 19 | emp1.setManager(manager1); 20 | emp1.setSenior(true); 21 | employees.add(emp1); 22 | 23 | 24 | Employee emp2 = new Employee(1,"Hasro Biko", "IT", false); 25 | emp2.setSenior(true); 26 | employees.add(emp2); 27 | 28 | emp2.setManager(manager2); 29 | 30 | Employee emp3 = new Employee(2,"Ram Nivas", "Strategy", true); 31 | employees.add(emp3); 32 | emp3.setManager(manager1); 33 | 34 | Employee emp4 = new Employee(3,"John Bhaijan", "Marketing", true); 35 | emp4.setSenior(true); 36 | employees.add(emp4); 37 | emp4.setManager(manager2); 38 | 39 | Employee emp5 = new Employee(3,"Kirk Carlos", "Marketing", false); 40 | employees.add(emp5); 41 | emp5.setManager(manager2); 42 | 43 | Employee emp6 = new Employee(3,"Kirk Carlos", "Marketing", false); 44 | employees.add(emp5); 45 | emp5.setManager(manager2); 46 | 47 | return employees; 48 | 49 | } 50 | 51 | public static List createDetailedEmployees() { 52 | 53 | List employees = new ArrayList<>(); 54 | 55 | Manager manager1 = new Manager("Sarah James"); 56 | Manager manager2 = new Manager("Elizabeth Williamson"); 57 | 58 | Employee emp1 = new Employee(0,"Harry Barry", "Finance", "London"); 59 | emp1.setExecutive(true); 60 | emp1.setSenior(true); 61 | emp1.setManager(manager1); 62 | employees.add(emp1); 63 | 64 | Employee emp2 = new Employee(1,"Hasro Biko", "IT", "New York"); 65 | emp2.setExecutive(false); 66 | emp2.setSenior(false); 67 | employees.add(emp2); 68 | emp2.setManager(manager2); 69 | 70 | Employee emp3 = new Employee(2,"Ram Nivas", "Strategy", "London"); 71 | employees.add(emp3); 72 | emp3.setExecutive(true); 73 | emp3.setSenior(true); 74 | emp3.setManager(manager1); 75 | 76 | Employee emp4 = new Employee(3,"John Bhaijan", "Marketing", "Hyderabad"); 77 | employees.add(emp4); 78 | emp4.setExecutive(true); 79 | emp4.setSenior(true); 80 | emp4.setManager(manager2); 81 | 82 | Employee emp5 = new Employee(3,"Kirk Carlos", "Marketing", "New York"); 83 | employees.add(emp5); 84 | emp5.setExecutive(false); 85 | emp5.setSenior(true); 86 | emp5.setManager(manager2); 87 | 88 | Employee emp6 = new Employee(3,"Kirk Carlos", "Marketing", "New York"); 89 | employees.add(emp5); 90 | emp6.setExecutive(false); 91 | emp6.setSenior(true); 92 | emp5.setManager(manager2); 93 | 94 | return employees; 95 | 96 | } 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/util/MovieUtil.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Actor; 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 8 | 9 | public class MovieUtil { 10 | public static List createMovies() { 11 | 12 | List movies = new ArrayList<>(); 13 | 14 | Movie movie = new Movie("Gods Must Be Crazy", false,""); 15 | movies.add(movie); 16 | movie = new Movie("Fiddler On The Roof", true, ""); 17 | movies.add(movie); 18 | movie = new Movie("Sound of Music", true, ""); 19 | movies.add(movie); 20 | movie = new Movie("Ben-Hur", true,""); 21 | movies.add(movie); 22 | // movie = new Movie("Jurassic Park", false,"Steven Spielberg"); 23 | // movies.add(movie); 24 | movie = new Movie("Jurassic Park", false,"Steven Spielberg"); 25 | movies.add(movie); 26 | movie = new Movie("ET", false,"Steven Spielberg"); 27 | movies.add(movie); 28 | movie = new Movie("Saving Private Ryan", false,"Steven Spielberg"); 29 | movies.add(movie); 30 | movie = new Movie("Catch Me If You Can", false,"Steven Spielberg"); 31 | movies.add(movie); 32 | return movies; 33 | 34 | } 35 | 36 | public static List createMoviesAndActors() { 37 | 38 | List movies = new ArrayList<>(); 39 | List actors1 = new ArrayList<>(); 40 | Actor actor = null; 41 | Movie movie = null; 42 | 43 | 44 | movie = new Movie("Sound Of Music"); 45 | actor = new Actor("Julie Andrews"); 46 | actors1.add(actor); 47 | actor = new Actor("Christopher Plummer"); 48 | actors1.add(actor); 49 | movie.setActors(actors1); 50 | 51 | movies.add(movie); 52 | 53 | List actors2 = new ArrayList<>(); 54 | movie = new Movie("Jurassic Park"); 55 | actor = new Actor("Sam Neil"); 56 | actors2.add(actor); 57 | actor = new Actor("Jeff Goldblum"); 58 | actors2.add(actor); 59 | movie.setActors(actors2); 60 | 61 | movies.add(movie); 62 | 63 | return movies; 64 | 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/util/TradeUtil.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 7 | 8 | /** 9 | * A utility class used to create set of trades 10 | * @author mkonda 11 | */ 12 | public class TradeUtil { 13 | 14 | public static List createTrades(){ 15 | List trades = new ArrayList(); 16 | 17 | Trade t = new Trade(1, "GOOG",200000,"CANCEL"); 18 | trades.add(t); 19 | t = new Trade(2,"APPL",2000000,"CANCEL"); 20 | trades.add(t); 21 | t = new Trade(3,"IBM",3000000,"NEW"); 22 | trades.add(t); 23 | t = new Trade(4,"IBM",4000000,"PENDING"); 24 | trades.add(t); 25 | 26 | return trades; 27 | } 28 | 29 | public static List createTrades(int size){ 30 | List trades = new ArrayList<>(); 31 | 32 | for (int i = 0; i < size; i++) { 33 | Trade t = new Trade("ISUER "+i,i+1000,"NEW"); 34 | trades.add(t); 35 | } 36 | 37 | return trades; 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithlambdas/CapturingLambda.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithlambdas; 2 | 3 | 4 | public class CapturingLambda { 5 | 6 | private String defaultGreeting = "Howdy, "; 7 | 8 | interface Greeting { 9 | void sayHello(String name); 10 | } 11 | 12 | private void accessLambdaVariables() { 13 | Greeting g = (name) -> { 14 | System.out.println(name); 15 | }; 16 | 17 | // Cannot access lamdba's input variable 18 | // System.out.println("Can I access lambda's variable:"+name); 19 | } 20 | 21 | private void accessInstanceVariables() { 22 | Greeting g = (name) -> { 23 | // Accessing an instance variable 24 | System.out.println(defaultGreeting + name); 25 | }; 26 | } 27 | 28 | 29 | public static void main(String[] args) { 30 | CapturingLambda cl = new CapturingLambda(); 31 | 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithlambdas/EffectivelyFinalLambda.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithlambdas; 2 | 3 | /** 4 | * A class to demonstrate effectively final variable access 5 | * 6 | * @author mkonda 7 | * 8 | */ 9 | public class EffectivelyFinalLambda { 10 | 11 | // Instance variable 12 | private String instanceVariable = "Instance Variable"; 13 | 14 | /** 15 | * Method to test the local variable's effective final state. 16 | * 17 | * 18 | */ 19 | private void modifyLocalVariable() { 20 | // Local non-final variable 21 | int count = 0; 22 | 23 | // The Lambda which tries to modify the count 24 | // The code throws error as compiler won't allow (it must be effectively final) 25 | // new Thread(() -> System.out.println(count++) ).start(); 26 | } 27 | 28 | /** 29 | * Method that shows overriding the instance variable in a lambda 30 | */ 31 | private void modifyClassInstanceVariable() { 32 | // Local non-final variable 33 | instanceVariable = "Modified Instance Variable"; 34 | // We can't modify (it must be effectively final) 35 | 36 | new Thread(() -> System.out.println(instanceVariable) ).start(); 37 | 38 | } 39 | 40 | 41 | public static void main(String[] args) { 42 | new EffectivelyFinalLambda().modifyLocalVariable(); 43 | new EffectivelyFinalLambda().modifyClassInstanceVariable(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithlambdas/LambdaAnonymousScope.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithlambdas; 2 | 3 | public class LambdaAnonymousScope { 4 | 5 | private void execute() { 6 | 7 | new Thread(() -> System.out.println("Lambda hashcode:"+this.hashCode())).start(); 8 | 9 | Runnable runnable = new Runnable(){ 10 | @Override 11 | public void run() { 12 | System.out.println("Runnable's hashcode:"+this.hashCode()); 13 | } 14 | }; 15 | Thread t = new Thread(runnable); 16 | 17 | t.start(); 18 | System.out.println("Thread's hashcode:"+t.hashCode()); 19 | System.out.println("Runnable's hashcode:"+runnable.hashCode()); 20 | } 21 | 22 | public static void main(String[] args) { 23 | new LambdaAnonymousScope().execute(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithlambdas/LambdaRedeclaringVariables.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithlambdas; 2 | 3 | public class LambdaRedeclaringVariables { 4 | 5 | private static String className = "Class Name"; 6 | 7 | public interface IComponent{ 8 | String name(); 9 | } 10 | 11 | private void testComp(IComponent comp) { 12 | System.out.println("Name: "+comp.name()); 13 | } 14 | private void testLocalVariable() { 15 | final String myName = "Modified Name";; 16 | IComponent cc = () -> { 17 | // Error! Redeclaring the variable 18 | // String myName = null; 19 | return myName; 20 | }; 21 | } 22 | 23 | private void getDefaultName() { 24 | 25 | } 26 | 27 | public static void main(String[] args) { 28 | LambdaRedeclaringVariables scope = new LambdaRedeclaringVariables(); 29 | 30 | IComponent comp = () -> "Default Name"; 31 | scope.testComp(comp); 32 | String name = "Main Name"; 33 | IComponent comp1 = () -> {return name;}; 34 | scope.testComp(comp1); 35 | IComponent comp2 = () -> {return className;}; 36 | scope.testComp(comp2); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithlambdas/LambdaThisStaticSuperAccess.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithlambdas; 2 | 3 | /** 4 | * Class demonstrating the lexical scoping functionality 5 | * @author mkonda 6 | * 7 | */ 8 | public class LambdaThisStaticSuperAccess extends SuperScope{ 9 | private String instanceName="instanceVariableName"; 10 | private static String staticName = "staticVariableName"; 11 | 12 | Runnable runnableLambda = () ->{ 13 | print("Super variable: "+super.superName); 14 | print("Instance variable: "+this.instanceName); 15 | print("Static variable: "+LambdaThisStaticSuperAccess.staticName); 16 | }; 17 | 18 | private void execute() { 19 | new Thread(runnableLambda).start(); 20 | } 21 | 22 | private void print(String string) { 23 | System.out.println(string); 24 | } 25 | public static void main(String[] args) { 26 | new LambdaThisStaticSuperAccess().execute(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithlambdas/SuperScope.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithlambdas; 2 | 3 | public class SuperScope { 4 | String superName = "superVariableName"; 5 | } 6 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithstreams/CreatingStreams.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithstreams; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | import java.nio.file.Paths; 7 | import java.nio.file.attribute.BasicFileAttributes; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Random; 11 | import java.util.function.BiPredicate; 12 | import java.util.function.Supplier; 13 | import java.util.stream.Stream; 14 | 15 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 16 | 17 | 18 | /** 19 | * This class represents various ways of creating Streams 20 | * 21 | * @author mkonda 22 | * 23 | */ 24 | 25 | public class CreatingStreams { 26 | /** 27 | * Creating a stream of empty values 28 | */ 29 | private void testEmptyStreams() { 30 | Stream moviesEmptyStream = Stream.empty(); 31 | System.out.println("Number of movies:" + moviesEmptyStream.count()); 32 | } 33 | 34 | /** 35 | * Creating a stream from a set of seed values 36 | */ 37 | private void testStreamsFromValues() { 38 | Stream movieNames = Stream.of("Gods Must Be Crazy", 39 | "Fiddler On The Roof", "Ben-Hur"); 40 | 41 | movieNames.forEach(System.out::println); 42 | 43 | // Array of movies 44 | String[] movieNames2 = { "Gods Must Be Crazy", "Fiddler On The Roof" }; 45 | Stream mNames2 = Stream.of(movieNames2); 46 | 47 | mNames2.forEach(System.out::println); 48 | 49 | // List of movies 50 | List moviesList = new ArrayList<>(); 51 | moviesList.add("The Sound of Music"); 52 | moviesList.add("Gone with the Wind"); 53 | 54 | // Creating the stream with a list of movies 55 | Stream> fromList = Stream.of(moviesList); 56 | fromList.forEach(System.out::println); 57 | } 58 | 59 | /** 60 | * Creating infinite streams - a stream of continuous random numbers 61 | */ 62 | private void testInfiniteStreams() { 63 | Random rand = new Random(); 64 | Supplier randomIntegerSupplier = () -> { 65 | return rand.nextInt(100); 66 | }; 67 | // Infinite stream of random ints 68 | Stream randomIntStream = Stream 69 | .generate(randomIntegerSupplier); 70 | randomIntStream.forEach(System.out::println); 71 | 72 | // Infinite stream of random Doubles 73 | Stream randomStream = Stream.generate(Math::random); 74 | randomStream.forEach(System.out::println); 75 | 76 | // Infinite stream of whole numbers starting from 1 77 | Stream wholeNumbers = Stream.iterate(1, i -> i + 1); 78 | wholeNumbers.forEach(System.out::println); 79 | 80 | } 81 | 82 | /** 83 | * Creating a stream from a File 84 | * 85 | * @throws IOException 86 | */ 87 | private void testFileStream() throws IOException { 88 | 89 | // Stream of lines read from a file 90 | Stream fileLines = Files.lines(Paths 91 | .get("/Users/mkonda/Temp/tmp.txt")); 92 | fileLines.forEach(System.out::println); 93 | 94 | // Stream of Paths 95 | Path root = Paths.get("/Users/mkonda/Temp"); 96 | int maxDepth = Integer.MAX_VALUE; 97 | BiPredicate filter = (path, attrs) -> true; 98 | Stream pathStream = Files.find(root, maxDepth, filter); 99 | pathStream.forEach(System.out::println); 100 | 101 | } 102 | 103 | public static void main(String[] args) throws IOException { 104 | new CreatingStreams().testEmptyStreams(); 105 | new CreatingStreams().testStreamsFromValues(); 106 | new CreatingStreams().testInfiniteStreams(); 107 | new CreatingStreams().testFileStream(); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithstreams/IterationStrategy.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithstreams; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 7 | import com.madhusudhan.wr.allaboutlambdas.util.MovieUtil; 8 | 9 | /** 10 | * This class demonstrates the fundamentals of internal and external iteration strategies 11 | * 12 | * @author mkonda 13 | * 14 | */ 15 | public class IterationStrategy { 16 | List movies = MovieUtil.createMovies(); 17 | List top2Classics = new ArrayList(10); 18 | 19 | /** 20 | * Gathering classic movies using a traditional for loop 21 | */ 22 | private void externalIteration() { 23 | for(Movie m: movies){ 24 | if(m.isClassic()){ 25 | top2Classics.add(m); 26 | } 27 | } 28 | System.out.println("Top two classics (using external iteration): " + top2Classics); 29 | } 30 | 31 | /** 32 | * Gathering classics using internal iteration (using streams) 33 | */ 34 | private void internalIteration() { 35 | movies.parallelStream() 36 | .filter(Movie::isClassic) 37 | .map(Movie::getName) 38 | .limit(2) 39 | .forEach(System.out::println); 40 | } 41 | 42 | 43 | public static void main(String[] args) { 44 | new IterationStrategy().externalIteration(); 45 | new IterationStrategy().internalIteration(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithstreams/LazyAndEagerStreams.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithstreams; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | import java.util.stream.Stream; 6 | 7 | import com.madhusudhan.wr.allaboutlambdas.domain.Movie; 8 | import com.madhusudhan.wr.allaboutlambdas.util.MovieUtil; 9 | 10 | /** 11 | * This class demonstrates the lazy and eager characteristics of streams 12 | * 13 | * @author mkonda 14 | * 15 | */ 16 | public class LazyAndEagerStreams { 17 | List movies = MovieUtil.createMovies(); 18 | 19 | /** 20 | * Lazy intermediate operations 21 | */ 22 | private void lazyIntermediateOperator() { 23 | 24 | // The filter is never executed 25 | Stream movieStream = movies 26 | .stream() 27 | .filter(m -> { 28 | System.out.println("Lazy operation"); 29 | return m.isClassic(); 30 | }).limit(2); 31 | 32 | // Unless we add a terminal operator - uncomment and rerun 33 | // movieStream.forEach(System.out::println); 34 | } 35 | /** 36 | * Eager terminal operations 37 | */ 38 | private void eagerTerminalOperator() { 39 | movies 40 | .stream() 41 | .filter(m -> { 42 | System.out.println("Filtering"); 43 | return m.isClassic(); 44 | }) 45 | .map(s -> { 46 | System.out.println("Mapping"); 47 | return s; 48 | }) 49 | .forEach(System.out::println); 50 | // .collect(Collectors.toList()); 51 | 52 | } 53 | 54 | public static void main(String[] args) { 55 | // new LazyAndEagerStreams().lazyIntermediateOperator(); 56 | new LazyAndEagerStreams().eagerTerminalOperator(); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/com/madhusudhan/wr/allaboutlambdas/workingwithstreams/PrimitiveStreams.java: -------------------------------------------------------------------------------- 1 | package com.madhusudhan.wr.allaboutlambdas.workingwithstreams; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.stream.DoubleStream; 6 | import java.util.stream.IntStream; 7 | 8 | import com.madhusudhan.wr.allaboutlambdas.domain.Trade; 9 | import com.madhusudhan.wr.allaboutlambdas.util.TradeUtil; 10 | 11 | 12 | /** 13 | * This class demonstrates the working of streams with primitives 14 | * 15 | * @author mkonda 16 | * 17 | */ 18 | public class PrimitiveStreams { 19 | List trades = TradeUtil.createTrades(); 20 | 21 | /** 22 | * Creating stream of ints - IntStream 23 | */ 24 | private void intStream() { 25 | int[] ints = new int[]{10,20,30,40,50}; 26 | 27 | IntStream intStream = IntStream.of(ints); 28 | intStream.forEach(System.out::println); 29 | 30 | IntStream intStream2 = IntStream.of(10,20,30,40,50); 31 | intStream2.forEach(System.out::println); 32 | } 33 | 34 | /** 35 | * Creating stream of doubles - DoubleStream 36 | */ 37 | private void doubleStream() { 38 | double[] doubles = new double[]{2.4, 4.2, 6.3, 8.5, 10.1}; 39 | DoubleStream doubleStream1 = DoubleStream.of(doubles); 40 | doubleStream1.forEach(System.out::println); 41 | 42 | DoubleStream doubleStream2 = DoubleStream.of(1.1,22.33,3.4); 43 | doubleStream2.forEach(System.out::println); 44 | } 45 | /** 46 | * Summing up the quantity using Object references. The quantity is boxed up. 47 | */ 48 | private void sumUsingObjectStream() { 49 | Optional sumQuantity = trades 50 | .stream() 51 | .map(Trade::getQuantity) 52 | .reduce(Integer::sum); 53 | 54 | System.out.println("Total quantity (using object stream):"+sumQuantity.get()); 55 | } 56 | 57 | /** 58 | * Summing up the quantity using primitive stream. The Object stream is converted to a primitive stream 59 | */ 60 | private void sumUsingPrimitiveStream() { 61 | int sumQuantity = trades 62 | .stream() 63 | .mapToInt(Trade::getQuantity) 64 | .sum(); 65 | 66 | System.out.println("Total quantity (using primitive stream):"+sumQuantity); 67 | } 68 | 69 | public static void main(String[] args) { 70 | new PrimitiveStreams().intStream(); 71 | new PrimitiveStreams().doubleStream(); 72 | new PrimitiveStreams().sumUsingObjectStream(); 73 | new PrimitiveStreams().sumUsingPrimitiveStream(); 74 | } 75 | 76 | } 77 | --------------------------------------------------------------------------------