
Explore how lambdas transform Java from verbose to concise, improving code readability and maintainability while reducing costs through clearer source code.
Learn a verbose approach that groups strings by length using a hash map, with keys as string lengths and values as lists of strings of that length, including initialization.
Explore how a verbose comparator sorts strings by length then alphabetically, using an anonymous class, and discuss when to favor conciseness over clarity.
Master Java lambdas and streams through hands-on sections that cover lambda syntax, functional interfaces, stream operations, reductions, collectors, and debugging, with behind-the-scenes bytecode and invoke dynamic insights.
Explore lambdas and streams through a what, how, and why approach, with practical exercises, refactoring, and guidance on the optional api and java eight concepts.
Explore how to solve list-sorting exercises in Java using anonymous classes, then replace them with lambda expressions, use the Comparator.comparing method, and apply method references.
Download and unzip the complete source code, then navigate to the lambdas.S.H.01 and streams.S.H.07 packages to locate the Java files and explore the course material.
Explore continuous refactoring of a simple employee management system, embracing changing requirements while illustrating the strategy pattern and an anonymous class through a developer's journey.
Implement two requirements in a simple employee management system: retrieve employees by unit, first for EBC then for FSA, by filtering a preexisting list and validating results with tests.
Show how a method with a skill enum filters employees by contains on their skills list to return Java developers, and discuss copy-paste pitfalls for senior employees over 10 years.
Follow a code walkthrough in Eclipse that details the employee class with unit and designation enums and skills, then refactors methods to fetch by unit, Java skills, and senior employees.
Explore the strategy pattern in Java by implementing a strategy interface with concrete strategies to filter employees by unit, skill, or experience, and apply it to the employee management system.
Understand how the strategy pattern uses an employee filter interface with concrete strategies—ABC filter, Java filter, and senior professionals filter—to enable flexible, open-closed filtering.
Explore the strategy pattern by implementing filters for the EDC unit, programming skills, and senior professionals, all driven by a single get all employees filtered by method.
Discover how anonymous classes in Java enable declaring and instantiating a class on the fly, replacing the strategy pattern, and refactoring the code in Eclipse for GUI applications.
Refactor the strategy pattern by replacing strategy classes with anonymous classes, using Runnable and employee filter interfaces to simplify one-time tasks and improve readability.
Rewrite anonymous classes with a lambda expression to run a long running operation in a thread, showing that run takes no parameters and returns void, delivering cleaner code.
Understand how lambda expressions implement functional interfaces in Java, including syntax, single abstract method, and the role of the functional interface annotation.
Refactor lambda expressions to improve readability while preserving behavior, illustrating higher-order functions by passing and returning functions via functional interfaces.
Explore predicate, consumer, supplier, and function interfaces in Java, apply them in employee management refactoring, and review default methods and collection API evolution to build a foundation for lambda expressions.
Refactor Java code by replacing the employee filter with the predicate interface, using its test method for filtering, and explore combining predicates to retrieve employees by unit and skills.
Combine multiple predicates with the predicate functional interface to filter employees by Java skills and unit using lambdas and streams, and the and method.
Explore how Java's removeIf, a default collection method, uses a lambda predicate to remove stale items from a list, avoiding concurrent modification and improving clarity over iterator or loop approaches.
Explore the Java supplier functional interface, its get method, and primitive specializations to avoid boxing, then learn how to pass behavior as a lambda to generate random coupons.
Implement a factory using the supplier functional interface to decouple commodity creation from trading logic, enabling lazy object creation and easy extension for new commodities.
Use ThreadLocal with the supplier functional interface to give each thread its own simple date format, avoiding shared state and improving date parsing across threads.
Explore how the Java logging API uses the supplier interface to make logging lazy, avoiding expensive message construction.
Explore the consumer functional interface in Java, learning how accept consumes a value and andThen composes a sequence of behaviors, with Eclipse-based examples.
Explore the Java consumer functional interface, its accept method, and how to pass behavior as lambdas. See examples of single-parameter consumers, chaining, and a generic perform operation with lists.
Demonstrates using the consumer functional interface and its andThen method to compose sequential actions, such as sending a Kafka message and storing a response in a database.
Explore how the forEach method uses the consumer functional interface and lambdas to print each string in a list, simplifying iteration and focusing on what to do rather than how.
Explore the BiConsumer functional interface in the JDK, pass two parameters with lambda expressions, and apply it to maps via forEach and entrySet to display key-value pairs.
Explore the Java function interface and its apply method, using lambdas to transform inputs into outputs, from string lengths and uppercase names to emails and primitive max values.
Learn to compose transformations with the andThen method of the Java function interface, turning strings into customer objects and chaining results through a single data pipeline.
Explore the difference between andThen and compose in Java's function interface, illustrating how execution order affects profit and subsequent transformations using real-world examples.
Explore how to apply Java predicate and function interfaces together to filter trades, transform them into stock symbols and volumes, and refactor high volume stock queries.
Explore how computeIfAbsent uses the function interface and lambdas to build a multi map from city data, mapping city first letters to city lists in core JDK apps.
Explore how functional interfaces in the Java function package enable transformations and actions, including predicate, consumer, supplier, and function, with primitive specializations and two-parameter variants for efficient, typed operations.
Dive into how lambda expressions are implemented behind the scenes in Java, examine bytecode-level details, explore method handles, and compare with dynamic languages to reveal an elegant solution.
Explore the differences between statically and dynamically typed languages, the compiler and runtime roles, and how dynamic languages run on the JVM using bytecode and invocation instructions.
Describe how invokedynamic introduces a new bytecode and method handles to bridge dynamic languages with the JVM, enabling custom runtime linkage and efficient dynamic dispatch.
Explore how the lambda meta factory uses invokedynamic and a bootstrap method to create runtime inner classes, distinguishing capturing from non-capturing lambdas and their synthetic methods.
Discover how lambda expressions translate at the bytecode level with dynamic instruction and invoke dynamic, and how the just-in-time compiler boosts runtime performance.
Explore how Java lambda expressions capture local variables and when they must be final or effectively final, with examples of compilation issues and the rationale to avoid race conditions.
Explore how lexical scope governs name resolution in lambda expressions versus anonymous inner classes, and how this refers to the enclosing environment to access outer variables.
Explore how lambda expressions offer concise, expressive, and focused code, and why they replace anonymous classes only for single-method functional interfaces, not for anonymous classes with state.
Refactor the employee sorting code by replacing anonymous comparators with lambdas, using type inference, to sort by name, then experience (ascending), and finally by name for ties.
Sorts employee objects using comparator helpers: comparing, thenComparing, and reversed, leveraging lambda expressions and key extractors to order by name and experience.
Discover the four types of method references in Java: static methods, constructors, instance methods of arbitrary types, and instance methods of existing objects.
Refactor sorting methods by replacing lambdas with method references, including static, instance, and existing object references, to improve readability and efficiency in Java.
Refactor imperative code into a declarative stream pipeline using stream, filter, and collect to retrieve senior employees with more than 10 years of experience.
Discover where the stream method lives on lists and how a stream acts as a data pipe with no storage for processing employee objects declaratively.
Describe how the map method in the stream API transforms objects from one type to another using lambda expressions, with examples of filtering, uppercasing names, and collecting results.
Apply the map method in Java streams to transform employee objects into names by filtering a skill and collecting the results, yielding Stanley and Manoj.
Explore the lazy nature of streams by building a pipeline with a source, intermediate operations like filter and map, and a terminal collect operation.
Analyze how a stream pipeline processes each item in a single pass, with filter and map, without temporary data structures, as data flows top to bottom to be collected.
Use the sorted method with streams to filter employees with more than one skill, sort by experience, and return their names.
Explore using Objects.nonNull in a stream filter to safely handle an employee's null skills, avoiding null pointer exceptions and improving readability with predicates and lambdas.
Use the distinct function in streams to deduplicate customer names by equals and hashCode, then map to uppercase. Filter Java-skilled employees, then apply distinct to fetch unique unit names.
Explore how stream pipelines distinguish stateful and stateless intermediate operations. See stateless filters and maps, and stateful sorts and distinct, with data buffering and the original list not modified.
Explains why methods that return a list should yield an empty list rather than null to avoid null pointer exceptions and simplify client code.
Explore why the Optional API in Java was introduced to indicate presence or absence of a value, compare with nulls and exceptions, and preview its basic methods.
Explore the optional class in Java by examining methods like off, is present, empty, or else, and off nullable, get, to understand handling absent values with optional wrappers.
Explore the design intention of the Java optional class by examining a first-match method that returns an optional and uses or a default when no match exists, with pattern matching.
Learn to find the first matching employee in a stream using filter and findFirst, and handle the Optional class value safely without overusing get.
Learn how findFirst guarantees the first match in a stream, while findAny may return any match. The lecture demonstrates filtering by skill and handling optional results with map and orElse.
Read a 173,000-word dictionary file using Java streams to find the first word longer than 20 characters, and any word starting with the letter a and length over 10.
Explore anyMatch, allMatch, and noneMatch in Java streams, using predicates and lambdas to short-circuit a pipeline, with practical examples like recent orders and high-value transactions.
Explore why the optional class was introduced in Java as an API return type to signal absent values and reduce null pointer errors, and learn scenarios to avoid overuse.
Explore how streams differ from collections: streams have no storage, are lazy and unbounded, and are functional; collections store finite elements and allow mutation.
Discover how to perform reduction on a stream to produce a single result, such as summing transactional values, identifying minimum goals, or the highest grossing movie.
Explore how the reduced method replaces imperative summation with declarative stream operations using a lambda or method reference, and switch to a parallel stream for parallel processing.
Explore how to compute the sum of word lengths using a stream pipeline by filtering blanks, mapping to length, and using reduce or the built-in sum method.
Explore how the stream count method counts elements by filtering today’s transactions, mapping them to one via mapToLong, and summing the results as a reduction.
Learn how to use Java's max and min methods on a stream to find the largest or smallest bank transaction by amount on a given date, returning an optional result.
Learn that collect in Java streams performs mutable reduction, contrasting it with immutable reduction performed by reduce, and see how collectors create data structures like hash maps and hash sets.
Explore reading a dictionary file with streams in Java, using filter, map, and reduce to find the maximum word length, and handle Optional from max.
Explore the Collectors' class methods in Java to group and partition stream elements, understand downstream collectors, and embrace declarative, reusable code for collecting into lists.
Explore the collectors class as the implementation of the collector interface, enabling declarative collection into lists, sets, maps, unmodifiable variants, and joining, plus single-pass summary statistics on data.
Explore the football team domain with three classes modeling name, league (Premier League, La Liga, Bundesliga, Champions League), goals for, goals against, goal difference, and points.
Group football teams by league using an imperative approach with a hash map. Use computeIfAbsent to simplify updates and preview a collectors approach in upcoming content.
Group football teams by style of play with Java's groupingBy in collectors, classifying them as attacking or defensive by goals over 20, via a lambda and stream.
Group football teams by league and then by style of play using multilevel grouping with collectors. Refactor lambdas into a method to detect attacking or defensive style.
Explore using grouping by with a downstream collector, mapping teams to names, and joining them with a comma per league.
Learn to partition a list using the partitioning by method and then group teams by league within each partition, using a downstream collector.
Join the most comprehensive course that covers Lambdas and Streams introduced in Java 8.
There are lots of exercises (along with the solution) at the end of a section that will help you gain confidence.
Using numerous real-life examples, you will learn:
What the Strategy pattern is
What kinds of problems do Anonymous classes solve?
Why do we need Lambda expressions?
How can Lambda expressions help us in writing concise code?
What are higher-order functions?
Deep dive into how Lambda expressions are implemented behind the scenes and -
Understand how to look at byte code using javap
Understand the role of the invokedynamic byte code instruction
What are Method Handles
Commonly used functional interfaces like Predicate, Function, Supplier, Consumer, BiConsumer -
How and where to apply them?
How are they used internally in the JDK library?
Function composition
Method references
Explore the Comparator interface
Numerous methods in the Stream API like - filter, map, collect, sorted, distinct
Understanding what a stream is
Understanding the important characteristics of a stream
Optional API and the right way to use them
Short-circuiting operations in the Stream pipeline
Understand why we need Primitive Streams
Reduction operations in the Stream pipeline and the importance of identity in Reduction
Explore the Collectors API
Explore flatMap and other sources of creating Streams
Explore Parallel Streams -
1. What is Moore's law?
2. Why do we need Parallel streams?
3. When should we use Parallel streams?
4. What is the infrastructure behind the scenes when we use Parallel streams?
5. How does Reduction work in parallel streams?
6. Role of the Spliterator
Learn how to debug and visualize Java 8 Streams with Eclipse & Intellij
and more!
Students completing the course will have a solid, in-depth knowledge of writing concise code using many features that have truly revolutionized how we write code in Java.
Now includes a focused PDF guide on Java 8 Lambdas & Streams — with fresh examples, best practices, and a quick reference table for coding and interviews.
What if you have questions?
I offer full support, 7 days a week, answering any questions you have.
What version of Java should you use?
I am using Java 14 for all the demos since that is the latest version when recording this course. I would urge you to use the latest version of Java. However, the focus will be on Lambdas, Streams, and lots of other features introduced in Java 8 as mentioned above.