22 Juni 2018
Menggunakan Functional Interface

Melanjutkan tulisan sebelumnya tentang lambda expression, tutorial kali ini akan memberikan contoh singkat penggunaan functional interfaces yang disediakan dalam java SE 8. Functional interface menyediakan beragam tipe target yang bisa digunakan dengan lambda expression atau melalui referensi metode.

Functional interface disediakan dalam paket java.util.function, disarankan kepada pembaca untuk melihat dokumentasi terlebih dahulu. Didalam paket tersebut terdapat beragam interface untuk kebutuhan-kebutuhan umum.

Operasi dengan Argumen Tunggal

Interface-interface berikut merepresentasikan operasi-operasi yang menerima satu input argumen

Consumer

Interface Consumer<T> (dokumentasi) merepresentasikan operasi yang menerima satu input argumen dengan tipe T dan tidak mengembalikan nilai hasil. Sebagai contoh :

import java.util.function.Consumer;

// Penggunaan Consumer dengan tipe String
Consumer<String> tampilNama = (nama) -> System.out.println("Hai, nama saya : " + nama);
tampilNama.accept("budi");

// Penggunaan Consumer dengan tipe Integer
Consumer<Integer> hitungLuasPersegi = (sisi) -> {
  int luas = sisi * sisi;
  System.out.println("Luas persegi adalah : " + luas);
};
hitungLuasPersegi.accept(20);

Sebagaimana dicontohkan diatas, pengerjaan operasi tampilNama dan hitungLuasPersegi dipicu oleh pemanggilan metode .accept(). Operasi ini dapat dirangkaikan dengan operasi Consumer<T> lain melalui penggunaan metode .andThen(). Sebagai contoh :

Consumer<String> tampilNama = (nama) -> System.out.println("Halo nama saya : " + nama);
tampilNama
  .andThen((nama) -> {
    char[] temp = new char[nama.length()];
    int j=0;
    for(int i=(nama.length()-1); i>=0; i--) {
      temp[j] = nama.charAt(i);
      j++;
    }
    System.out.println("Kalau dibalik menjadi : " + new String(temp));
  })
  .accept("Budiman");

Hasil eksekusi dari kode diatas adalah sebagai berikut :

cmd01

Function

Interface Function<T,R> (dokumentasi) merepresentasikan sebuah fungsi yang menerima satu input argumen dengan tipe T dan mengembalikan hasil dengan tipe R. Sebagai contoh :

import java.util.function.Function;

// fungsi dengan input 1 argumen String dan output String
Function<String, String> flipText = (text) -> {
  char[] temp = new char[text.length()];
  int j = 0;
  for(int i=(text.length()-1); i>=0; i--) {
    temp[j] = text.charAt(i);
    j++;
  }
  return new String(temp);
};
String str = flipText.apply("Quick Brown Fox Jumps Over The Lazy Dog");
System.out.println(str);

Pemicu dari fungsi flipText diatas adalah metode .apply(). Interface Function<T,R> juga dilengkapi dengan beberapa metode default yaitu .compose() dan .andThen(). Contoh penggunaannya adalah sebagai berikut :

import java.util.function.Function;

// fungsi ini membalik text dari belakang ke depan
Function<String,String> flipText = (text) -> {
  char[] temp = new char[text.length()];
  int j = 0;
  for(int i=(text.length()-1); i>=0; i--) {
    temp[j] = text.charAt(i);
    j++;
  }
  return new String(temp);
};

// fungsi ini menghapus spasi dan mengubah karakter menjadi kapital
Function<String, String> uppercaseText = (text) -> {
  return text.toUpperCase().replaceAll(" ", "");
};

// fungsi ini menambah text dengan kalimat "this is just a text"
Function<String, String> mixText = (text) -> {
  return text + " this is just a text";
};

String str = flipText
  .andThen(uppercaseText)
  .compose(mixText)
  .apply("Quick Brown Fox Jumps Over The Lazy Dog");
System.out.println(str);

Urutan kerja dari kode diatas adalah sebagai berikut :

  1. Input String yang diterima, digabungkan (concat) dengan tulisan "this is just a text" sebagaimana terlihat pada fungsi mixText yang dipanggil dalam metode .compose()
  2. Hasil berupa String dari .compose(mixText) dibalik menggunakan fungsi flipText yang dipicu dengan metode .apply()
  3. Terakhir, karakter pada text hasil dari metode .apply() diubah menjadi huruf kapital dan spasi yang ada didalamnya dihilangkan (perhatikan fungsi uppercaseText)

Contoh eksekusi dari kode diatas adalah sebagai berikut :

cmd02

Predicate

Interface Predicate<T> merepresentasikan fungsi dengan satu buah input argumen bertipe T yang akan mengembalikan nilai boolean. Sebagai contoh :

import java.util.function.Predicate;

Predicate<Integer> isEven = (num) -> (num % 2) == 0;
if(isEven.test(20)) {
  System.out.println("Bilangan genap");
}
else {
  System.out.println("Bilangan ganjil");
}

Fungsi isEven akan mengembalikan nilai true jika operasi modulo terhadap variabel num menghasilkan nilai 0, yang mengindikasikan bahwa num adalah bilangan genap. Pemicu dari fungsi tersebut adalah pemanggilan terhadap metode .test().

Interface Predicate<T> juga dilengkapi dengan beberapa metode default diantaranya adalah .and() dan .or(). Contoh penggunaannya adalah sebagai berikut :

Predicate<Integer> isEven = (num) -> (num % 2) == 0;
boolean res = isEven
  .and((num) -> num >= 1000 && num <= 5000)
  .or((num) -> (num == 1981) || (num == 2981))
  .test(1980);
if(res) {
  System.out.println("Genap, diantara 1000 dan 5000 atau angka spesial (1981/2981)");
}
else {
  System.out.println("Ganjil, tidak diantara 1000 dan 5000, dan bukan angka spesial (1981/2981)");
}

Penjelasan : variabel boolean res akan bernilai true jika argumen num adalah bilangan genap dan diantara 1000 sampai 5000 atau angka spesial (1981 atau 2981). Hasil eksekusi dari kode diatas adalah sebagai berikut :

cmd03