Lazy computations, which are evaluated as much as possible, are characteristic of many functional programming languages. Lazy collections provide their elements when they are needed without having to compute them in advance, which brings some benefits. First, you can defer the time-consuming calculation to the point of absolute need. Second, you can create unlimited collections that continue to provide elements as long as they continue to receive requests. Third, the lazy use of functions such as map and filter allow you to get more efficient code. Java does not provide native support for laziness, but some frameworks and successor languages support this inertia, and I'll explore them in this and next installment.
Suppose you use this pseudo code fragment to print the length of the list:
Print length ([2+1, 3*2, 1/0, 5-4])
If you try to execute this code, the result will vary depending on the type of programming language of your code: strict or not strict (also known as inertia). In a strict programming language, executing (or compiling) This code produces a Divbyzero exception because of the third element of the list. In a less restrictive language, the result is 4, which accurately reports the number of items in the list. After all, the method I call is length (), not Lengthandthrowexceptionwhendivbyzero ()! Haskell is one of the few less stringent languages that are still in use. Unfortunately, Java does not support less rigorous computing, but you can still use the concept of inertia in Java.
Lazy iterators in Java
Java lacks native support for lazy collections, but that does not mean that you cannot use iterator to simulate a lazy collection. In the previous articles in this series, I used a simple prime number algorithm to illustrate functional concepts. I'll start the discussion in this article on the basis of the optimization classes described in the previous article, along with the enhancements shown in Listing 1:
Listing 1. A simple algorithm for determining prime numbers
Import Java.util.HashSet;
Import Java.util.Set;
Import static java.lang.Math.sqrt; public class Prime {public static Boolean isfactor (int potential, int number) {return number% Potentia
L = = 0; public static set<integer> getfactors (int number) {set<integer> factors = new Hashset<i
Nteger> ();
Factors.add (1);
Factors.add (number);
for (int i = 2; i < sqrt (number) + 1; i++) if (Isfactor (i, number)) {Factors.add (i);
Factors.add (number/i);
return factors;
public static int sumfactors (int number) {int sum = 0;
for (int i:getfactors (number)) sum = i;
return sum;
public static Boolean isprime (int number) {return number = = 2 | | sumfactors (number) = number + 1;
public static Integer nextprimefrom (int lastprime) {lastprime++; WhIle (! IsPrime (lastprime)) lastprime++;
return lastprime; }
}
The previous installment discussed in detail how this class determines whether an integer is a prime. In Listing 1, I added the Nextprimefrom () method to generate the next prime number based on the input parameters. This method plays an important role in the example that is coming up in this article.
In general, developers believe that iterators use collections as backing stores, but any collection that supports the iterator interface meets this condition. So I can create an infinite iterator for a prime number, as shown in Listing 2:
Listing 2. Create an inert iterator
public class
Primeiterator implements iterator<integer> {
private int lastprime = 1;
public Boolean Hasnext () {return
true;
}
Public Integer Next () {return
lastprime = Prime.nextprimefrom (lastprime);
}
public void Remove () {
throw new RuntimeException ("Can ' t change the fundamental nature of the universe!");
}
}