import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Supplier;

class Buku {
    String judul;
    int harga;

    Buku() {
        this.judul = "Tanpa Judul";
        this.harga = 0;
    }

    Buku(String judul) {
        this.judul = judul;
        this.harga = 0;
    }

    Buku(String judul, int harga) {
        this.judul = judul;
        this.harga = harga;
    }

    @Override
    public String toString() {
        return judul + " (Rp" + harga + ")";
    }
}

public class PabrikBuku {
    public static void main(String[] args) {
        // Constructor tanpa argumen dipetakan ke Supplier.get()
        Supplier<Buku> pabrikKosong = Buku::new;
        System.out.println(pabrikKosong.get());

        // Constructor satu argumen dipetakan ke Function.apply()
        Function<String, Buku> pabrikJudul = Buku::new;
        System.out.println(pabrikJudul.apply("Algoritma Dasar"));

        // Constructor dua argumen dipetakan ke BiFunction.apply()
        BiFunction<String, Integer, Buku> pabrikLengkap = Buku::new;
        System.out.println(pabrikLengkap.apply("Belajar Java", 95000));

        // Constructor array dipetakan ke IntFunction.apply(int)
        IntFunction<String[]> pabrikRak = String[]::new;
        String[] rak = pabrikRak.apply(3);
        rak[0] = "Pemrograman";
        System.out.println("Rak berisi " + rak.length + " slot, slot pertama: " + rak[0]);
    }
}
