Primitive Type Specializations of Supplier – Functional-Style Programming

Primitive Type Specializations of Supplier<T>

The primitive type versions of the generic supplier interface are appropriately named with a prefix to indicate the type of primitive value returned by their functional methods. For example, the integer supplier is named IntSupplier. Their functional methods are also appropriately named with a postfix to indicate the type of value they return. For example, the functional method of the IntSupplier interface is named getAsInt. These primitive type versions are not subinterfaces of the generic Supplier<T> interface. BooleanSupplier is the only specialization with a primitive type other than int, long, or double in the java.util.function package.

Example 13.4 also illustrates defining and using suppliers that return primitive values. Non-generic int suppliers are used in the following examples, without the overhead of boxing and unboxing int values. Calling the getAsInt() method results in the lambda expression to be executed.

Click here to view code image

IntSupplier intSupplier2 = () -> numGen.nextInt(100);
System.out.println(intSupplier2.getAsInt());   // Prints a number in [0, 100).

The method roleDice() at (14) prints statistics of rolling a many-sided dice a specified number of times using an IntSupplier as a dice roller. In the call below, a six-sided dice is rolled 100,000 times using the specified int supplier that generates numbers from 1 to 6.

Click here to view code image

roleDice(6, 100_000, () -> 1 + numGen.nextInt(6));

The reader is encouraged to work through Example 13.4, as it provides additional examples of defining and using suppliers.

Example 13.4 Implementing Suppliers

Click here to view code image

import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.function.DoubleSupplier;
import java.util.function.IntSupplier;
import java.util.function.Supplier;
public class SupplierClient {
  public static void main(String[] args) {
    Supplier<StringBuilder> createSB = () -> new StringBuilder(“Howdy!”);   // (1)
    System.out.println(createSB.get());                          // Prints: Howdy!
    String str = “uppercase me!”;
    Supplier<String> makeUppercase = () -> str.toUpperCase();               // (2)
    System.out.println(makeUppercase.get());              // Prints: UPPERCASE ME!
    // Pseudorandom number generator captured and used in lambda expressions: (3)
    Random numGen = new Random();
    // Generate a number between 0 (inclusive) and 100 (exclusive):            (4)
    Supplier<Integer> intSupplier = () -> numGen.nextInt(100);
    System.out.println(intSupplier.get());         // Prints a number in [0, 100).
    // Build a list of Integers with values between 0 (incl.) and 100 (excl.): (5)
    List<Integer> intRefList = listBuilder(5, () -> numGen.nextInt(100));
    System.out.println(intRefList);
    // Build a list of StringBuilders:                                         (6)
    List<StringBuilder> stringbuilderList = listBuilder(6,
        () -> new StringBuilder(“str” + numGen.nextInt(10)));           // [0, 10)
    System.out.println(stringbuilderList);
    // Build a list that has the same string:                                  (7)
    List<String> stringList2 = listBuilder(4, () -> “Mini me”);
    System.out.println(stringList2);
    // Build a list of LocalTime:                                              (8)
    List<LocalTime> dateList1 = listBuilder(3, () -> LocalTime.now());
    System.out.println(dateList1);
    // Generate a number between 0 (inclusive) and 100 (exclusive):            (9)
    IntSupplier intSupplier2 = () -> numGen.nextInt(100);
    System.out.println(intSupplier2.getAsInt());   // Prints a number in [0, 100).
    // Role many-sided dice:                                                  (10)
    roleDice(6, 100_000, () -> 1 + numGen.nextInt(6));
    roleDice(8, 1_000_000, () -> 1 + (int) (Math.random() * 8));
    // Build an array of doubles with values
    // between 0.0 (incl.) and 5.0 (excl.):                                   (11)
    DoubleSupplier ds = () -> Math.random() * 5;                     // [0.0, 5.0)
    double[] dArray = new double[4];
    for (int i = 0; i < dArray.length; i++) {
      dArray[i] = ds.getAsDouble();
    }
    System.out.println(Arrays.toString(dArray));
  }
  /**
   * Creates a list whose elements are supplied by a Supplier<T>.
   * @param num       Number of elements to put in the list.
   * @param supplier  Supplier that supplies a value to put in the list
   * @return          List created by the method
   */
  public static <T> List<T> listBuilder(int num, Supplier<T> supplier) {   // (12)
    List<T> list = new ArrayList<>();
    for (int i = 0; i < num; ++i) {
      list.add(supplier.get());                                            // (13)
    }
    return list;
  }
  /**
   * Print statistics of rolling a many-sided dice the specified              (14)
   * number of times using an IntSupplier as dice roller.
   */
  public static void roleDice(int numOfSides, int numOfTimes,
                              IntSupplier diceRoller) {
    int[] frequency = new int[numOfSides + 1];         // frequency[0] is ignored.
    for (int i = 0; i < numOfTimes; i++) {
      ++frequency[diceRoller.getAsInt()];                                  // (15)
    }
    System.out.println(Arrays.toString(frequency));
  }
}

Probable output from the program:

Click here to view code image

Howdy!
UPPERCASE ME!
83
[15, 24, 48, 3, 16]
[str8, str0, str6, str8, str6, str7]
[Mini me, Mini me, Mini me, Mini me]
[15:32:05.707, 15:32:05.707, 15:32:05.707]
54
[0, 16747, 16723, 16701, 16607, 16637, 16585]
[0, 124918, 124385, 125038, 125451, 124618, 124600, 125230, 125760]
[0.2129971975975531, 0.6933477140020566, 1.3559818256541756, 1.183773498854187]

Leave a Comment