DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Java
  4. Infinite Streams in Java 8 and 9

Infinite Streams in Java 8 and 9

Time to put on your functional programming hats. See how Java 8 and 9 handle implementing infinite streams and check out the tools at your disposal.

Thomas Much user avatar by
Thomas Much
·
Feb. 26, 18 · Tutorial
Like (18)
Save
Tweet
Share
21.68K Views

Join the DZone community and get the full member experience.

Join For Free

With the advent of lambdas and streams in Java 8, it's finally possible to write Java algorithms in a more functional style. An important element of functional programming is generated (or "infinite") streams that are cut by suitable conditions (of course, these streams aren't really infinite, but they are computed "lazily", i.e. on demand). Infinite streams do exist in Java, too, as we'll see in the following examples.

We're implementing the Luhn algorithm to calculate a simple checksum. I took the idea of using this example from the talk "JVM Functional Language Battle" by Falk Sippach. A short summary of the Luhn algorithm:

  • Given a non-negative, integer number of arbitrary length.
  • From right to left, double every second digit. If the resulting number has two digits, take the square sum (so we have one digit again).
  • Sum up all the resulting digits.
  • If the sum modulo 10 is zero, the original number is valid according to the Luhn algorithm.

How do we implement this algorithm with Java 8 streams? Without variables, state change or conditional branching? Like this, for the example:

import java.util.PrimitiveIterator;
import java.util.stream.IntStream;

public class Luhn {

  public static boolean isValid(String number) {

    PrimitiveIterator.OfInt factor =
      IntStream.iterate(1, i -> 3 - i).iterator();

    int sum = new StringBuilder(number).reverse()
      .toString().chars()
      .map(c -> c - '0')
      .map(i -> i * factor.nextInt())
      .reduce(0, (a, b) -> a + b / 10 + b % 10);

    return (sum % 10) == 0;
  }
}


Let's run isValid()with parameter string "8763".

IntStream.iterate() generates an endless (but lazily calculated) stream of numbers 1,2,1,2,1,2, ... – this is the factor we'll multiply each digit with.

Now, we wrap the parameter string in a StringBuilder since this class offers a reverse() method. This way we can walk through the chars() stream of digits forward:

'3', '6', '7', '8'

The firstmap() converts each digit char to its number value. The second map() multiplies this number value with the next factor value from the infinite IntStream (i.e. here, each second digit is doubled):

3, 12, 7, 16

reduce() calculates the square sum for all of these numbers (even for the ones with only one digit). We add the tens-digit (div 10) and the ones-digit (mod 10):

(0 + 3) + (1 + 2) + (0 + 7) + (1 + 6)

That gives 20, which is divisible by 10 without a remainder. So the checksum is valid!

Meanwhile, Java 9 introduced takeWhile(). We can use this stream operation to get rid of the StringBuilder and the reversing of the characters. Instead, we create a second infinite stream from the number parameter and cut the stream with a suitable lambda predicate:

import java.util.PrimitiveIterator;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class Luhn9 {

  public static boolean isValid(long number) {

    PrimitiveIterator.OfInt factor =
      IntStream.iterate(1, i -> 3 - i).iterator();

    long sum = LongStream.iterate(number, n -> n / 10)
      .takeWhile(n -> n > 0)
      .map(n -> n % 10)
      .map(i -> i * factor.nextInt())
      .reduce(0, (a, b) -> a + b / 10 + b % 10);

    return (sum % 10) == 0;
  }
} 


The chars() stream from the previous Java 8 example stopped after the last character of the parameter string. In this Java 9 example, LongStream.iterate() divides the parameter by 10 endlessly, e.g.

8763, 876, 87, 8, 0, 0, 0, ...

We have to consider the stream's values only as long as they are greater than zero. takeWhile() does exactly this and yields the following finite stream:

8763, 876, 87, 8

Now we map() this stream to a stream of its rightmost digits (mod 10):

3, 6, 7, 8

The final operations (doubling of each second digit and adding the square sums) are the same as in the Java 8 example.

This implementation in Java might not be perfect functional style because we are limited to the existing Stream API and we cannot use composition of arbitrary functions (at least unless we're using additional libraries like Vavr). But hey, using only standard API, these examples show quite a different and more expressive Java already than we used to know!

[This text is also available in German on my personal blog.]

Stream (computing) Java (programming language)

Published at DZone with permission of Thomas Much. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • 5 Software Developer Competencies: How To Recognize a Good Programmer
  • File Uploads for the Web (2): Upload Files With JavaScript
  • Use AWS Controllers for Kubernetes To Deploy a Serverless Data Processing Solution With SQS, Lambda, and DynamoDB
  • How Chat GPT-3 Changed the Life of Young DevOps Engineers

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: