Showing posts with label lambda. Show all posts
Showing posts with label lambda. Show all posts

Thursday, 7 December 2023

Is Stream.findFirst() Short-circuited?

So, the assumption is: if I use findFirst on a stream, none of the items in the stream after the first match are evaluated.

I assumed that it was, and it is, but it's always nice to see this verified in a simple test.

  private List<String> list = new ArrayList<>();

  private boolean add(String message, boolean returnValue) {
    list.add(message);
    return returnValue;
  }

  public boolean check() {
    List<Supplier<Boolean>> checks = new ArrayList<>();
    checks.add(super::onLeave);
    checks.add(() -> {
      list.add("First expression");
      return true;
    });
    checks.add(() -> {
      list.add("Second expression");
      return true;
    });
    checks.add(() -> {
      list.add("Third expression");
      return false;
    });
    checks.add(() -> {
      list.add("Fourth expression");
      return true;
    });
    checks.add(() -> {
      list.add("Fifth expression");
      return true;
    });
    checks.add(() -> {
      list.add("Sixth expression");
      return false;
    });
    return checks.stream()
        .filter(t -> t.get().equals(Boolean.FALSE))
        .findFirst()
        .isEmpty();
  }

  @Test
  public void testShortCircuit() {
    assertThat(check()).isFalse();
    assertThat(list)
        .containsExactly("First expression", "Second expression", "Third expression");
  }

As this test passes, it seems that way.

In the very beginning it took some time for me to wrap my head around it, but the operations you define on a stream (.map, .filter, etc.) are not all processed on every item in the stream.

All operations are processed on the first item of the stream, then on the second item of the stream. From this it follows, that a .findFirst() operation will immediately terminate operations if it finds one and the rest of the stream will be ignored.

Friday, 4 May 2018

Creating a method reference on a null reference does not throw NullPointerException

We ran into a problem that the Unit tests ran perfectly on my local machine, but the same Unit tests would break in the continuous delivery pipeline.

The problem occurred when creating a method reference. Like so:

When running the test included above, the test failed with:

java.lang.AssertionError: Expected exception: java.lang.NullPointerException

After some research we found out that the difference between the two is the Eclipse compiler used by the IntelliJ IDE vs. the openjdk installed in the continuous delivery pipeline.

We found out that it is illegal to use a method reference on a null reference. Quoting from [1]:

First, if the method reference expression begins with an ExpressionName or a Primary, this subexpression is evaluated. If the subexpression evaluates to null, a NullPointerException is raised, and the method reference expression completes abruptly.

At first glance, this is a bit weird. After all, we want to have a method reference, in order to call it at a later time, which in fact may never occur. So why not have the NullPointerException when an attempt is made to actually call the method?

IntelliJ

IntelliJ comes equipped automatically with the Eclipse Java Compiler (ECJ), and as such it takes some effort to find out which version is installed along with the IDE.

Jar file ecj-4.6.1.jar was include in directory .local/share/JetBrains/Toolbox/apps/IDEA-U/ch-1/181.4445.78/lib/ecj-4.6.1.jar.

In IntelliJ it is possible to provide the path to the ecj jar to use, see [2].

Setting the path to the newly downloaded jar file ~/Downloads/ecj-4.7.3a.jar solved my problem.

It's been a long time since I encountered a bug in the compiler3, but other people have noticed it too4 and then it gets fixed.

Note

Bear in mind that, if we did not use a method reference, but an ordinary lambda, that this problem would not have occurred (immediately).

This means that, if you replace a Lambda with a method reference you may be introducing a NullPointerException earlier in the code without realising it5.

Bear this in mind.

References

[1] JLS 8 - 15.13.3. Run-Time Evaluation of Method References
https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.13.3
[2] IntelliJ - Specifying compilation settings
https://www.jetbrains.com/help/idea/specifying-compilation-settings.html
[3] Eclipse - Bug Report
https://bugs.eclipse.org/bugs/show_bug.cgi?id=521182
[4] StackOverflow - Creating a method reference on a null reference does not throw an exception
https://stackoverflow.com/questions/37681625/creating-a-method-reference-on-a-null-reference-does-not-throw-an-exception
[5] StackOverflow - java.lang.NullPointerException is thrown using a method reference but not a lambda
https://stackoverflow.com/questions/37413106/java-lang-nullpointerexception-is-thrown-using-a-method-reference-but-not-a-lamb/37413546

Friday, 16 February 2018

Turning a Stream into an Iterable

Recently I wanted to know how to change a stream into an Iterable. The method in the API that I need to call expects an Iterable.

I found the following solution in [1]:

public class RealEstateEvaluator
{
  public void evaluate(Session session, Iterable<House> iterable)
  {
    // do stuff
  }
}

public void realEstateEvaluation()
{
  Stream<House> housenumbersStream = 
    housenumbers.stream()
      .map(realEstateService::getHouse);   

  new RealEstateEvaluator().evaluate(getSession(), housenumbersStream::iterator);
}

However, [1] did mention that the result was unreadable. It is confusing that a method reference that provides an Iterator, perhaps accidentally, fulfills the contract for Iterable2.

That's right. Iterable is an interface3, which has three methods, two of which have default implementations. Which means it has one method (iterator()), which means it can be used as a Lambda expression.

I prefer:

public void evaluate()
{
  List<House> houses = 
    housenumbers.stream()
      .map(realEstateService::getHouse)
      .collect(Collectors.toList();   

  new RealEstateEvaluator().evaluate(getSession(), houses);
}

It is a lot more readable. And I am a big believer in the Principle of Least Surprise.

All Collections are Iterables, by the way.

Update 2018-02-23: after reading and evaluating the comment below, I still think using the method reference makes it harder to read, but is much safer to use. Perhaps getting used to using stream::iterator is just a question of time.

References

[1] LambdaFAQ - How do I turn a stream into an iterable
http://www.lambdafaq.org/how-do-i-turn-a-stream-into-an-iterable/
[2] StackOverflow - Why does stream not implement iterable
https://stackoverflow.com/questions/20129762/why-does-streamt-not-implement-iterablet
[3] Oracle JavaDoc - Iterable
https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html?is-external=true

Thursday, 6 July 2017

Lambdas, New IO, and parsing textfiles in a hurry.

Okay, so I needed to do some parsing of a file containing URLs (which I "wget"-ted) and moving the retrieved files to proper locations.

I decided to write a quick Java program to do this instead of messing around with scripting languages or a Linux bash shell.

It worked very well, and I am rather pleased with the result and Java 8.

It contains the following "new/newer/not-very-old" stuff:
  • a lambda
  • a stream (of Strings)
  • a method reference (used as a lambda)
  • the java.nio.file package (New IO)
One small note: lambdas implement an interface. In this case the forEach requires a lambda that implements the Consumer interface. The Consumer interface does not specify an IOException. Therefore, I am required to catch it here and rethrow it unchecked.

References

[1] Java SE 8 - Official Javadoc
https://docs.oracle.com/javase/8/docs/api/

Thursday, 23 February 2017

A Natural Progression Towards Lambda

At my work, in order to deal with a grid1 in the frontend and a list at the backend, we use a DataModel at the backend.

It seems simple enough, and used to work as follows:
private List<Person> list = Arrays.asList(new Person("Jim"), new Person("Jack"));

private ListDataModel<Person> dataModel = new ListDataModel<>(list);
This had some shortcomings when for example the user decided to select a different department, executing this code:
list = findPersonsByDepartment(department);
This seems to work just fine. A person selects a different department, and the employees data model updates itself. Or so one would think.
What happens is that the ListDataModel retains the old list. So, the frontend is never updated.

Reusing the same list

Because of this little problem, our code retains a lot of the following statements, to make sure the same list is used over and over again:
list.clear();
list.addAll(findPersonsByDepartment(department));
It seems a slightly convoluted way to doing things.

Anonymous inner classes

We soon found out that anonymous inner classes would solve this problem better, and in fact there are more anonymous inner classes than there are named DataModels in our current code base.

It looks like the following:
private ListDataModel<Person> dataModel = new ListDataModel<Person>() 
{
   @Override
   public List<Person> getList() 
   {
     return findPersonsByDepartment(department);
   }
};
There now, any time the contents of the ListDataModel is requested in the frontend, a new and accurate List containing the department employees is returned.

Passing code

Instead of creating an entire new anonymous inner subclass of a ListDataModel, it might be more elegant to create an interface especially for this purpose, call it the ListProvider interface.

As follows:
public interface ListProvider<T> 
{
  List<T> getList();
}

private ListDataModel<Person> dataModel = new ListDataModel<Person>(new ListProvider<>() 
{
   @Override
   public List<Person> getList() 
   {
     return findPersonsByDepartment(department);
   }
});

Using lambdas


The good part is that now with Java 8 we can start using Lambdas.

And in this case, we have an interface containing just one method. This is in essence the definition of a lambda.

So now the proper way to write this would be the following:
public interface ListProvider<T> 
{
  List<T> getList();
}

private ListDataModel<Person> dataModel = 
    new ListDataModel<Person>(() -> findPersonsByDepartment(department));
Convenient, isn't it?
In this case, the lambda is called a Supplier2 .

References

[1] Welcome to the SlickGrid! (outdated sadly)
https://github.com/mleibman/SlickGrid/wiki
[2] Supplier (Java Platform SE 8)
https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html

Saturday, 29 October 2016

The Martingale using Lambdas

I created a small blog post some time ago regarding the Martingale System of Gambling.

In it, a programming example is available, which could be rewritten using the Lambda style in Java 8.

I am going to attempt doing just that and post my results below.

ForEach

When I was following the MOOC course of Oracle1, Simon Ritter quite emphatically mentioned trying not to use the foreach method when not required.

But let us try it now, as a seemingly perfectly reasonable first step on a slippery slope to hell.

What we need is a stream of random numbers, and then run the foreach on it.
So far, so good.

Still doesn't look very much better, and perhaps even a little bit worse.

Mapping

Let's try to make it better.

For this we are going to use an "Account" class. Like this:

This class will be used in the Lambda, like so:

Conclusion

Lambdas can make your code look a lot cleaner. However, they can never replace all the loops in your code, as witnessed in the example above.

I'd really like to use collect or reduce instead of the forEach in the example, but I don't think I can.

But if anyone has any suggestions on how to fix it, please tell me.

For the source code to the "Bet" class, check out https://gist.github.com/maartenl/a804f4ac435f491b57c7ae810d5fd577.

Peek and Debugging

Peek is very valuable if you wish to do some debugging of your new Lambdas.

Using the following:
new Random()
           .ints(0, 37)
           .peek(System.out::println)
           .mapToObj(x -> Bet.getBet(x))
           .peek(System.out::println)
           .forEach(x
                   ->
                   {
                     if (x == Bet.RED)
                     {
                       account.add();
                     } else
                     {
                       account.subtract();
                     }
           });

You get some nice output to see what's happening:
10
BLACK
29
BLACK
11
BLACK
19
RED
26
BLACK
34
RED
34
RED

References

[1] Oracle - Announcing: JDK 8 MOOC: Lambdas and Streams!
https://blogs.oracle.com/javatraining/entry/announcing_jdk_8_mooc_lambdas
[2] The Java™ Tutorials > Collections > Aggregate Operations - Reduction
https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html
Wikipedia - Roulette
https://en.wikipedia.org/wiki/Roulette

Thursday, 11 February 2016

My First Lambda

I just implemented my first lambda1. My java code is now officially only Java 8 and up compliant.

My pom was changed as follows:
<project.source.version>1.8</project.source.version>
<project.target.version>1.8</project.target.version>

Original code

The original code looked like this:
Pretty straight forward stuff.

Adding a Lambda

Then we received two change requests, that could be resolved by re-using the method above.

But this time, not everyone was required to see the message. In other words, the list of active players needed to be filtered.

Enter the Predicate2.

Let us say the filtering needs to be done, by those who wish to be kept in the loop regarding roleplaying events. These users contain an Ooc (Out-of-Character) flag.

Calling this can be done using a Lambda, like so:
sendWall("[OOC: " + aUser.getName() + "] " + message + "\r\n", p -> p.getOoc());

Streams

To make things a little more complicated, you can make use of the new Streams3 4 provided in Java 8.

In the example below, I take a stream from the List collection provided by getActivePlayers, filter it by the predicate, and run the writeMessage on each found user. That last one is called a "terminator" as it terminates the stream, i.e. it "does something".

A lot less code than the previous for loop. It seems more complicated, but I guess it just requires me to get used to it.

It also causes me to create another Lambda, as the terminator.

The Old Way

In the old way, calling this method sendWall was done using an inner class, and it looked as follows:

References

[1] JavaTM Tutorials - Lambda Expressions
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
[2] JavaDoc - Interface Predicate<T>
https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html
[3] JavaTM Tutorials - The Collection Interface
https://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html
[4] Processing Data with Java SE 8 Streams, Part 1
http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html


Wednesday, 23 April 2014

NetBeans 8.0 - Upgrading My Source Code

I have heard that in NetBeans 8.0, which has full support for the new Java 81, you can have your source code transformed to make use of the latest and greatest Java 8 has to offer.

Naturally, I wish to test this. I've chosen my YPPO project for it.

Progress


It seems easy enough. Just select Source in the main menu and choose Inspect2.

It transpired that I require FindBugs to use All Analyzers, but NetBeans automatically asked if I wanted to install it.

A lot of the inspection messages are regarding missing JavaDoc. I'm going to skip over those (as being not interesting).

Functional Operations

Use functional operations instead of imperative style loop.
public static void addErrorMessages(List<String> messages)
{
    for (String message : messages)
    {
        addErrorMessage(message);
    }
}
Got turned into:
public static void addErrorMessages(List<String> messages)
{
    messages.stream().forEach((message) ->
    {
        addErrorMessage(message);
    });
}

private void persistGalleries(Map<String, Gallery> galleries)
{
    for (String path : galleries.keySet())
    {
        Gallery gallery = galleries.get(path);
        logger.log(Level.FINE, "persistGalleries persist gallery {0}.", gallery);
        galleryBean.create(gallery);//em.persist(gallery);
    }
}
Got turned into:
private void persistGalleries(Map<String, Gallery> galleries)
{
    galleries.keySet().stream().map((path) -> galleries.get(path)).map((gallery) ->
    {
        logger.log(Level.FINE, "persistGalleries persist gallery {0}.", gallery);
        return gallery;
    }).forEach((gallery) ->
    {
        galleryBean.create(gallery);
    });
}

Lambda Expressions

Anonymous inner class creation can be turned into a lambda expression.
Collections.sort(list, new Comparator<Gallery>()
{
    @Override
    public int compare(Gallery t, Gallery t1)
    {
        return t.getCreationDate().compareTo(t1.getCreationDate());
    }
});
Got turned into:
Collections.sort(list, (Gallery t, Gallery t1) -> t.getCreationDate().compareTo(t1.getCreationDate()));

Notes


Despite NetBeans telling me that everything is perfectly fine, actually deploying it to GlassFish using the new Streams throws an ArrayIndexOutOfBoundsException. See [3].

I'm sure they're already hard at work.

References

[1] Overview of JDK 8 Support in NetBeans IDE
https://netbeans.org/kb/docs/java/javase-jdk8.html
[2] 7.11.21 Using Hints in Source Code Analysis and Refactoring
http://docs.oracle.com/cd/E40938_01/doc.74/e40142/build_japps.htm#NBDAG613
[3] Collection streams provoke java.lang.ArrayIndexOutOfBoundsException
https://java.net/jira/browse/GLASSFISH-21014

Friday, 15 March 2013

Natural Progression of Java for Statement

Introduction


I find it fascinating the way Java is being developed, and accrues different new features from other "newer" programming languages.

One of the things that struck me forcefully recently, is the progression of our beloved for Statement. So forcefully, that I had to make a blog about it.

Output of the programs listed below is always:
James Gosling is 57 years old.
Charles Babbage is 221 years old.
Alan Turing is 100 years old.
Donald Knuth is 75 years old.
Edsger Dijkstra is 82 years old.
Anyone interested in the Person.java class used, can find it here.

Version 1

This is the way we did it back in the old days. A counter for 0 until we reached the size of the list we wanted to iterate over. And every time we had to cast what we got out of the list, as the list contained Objects.

Version 2

Finally! A Collections framework! With default naming, so we could always more or less assume what the exact Contract was that the Collection adhered to, once we knew the name of the Collection used.

Version 2.5

Yay! No more casting, no more 'counters' and we can add a variable number of arguments to some of our collection framework methods.

Version 7

Small change, due to project Coin. We have a simpler notation for Generics.

Version 8

Lambdas, here we come!

Conclusion

The for-loop, while still a very important tool in the arsenal of the Developer, seems to have been relegated to the internals of the Frameworks. I would not be surprised if the for-loop will become used less and less.

Small note

Whilst trying to get Lambda functions to work, I made the mistake to download the OpenJDK snapshot from Oracle that does not actually contain Lambda syntax yet. Try [1].

References

The for Statement
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
Maurice Naftalin's Lambda FAQ
http://www.lambdafaq.org/
JDK 8 Features
http://openjdk.java.net/projects/jdk8/features
Java 8: The First Taste of Lambdas
http://zeroturnaround.com/labs/java-8-the-first-taste-of-lambdas/
[1] Java™ Platform, Standard Edition 8 Early Access with Lambda Support
http://jdk8.java.net/lambda/
Java Version History
http://tech-my-talk.blogspot.in/2013/03/java-version-history.html