top of page

Using Lambdas and Streams in Java and AnyLogic to neaten and improve your code.

Updated: Mar 22, 2023

This is a special guest blog post by intern Devon Cowling. After some great feedback from readers on his previous blog posts on smart traffic lights and dynamically adding presentations, we decided to invite him to make a post about some advanced Java coding features.


This post was made possible by the support of our Patrons. To become a member, click here

 

If you're like me, after a few months of learning to code and writing Java code you start to become OCD about the neatness and length of the code. Scratching your head for a better technique to implement methods once they start to become bloated and messy. Anyone who has dealt with multiple nested For loops will vouch for this.


Imperative vs Declarative programming


This messy way of coding isn't all our fault, it is the traditional technique that coders have used for a long time. This is called Imperative programming. But there is a better way.


If you know what Imperative and Declarative programming is you can skip to the next section otherwise, here is a crash course.


Imperative programming is the oldest and most basic programming approach. Within the imperative paradigm, code describes a step-by-step process for a program’s execution. Because of this, beginners often find it easier to reason with imperative code by following along with the steps in the process.

The step-by-step process contains individual statements, instructions, or function calls. In the programming world, this process is called the control flow.

In other words, you’re interested in how the program runs, and you give it explicit instructions.


Declarative programming describes what you want the program to achieve rather than how it should run. In other words, within the declarative paradigm, you define the results you want a program to accomplish without describing its control flow. Ultimately, it’s up to the programming language’s implementation and the compiler to determine how to achieve the results. This places emphasis not on the execution process but on the results and their ties to your overall goal. In other words, writing declarative code forces you to ask first what you want out of your program. Defining this helps you develop more expressive and explicit code.



The introduction of Java 8 in 2014 brought with it two new features that allowed programmers to write declarative code. These two features are Lambdas and Streams.


By using these features together, you can neaten and shorten your code to help you become a better programmer/simulator.


Lambdas


Java Lambda Expressions are the foundation of functional programming in Java.

Since Java version 8, Lambda expressions have reduced the code length and code complexity to a greater extent.

Lambda Expressions are particular code segments that behave like a regular method, except they don't belong to any class and can be passed around as if it was an object and executed on demand.

They are designed to accept a set of parameters as input and return a value as an output.

Unlike methods, a Lambda Expression does not mandatorily require a specific name.


A typical function has 4 requirements:

  1. Name

  2. Parameter List

  3. Body

  4. Return type

Note: The term functions is only used in AnyLogic - in Java it is called methods


A lambda simplifies this and only needs 2 of those requirements: A parameter list, and a body.

Below is an example of using a Lambda expression to make the code neater and Declarative.

traceln(findAll(people, a -> a.Age < 50).size());

*instead of*

int counter = 0;
for (People p:people){
    if (p.Age < 50) counter++;
}
traceln(counter);

Neat, isn't it?


Now with regards to Imperative and Declarative programming and trying to achieve the latter, the lambda expression is simply a stepping stone to the next and arguably more critical feature, Streams.


Streams


The stream feature affords a functional programming style and is the real power of Java 8. A stream is essentially a very powerful iterator. The process acts as a pipeline from source through intermediate operations and a terminal operation to a result. The term pipeline is used as data enters and exits but nothing in the middle/intermediate stages is saved.

The source may come from collections, lists, sets, arrays, and agent populations to name a few. This source data is also never modified, so if data is filtered, then a new stream is created that only consists of the filtered data.


The beauty of a stream is that the JVM (Java Virtual Machine) will do most of the work for you in the background. You give it the source data and ask it to complete operations on the data, but the way those operations execute is up to the JVM and stream feature. As in the example below.


This example is trying to add people from the population People to an ArrayList called collection. The forEach() function seen below is one of many tools that can be used with streams.

people.stream().forEach(p -> collection.add(p));	

*instead of*

for (int i = 0; i < people.size(); i++){
	collection.add(people(i));
}	

As you can see, you don't have to specify how and how long the iteration will occur. This is taken care of for you in the background. Leaving you more time to focus on the big picture and less on the small details. This is the goal of Declarative programming and the benefit of using streams!


You can download the example model from the AnyLogic cloud here, or the link below.


StreamsAndLambdasExample
.zip
Download ZIP • 4KB

If you would like a more in-depth explanation and examples of Streams and Lambdas, watch out for The AnyLogic Modelers Udemy Course on Advanced Java for AnyLogic coming out soon.


Devon Cowling


 

Devon Cowling is a guest writer for the AnyLogic Modeler. Feel free to connect with him over LinkedIn.


What next?

If you liked this post, you are welcome to read more posts by following the links above to similar posts. Why not subscribe to our blog or follow us on any of the social media accounts for future updates? The links are in the Menu bar at the top, or the footer at the bottom. You can also join the mobile app here!


If you really want to make a difference in supporting us please consider joining our Patreon community here


If you want to contact us for some advice, maybe a potential partnership or project or just to say "Hi!", feel free to get in touch here, and we will get back to you soon!








467 views1 comment
Post: Blog2_Post
bottom of page