Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
CBStreams => AccelerateYour Functional Programming!
WHO AM I?
• Luis Majano
• Computer Engineer
• Born in El Salvador ->Texas
• CEO of Ortus Solutions
• Sandals -> ESRI -> Or...
What are Java Streams
What is CBStreams
Imperative vs Functional Programming
Building Streams
Using Streams
Collecting Str...
What are Java Streams
• Introduced in JDK 8+
• Not I/O Streams
• A data abstraction layer
• Does not store any data, it wr...
What is CBStreams
• Port of Java 8+ Streams to CFML Land!
• 90% of all Java functionality is there
• Plus some CFML Dynami...
Imperative
VS
Functional
Programming
Imperative Programming
• Major OO languages are imperative (C,++,C#, Java)
• Follow a top-down or procedural design to rea...
Functional Programming
• Declarative programming
• We tell the computer what things, actions, etc are
• Runtime determines...
Comparing Styles
Why?
Streams Functional Heaven!
• All about functional programming
• Heavy Lambda/Closure usage
• Must focus on the what and no...
Streams Functional Heaven!
var errors = [];
    var errorCount = 0;
    var oFile = fileOpen( filename );
    var thisLine...
What about CFML Functions?
• They are limited in input, scope & operations
• No short-circuiting operations
• No lazyness,...
Element Stream
Stream Processing Pipeline
Lazy!
Stream Lazyness!
Lazy Example
var empIds = [ 1, 2, 3, 4 ];
var employee = streamBuilder.new( empIds )
// Convert ID's to Employee Objects, ...
Let’s Get Started!
install cbstreams
StreamBuilder@cbstreams
• The StreamBuilder is injected where needed
• Helps you buil...
Empty Streams
emptyStream = streamBuilder.new();
emptyStream = streamBuilder.new().empty();
• Simple way to build streams ...
Building Custom Streams
builder = streamBuilder.builder();
myData.each( function( item ){
    builder.add( item );
} );
my...
Streams of Characters
stream = streamBuilder.new().ofChars( "Welcome to Streams" );
• Stream of string characters
• Great ...
File Streams
stream = streamBuilder.new().ofFile( absolutePath );
try{
    //work on the stream
} finally{
    stream.clos...
Generate Infinite Streams
// Generate 100 random numbers
stream = streamBuilder.new().generate( function(){
return randRang...
Ranged Streams
stream = streamBuilder.new().range( 1, 200 );
stream = streamBuilder.new().rangeClosed( 1, 2030 );
• Create...
Intermediate Operations
• Remember, they are lazy, nothing gets done until a terminator is called.
• Result is always a st...
Terminal Operations
• They kick off processing of elements sequentially or in parallel
Operation Description
iterator() Re...
Short-Circuit Operations
• Also terminal, but can short-circuit processing of the stream
Operation Description
findAny() F...
Collectors
• Finalizes the stream by converting it to concrete collections
• CBStreams auto-converts Java -> CFML DataType...
Lambda/Closure References
• CBStreams converts CFML Closures -> Java Lambdas
• Let’s investigate them by Java name:
// BiF...
CBStreams Optionals
• Most return values are not the actual values but a CFML Optional
• Wraps a Java Optional
• Simple fu...
Examples
myArray = [
    "ddd2",
    "aaa2",
    "bbb1",
    "aaa1",
    "bbb3",
    "ccc",
    "bbb2",
    "ddd1"
];
// F...
Examples
// Sorted Stream
streamBuilder.new( myArray )
    .sorted()
    .filter( function( item ){
        return item.st...
Examples
// Mapping
streamBuilder.new( myArray )
    .map( function( item ){
        return item.ucase();
    })
    .sort...
Examples
// Partition stream to a struct of arrays according to even/odd
var isEven = streamBuilder.new( 2,4,5,6,8 )
.coll...
Examples
// Group employees into character groups
component{
var groupByAlphabet = streamBuilder.of( employeeArray )
.coll...
Examples
// Matching
anyStartsWithA =
    streamBuilder
        .new( myArray )
        .anyMatch( function( item ){
     ...
Examples
noneStartsWithZ =
    streamBuilder
        .new( myArray )
        .noneMatch((s) -> s.startsWith("z"));
noneSta...
Examples
// Reduce
optional =
    streamBuilder
        .new( myArray )
        .sorted()
        .reduce( function( s1, s...
Examples
// Parallel Sorted Count
count =
    streamBuilder
        .new( myArray )
        .parallel()
        .sorted()
...
Still in infancy
Implement JDK 9-10 features
CFML Query Support
ORM Integration
ColdBox Core
Reactive Streams
Help me: 

L...
QUESTIONS?
Go Build Some Streams!!
www.ortussolutions.com
@ortussolutions
ITB2019 CBStreams : Accelerate your Functional Programming with the power of Java Streams - Luis Majano
Upcoming SlideShare
Loading in …5
×

ITB2019 CBStreams : Accelerate your Functional Programming with the power of Java Streams - Luis Majano

53 views

Published on

This session will introduce the cbStreams module. It will discuss what Java streams are, each of the available methods and options, and how to implement cbStreams into their applications. With real-world examples of stream implementation, this session will also show how using streams can enhance the performance of your application and reduce latency. Target Audience: Anyone wishing to learn about Java streams.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

ITB2019 CBStreams : Accelerate your Functional Programming with the power of Java Streams - Luis Majano

  1. 1. CBStreams => AccelerateYour Functional Programming!
  2. 2. WHO AM I? • Luis Majano • Computer Engineer • Born in El Salvador ->Texas • CEO of Ortus Solutions • Sandals -> ESRI -> Ortus @lmajano @ortussolutions
  3. 3. What are Java Streams What is CBStreams Imperative vs Functional Programming Building Streams Using Streams Collecting Streams
  4. 4. What are Java Streams • Introduced in JDK 8+ • Not I/O Streams • A data abstraction layer • Does not store any data, it wraps the data • Designed to process streams of data elements • map(), reduce(), filter(), collect() • Enables functional-style operations on such elements https://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html
  5. 5. What is CBStreams • Port of Java 8+ Streams to CFML Land! • 90% of all Java functionality is there • Plus some CFML Dynamic Goodness • Box Module (ColdBox, CommandBox, etc) https://forgebox.io/view/cbstreams install cbstreams
  6. 6. Imperative VS Functional Programming
  7. 7. Imperative Programming • Major OO languages are imperative (C,++,C#, Java) • Follow a top-down or procedural design to reach a goal • Each statement changes the state (side-effect) of the program • Each statement tells the computer what to change and in what order • Always cons and pros function isPrime( number ) { for( var i = 2; i <= sqr( number ); i++) { if(number % i == 0) return false; } return number > 1; } isPrime(9220000000000000039) // Output: true
  8. 8. Functional Programming • Declarative programming • We tell the computer what things, actions, etc are • Runtime determines the best way how to do it • Functions are first class citizens • No side-effect or iterating state to worry about • Always cons and pros function isPrime(number) { return number > 1 && stream .rangeClosed( 2, sqr( number ) ) .noneMatch( index => number % index == 0 ); } isPrime( 9220000000000000039 ) // Output: true
  9. 9. Comparing Styles
  10. 10. Why?
  11. 11. Streams Functional Heaven! • All about functional programming • Heavy Lambda/Closure usage • Must focus on the what and not on the how! • Create a data processing pipeline • Not for everything, choose wisely…. You have been warned!
  12. 12. Streams Functional Heaven! var errors = [];     var errorCount = 0;     var oFile = fileOpen( filename );     var thisLine = fileReadLine( oFile );     while( errorCount < 40 && !isNull( thisLine ) ){         if( line.startsWith( "ERROR" ) ){             errors.append( line );             errorCount++;         }         line = fileReadLine( oFile );     } var errors = streamBuilder.ofFile( filePath )         .filter( line => line.startsWith( "ERROR" ) )         .limit( 40 )         .collect(); What if I want to multi- thread this? .parallel()
  13. 13. What about CFML Functions? • They are limited in input, scope & operations • No short-circuiting operations • No lazyness, they all fire top-down • Each operation blocks until it finishes processing ALL elements • Creates new arrays/queries/structs for each new concatenated operation • What about infinite input or biiiiig files? • map(), reduce(), each(), filter()
  14. 14. Element Stream
  15. 15. Stream Processing Pipeline
  16. 16. Lazy!
  17. 17. Stream Lazyness!
  18. 18. Lazy Example var empIds = [ 1, 2, 3, 4 ]; var employee = streamBuilder.new( empIds ) // Convert ID's to Employee Objects, passing function reference .map( employeeService.findByID ) // only valid employees .filter( (employee) => !isNull( employee ) ) .filter( function( employee ){ return !isNull (employee); } ) // only salaries > 10000 .filter( (employee) => employee.getSalary() > 100000 ) // Find the first one .findFirst() // Return null .orElse( null ); expect( employee.getSalary() ).toBe( 200000 ); • Stream performs the map and two filter operations, one element at a time. • Since the salary of id 1 is not greater than 100000, the processing moves on to the next element. • Id 2 satisfies both of the filter predicates and hence the stream evaluates the terminal operation findFirst() and returns the result. • No operations are performed on id 3 and 4.
  19. 19. Let’s Get Started! install cbstreams StreamBuilder@cbstreams • The StreamBuilder is injected where needed • Helps you build streams out of native CFML data types • Strings, Files, Arrays, Structs, Queries, Nulls • Helps you build infinite or closure based streams • You can strong type elements for the stream if needed • For mathematical operations • int, long, or double
  20. 20. Empty Streams emptyStream = streamBuilder.new(); emptyStream = streamBuilder.new().empty(); • Simple way to build streams with no elements • Useful? Maybe…
  21. 21. Building Custom Streams builder = streamBuilder.builder(); myData.each( function( item ){     builder.add( item ); } ); myStream = builder.build(); stream = streamBuilder.new()
 .of( "a", "hello", "stream" ); stream = streamBuilder.new()
 .of( argumentCollection=myData ); • Two approaches: • builder() - Add your own data via the add() method • Of( arguments ) -Via an array of arguments
  22. 22. Streams of Characters stream = streamBuilder.new().ofChars( "Welcome to Streams" ); • Stream of string characters • Great for parsing, lookups, etc.
  23. 23. File Streams stream = streamBuilder.new().ofFile( absolutePath ); try{     //work on the stream } finally{     stream.close(); } • Non Blocking I/O Classes • Stream of file lines • Throw any file size to it, I dare ya!
  24. 24. Generate Infinite Streams // Generate 100 random numbers stream = streamBuilder.new().generate( function(){ return randRange( 1, 100 ); } ).limit( 100 ); // Seeded iteration stream = streamBuilder.new().iterate( 40, function( x ){ return x + 2; } ).limit( 20 ); • Infinite streams of data • Start with a seed or no seeded results • Make sure you limit them or wait forever….
  25. 25. Ranged Streams stream = streamBuilder.new().range( 1, 200 ); stream = streamBuilder.new().rangeClosed( 1, 2030 ); • Create open or closed ranges • Similar to of() but a whole less typing
  26. 26. Intermediate Operations • Remember, they are lazy, nothing gets done until a terminator is called. • Result is always a stream Operation Description limit( maxSize ) Limit the stream processing distinct() Return only distinct elements skip( n ) Skip from the first element to n sorted( comparator ) Sort a stream using a compactor closure unordered() Return an unordered stream (default) onClose( closeHandler ) Attach a listener to when the close operation is called concat( stream1, stream2 ) Concatenates two streams together peek( action ) Allows you to peek on the element in the order is called Map( mapper ) Transform the elements into something else filter( predicate ) Returns a new stream containing only the requested elements parallel() Convert the stream to a parallel multi-threaded stream
  27. 27. Terminal Operations • They kick off processing of elements sequentially or in parallel Operation Description iterator() Returns a java iterator spliterator() Returns a java spliterator close() Close the stream toArray() Convert the stream back into an array count() Count the elements in the stream forEach( action ) Iterate through the elements calling the action closure forEachOrdered( action ) Iterate through the elements calling the action closure in order, even in parallel reduce( accumulator, identity ) Fold, reduces the stream to a single element. max( comparator ) Returns the max value in the stream, if a comparator is passed its called for you min( comparator ) Returns the min value in the stream, if a comparator is passed its called for you average( comparator ) Returns the avg value in the stream, if a comparator is passed its called for you summaryStatistics() Gives you a struct of stats containing: { min, max, count, sum, average }
  28. 28. Short-Circuit Operations • Also terminal, but can short-circuit processing of the stream Operation Description findAny() Find any element in the stream findFirst() Find the first element in the stream anyMatch( predicate ) Returns a boolean that indicates if any of the elements match the predicate closure allMatch( predicate ) Returns a boolean that indicates if ALL of the elements match the predicate closure noneMatch( predicate ) Returns a boolean that indicates if none of the elements match the predicate closure
  29. 29. Collectors • Finalizes the stream by converting it to concrete collections • CBStreams auto-converts Java -> CFML DataTypes Operation Description collect() Return an array of the final elements collectGroupingBy( classifier ) Build a final collection according to the classifier lambda/closure that will classify the keys in the group. End result is usually a struct of data collectAverage( mapper, primitive=long ) Collect an average according to the mapper function/closure and data type passed collectSum( mapper, primitive=long ) Collect a sum according to the mapper function/closure and data type passed collectSummary( mapper, primitive=long ) Collect a statistics struct according to the mapper function and data type passed collectAsList( delimiter=“,”, prefix, suffix ) Collect results into a string list with a delimiter and attached prefix and/or suffix. collectAsStruct( keyId, valueID, overwrite=true ) Collect the elements into a struct by leveraging the key identifier and the value identifier from the stream of elements to pass into the collection. collectPartitioningBy( predicate ) partitions the input elements according to a Predicate closure/lambda, and organizes them into a Struct of <Boolean, array >.
  30. 30. Lambda/Closure References • CBStreams converts CFML Closures -> Java Lambdas • Let’s investigate them by Java name: // BiFunction, BinaryOperator function( previous, item ){ return item; } // Comparator function compare( o1, o2 ){ return -,+ or 0 for equal } // Consumer void function( item ){ } // Function, ToDoubleFunction, ToIntFunction, ToLongFunction, UnaryOperator function( item ){ return something; } // Predicate boolean function( item ){ return false; } // Supplier function(){ return something; } // Runnable void function(){ // execute something }
  31. 31. CBStreams Optionals • Most return values are not the actual values but a CFML Optional • Wraps a Java Optional • Simple functional value container instead of doing null checks, with some cool functions Operation Description isPresent() Returns boolean if value is present ifPresent( consumer ) If value is present call the consumer closure for you filter( predicate ) If a value is present and the value matches the predicate then return another Optional :) map( mapper ) If a value is present, apply the mapping function and return another Optional get() Get the value! orElse( other ) Get the value or the `other` if the value is null orElseGet( other ) Get the value or if not present call the other closure to return a value hashCode() Unique hash code of the value toString() Debugging
  32. 32. Examples myArray = [     "ddd2",     "aaa2",     "bbb1",     "aaa1",     "bbb3",     "ccc",     "bbb2",     "ddd1" ]; // Filtering streamBuilder.new( myArray )     .filter( function( item ){         return item.startsWith( "a" );     } )     .forEach( function( item ){         writedump( item );     } );
  33. 33. Examples // Sorted Stream streamBuilder.new( myArray )     .sorted()     .filter( function( item ){         return item.startsWith( "a" );     } )     .forEach( function( item ){         writedump( item );     } );
  34. 34. Examples // Mapping streamBuilder.new( myArray )     .map( function( item ){         return item.ucase();     })     .sorted( function( a, b ){         return a.compareNoCase( b );     }     .forEach( function( item ){         writedump( item );     } );
  35. 35. Examples // Partition stream to a struct of arrays according to even/odd var isEven = streamBuilder.new( 2,4,5,6,8 ) .collectPartitioningBy( function(i){ return i % 2 == 0; } ); expect( isEven[ "true" ].size() ).toBe( 4 ); expect( isEven[ "false" ].size() ).toBe( 1 );
  36. 36. Examples // Group employees into character groups component{ var groupByAlphabet = streamBuilder.of( employeeArray ) .collectGroupingBy( function( employee ){ return listFirst( employee.getlastName(), “” ); } ); expect( groupByAlphabet.get( 'B' ).get( 0 ).getName() ) .toBe( "Bill Gates" ); expect( groupByAlphabet.get( 'J' ).get( 0 ).getName() ) .toBe( "Jeff Bezos" ); expect( groupByAlphabet.get( 'M' ).get( 0 ).getName() ) .toBe( "Mark Zuckerberg" ); }
  37. 37. Examples // Matching anyStartsWithA =     streamBuilder         .new( myArray )         .anyMatch( function( item ){             return item.startsWith( "a" );         } ); writeDump( anyStartsWithA ); // true allStartsWithA =     streamBuilder         .new( myArray )         .allMatch( function( item ){             return item.startsWith( "a" );         } ); writeDump( anyStartsWithA ); // false
  38. 38. Examples noneStartsWithZ =     streamBuilder         .new( myArray )         .noneMatch((s) -> s.startsWith("z")); noneStartsWithZ =     streamBuilder         .new( myArray )         .noneMatch( function( item ){             return item.startsWith( "z" );         } ); writeDump( noneStartsWithZ ); // true
  39. 39. Examples // Reduce optional =     streamBuilder         .new( myArray )         .sorted()         .reduce( function( s1, s2 ){             return s1 & "#" & s2;         } ); writedump( optional.get() );
  40. 40. Examples // Parallel Sorted Count count =     streamBuilder         .new( myArray )         .parallel()         .sorted()         .count();
  41. 41. Still in infancy Implement JDK 9-10 features CFML Query Support ORM Integration ColdBox Core Reactive Streams Help me: 
 Lucee/Adobe Lambda -> Java lambda Roadmap
  42. 42. QUESTIONS? Go Build Some Streams!! www.ortussolutions.com @ortussolutions

×