Java 8 විශේෂාංග: Lambdas, Streams, Optional - පියවරෙන් පියවර ගයිඩ්

කොහොමද යාලුවනේ! මේ දවස් වල තාක්ෂණය ගැන කතා කරනකොට, Software Development කියන්නේ ගොඩක් දෙනෙක්ගේ අවධානය දිනාගත්තු ක්ෂේත්රයක් නේද? විශේෂයෙන්ම Java ගැන කතා කරනකොට, ඒක තාමත් ලෝකේ ජනප්රියම programming languages වලින් එකක්. ඒකත් ඉතින් හේතු නැතුව නෙවෙයි, enterprises වල ඉඳන් mobile apps වෙනකම් හැම තැනම Java තියෙනවා.
හැබැයි, Java කියන්නේ නිකම්ම නිකම් එක තැන පල්වෙන language එකක් නෙවෙයි. ඒක සැරෙන් සැරේ අලුත් වෙනවා, දියුණු වෙනවා. Java 8 release එක කියන්නේ Java ecosystem එකට ආපු ලොකුම වෙනස්කම් වලින් එකක්. ඒකෙන් අපේ කෝඩ් කරන විදිය, ප්රොබ්ලම්ස් solve කරන විදිය ගොඩක් පහසු වුණා, modern වුණා. අද අපි කතා කරමු Java 8 ගෙනාපු ඒ සුපිරිම features ටික ගැන: Lambdas, Streams, Optional වගේ දේවල් කොහොමද අපේ දෛනික කෝඩිං වැඩ වලට උදව් වෙන්නේ කියලා.
ඉතින්, මේක Java ගැන අලුතින් ඉගෙන ගන්න කෙනෙක්ට වගේම, දැනටමත් Java කරන කෙනෙක්ටත් ගොඩක් වැදගත් වෙයි. එහෙනම් අපි පටන් ගමු!
Lambdas – කම්මැලි කෝඩ් වලට බයි-බයි!
Java 8 එක්ක ආපු ප්රධානම වෙනස්කම තමයි Lambda Expressions. "Lambdas" කියන්නේ මොනවද? සරලවම කිව්වොත්, ඒක anonymous functions හෙවත් නම් නැති functions. අපිට පුළුවන් මේකෙන් කෙටි, පැහැදිලි කෝඩ් ලියන්න. විශේෂයෙන්ම functional interfaces (එක abstract method එකක් විතරක් තියෙන interfaces) එක්ක වැඩ කරනකොට මේක ගොඩක් ප්රයෝජනවත්.
ඇයි Lambdas වැදගත්?
- කෝඩ් එකේ කෙටිකම (Conciseness): බොයිලර්ප්ලේට් කෝඩ් (boilerplate code) අඩු කරනවා.
- පැහැදිලිකම (Readability): කෝඩ් එක කියවන්න පහසුයි, මොකද වැඩේ වෙන්නේ මොකක්ද කියලා කෙලින්ම පේනවා.
- Functional Programming: Java වලට functional programming concept ගෙනාවා.
උදාහරණයක් බලමු:
ඉස්සර අපි `Thread` එකක් හදන්න `Runnable` interface එක implement කරේ මෙහෙමයි:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello from a Thread!");
}
}).start();
දැන් Java 8 එක්ක, Lambda එකක් පාවිච්චි කරලා මේක කොච්චර කෙටියෙන් ලියන්න පුළුවන්ද බලන්න:
new Thread(() -> System.out.println("Hello from a Lambda Thread!")).start();
අප්පට සිරි, දැක්කද වෙනස! මේකෙන් කෝඩ් එක කොච්චර නම් clear ද? ඒ වගේම `Collections.sort()` වගේ තැන් වලදීත් `Comparator` එකක් ලියන්න පුළුවන්කම ලැබුණා. ඉස්සර අර class එකක් හදලා implement කරන වැඩේ දැන් එක ලයින් එකෙන් ඉවරයි. නියමයි නේද?
Stream API – දත්ත ප්රොසෙස් කරන සුපිරි ක්රමය!
Java 8 ගෙනාපු තවත් සුපිරි feature එකක් තමයි Stream API එක. මේක Collection (List, Set, Map) වගේ දත්ත structure වල තියෙන දත්ත (data) ප්රොසෙස් කරන්න තියෙන අලුත්ම, powerful ක්රමයක්. අපි Collection එකක data filter කරනවා නම්, map කරනවා නම්, sort කරනවා නම්, මේ Stream API එකෙන් ඒක ගොඩක් පහසුවෙන්, කාර්යක්ෂමව කරන්න පුළුවන්.
Stream API වල වාසි:
- Functional Operations: filter, map, reduce වගේ functional operations ගොඩක් තියෙනවා.
- Pipeline processing: එකෙන් එකට operations chaining කරන්න පුළුවන්.
- Parallel processing: ගොඩක් data ප්රොසෙස් කරන්න ඕන නම්, parallel streams පාවිච්චි කරලා performance වැඩි කරගන්න පුළුවන්.
උදාහරණයක් බලමු:
අපිට තියෙනවා නම් numbers list එකක්, ඒකෙන් even numbers විතරක් අරගෙන, ඒ හැම even number එකක්ම දෙකෙන් වැඩි කරලා, අන්තිමට ඒ list එක print කරන්න ඕනේ කියලා හිතමු.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Java 7 වලදි නම් මෙහෙමයි කරන්නේ:
List<Integer> evenDoubledNumbersJava7 = new ArrayList<>();
for (Integer number : numbers) {
if (number % 2 == 0) {
evenDoubledNumbersJava7.add(number * 2);
}
}
System.out.println("Java 7 Output: " + evenDoubledNumbersJava7);
// Java 8 Stream API පාවිච්චි කරලා:
List<Integer> evenDoubledNumbersJava8 = numbers.stream()
.filter(n -> n % 2 == 0) // Even numbers විතරක් filter කරනවා
.map(n -> n * 2) // හැම even number එකක්ම දෙකෙන් වැඩි කරනවා
.collect(Collectors.toList()); // අලුත් List එකකට එකතු කරනවා
System.out.println("Java 8 Output: " + evenDoubledNumbersJava8);
දැක්කද, Stream API එකෙන් කෝඩ් එක කොච්චර පැහැදිලිද කියලා! `filter`, `map`, `collect` වගේ operations chaining කරලා අපිට ඕන දේ එක line එකකින් වගේ කරගන්න පුළුවන්. මේකෙන් කෝඩ් එකේ flow එකත් ගොඩක් පැහැදිලියි, මොකක්ද වෙන්නේ කියලා එකපාරටම තේරෙනවා.
Optional – NullPointerExceptions වලට විසඳුමක්!
Java developer කෙනෙක් විදියට ඔයාලට `NullPointerException` (NPE) කියන error එක නොලැබී නැතුව ඇති. ඒක Java වලදී ගොඩක්ම එන runtime error එකක්. Object එකක් null ද නැද්ද කියලා check නොකර methods call කරාම තමයි මේ error එක එන්නේ.
Java 8 මේකට ලස්සන විසඳුමක් ගෙනාවා: ඒ තමයි `java.util.Optional` class එක. `Optional` කියන්නේ object එකක් තියෙන්නත් පුළුවන්, නැති වෙන්නත් පුළුවන් (null වෙන්නත් පුළුවන්) කියන එක පෙන්නන්න පාවිච්චි කරන container object එකක්. මේකෙන් අපිට NullPointerException එක අවම කරගන්න පුළුවන්, ඒ වගේම අපේ කෝඩ් එකේ null values handle කරන විදියත් ගොඩක් පැහැදිලි වෙනවා.
Optional පාවිච්චි කරන විදිය:
- `Optional.of(value)`: value එක null නොවන බවට sure නම් පාවිච්චි කරන්න. value එක null නම් NPE එනවා.
- `Optional.ofNullable(value)`: value එක null වෙන්නත් පුළුවන් නම් පාවිච්චි කරන්න. null නම් empty Optional එකක් return කරනවා.
- `Optional.empty()`: හිස් Optional object එකක් හදන්න.
වැදගත් Methods:
- `isPresent()`: Optional එකේ value එකක් තියෙනවද කියලා check කරන්න. (නමුත් `ifPresent()` හෝ `orElse()` වැනි methods වඩා හොඳයි)
- `get()`: value එක ගන්න. හැබැයි value එක නැත්නම් `NoSuchElementException` එකක් එනවා. ඒ නිසා පරිස්සමෙන් පාවිච්චි කරන්න.
- `orElse(defaultValue)`: value එකක් නැත්නම් default value එකක් දෙන්න.
- `orElseThrow(exceptionSupplier)`: value එකක් නැත්නම් custom exception එකක් throw කරන්න.
- `ifPresent(consumer)`: value එකක් තියෙනවා නම් විතරක් action එකක් කරන්න.
උදාහරණයක්:
String name = "Kasun";
Optional<String> optionalName = Optional.ofNullable(name);
if (optionalName.isPresent()) {
System.out.println("Hello, " + optionalName.get());
} else {
System.out.println("Hello, Guest!");
}
// orElse() පාවිච්චි කරලා
String actualName = optionalName.orElse("Guest");
System.out.println("Hello using orElse, " + actualName);
// ifPresent() පාවිච්චි කරලා
optionalName.ifPresent(n -> System.out.println("Hello using ifPresent, " + n));
// null value එකක් එක්ක බලමු
String emptyName = null;
Optional<String> optionalEmptyName = Optional.ofNullable(emptyName);
System.out.println("Empty name using orElse: " + optionalEmptyName.orElse("No Name Provided"));
මේ `Optional` එක පාවිච්චි කරනකොට, "අප්පෝ මේක null වෙන්න පුළුවන් නේ" කියලා හිතලා ඒක handle කරන්න අපිට කෝඩ් එකෙන්ම අර අත දික් කරනවා වගේ වැඩක්. මේකෙන් අපේ කෝඩ් එකේ robustness එක වැඩි වෙනවා.
Default Methods and Static Methods in Interfaces – අලුත් Interface සෙල්ලම්!
Java 8 එක්ක ආපු තවත් වැදගත් වෙනසක් තමයි interfaces වලට default methods සහ static methods එකතු කරන්න පුළුවන් වීම. ඉස්සර නම් interface එකක තියෙන්නේ abstract methods විතරයි. ඒ කියන්නේ implementation එකක් නැති methods.
ප්රශ්නය:
අපි library එකක් හදනකොට, interface එකකට අලුත් method එකක් එකතු කරන්න වුණොත්, ඒ interface එක implement කරපු හැම class එකකටම ඒ අලුත් method එක implement කරන්න වෙනවා. මේක බරපතල ගැටලුවක්, මොකද ඒ library එක පාවිච්චි කරන අයගේ කෝඩ් එක එකපාරටම කැඩෙනවා (breaks backward compatibility).
විසඳුම: Default Methods
`default` කියන keyword එක පාවිච්චි කරලා, අපිට පුළුවන් interface method එකකට default implementation එකක් දෙන්න. එතකොට අලුත් method එකක් interface එකට එකතු කරාට, ඒ interface එක implement කරපු classes කැඩෙන්නේ නැහැ. මොකද එයාලට default implementation එක පාවිච්චි කරන්න පුළුවන්.
interface MyInterface {
void existingMethod();
// Java 8 වලට පස්සේ අලුතින් එකතු කරපු default method එකක්
default void newDefaultMethod() {
System.out.println("This is a default implementation from MyInterface.");
}
}
class MyClass implements MyInterface {
@Override
public void existingMethod() {
System.out.println("Existing method implemented in MyClass.");
}
// newDefaultMethod() එක මෙතන implement කරන්න ඕන නැහැ, default එක වැඩ කරනවා
}
class AnotherClass implements MyInterface {
@Override
public void existingMethod() {
System.out.println("Existing method implemented in AnotherClass.");
}
@Override
public void newDefaultMethod() {
// default implementation එක overwrite කරන්නත් පුළුවන්
System.out.println("AnotherClass's custom implementation for newDefaultMethod.");
}
}
// Usage
// MyClass obj1 = new MyClass();
// obj1.existingMethod();
// obj1.newDefaultMethod(); // default implementation එක call වෙනවා
// AnotherClass obj2 = new AnotherClass();
// obj2.existingMethod();
// obj2.newDefaultMethod(); // custom implementation එක call වෙනවා
Static Methods in Interfaces:
මේකත් default methods වගේම interface වලට ආපු තවත් හොඳ feature එකක්. මේකෙන් interface එකටම අයිති utility methods ලියන්න පුළුවන්. උදාහරණයක් විදියට `Comparator.comparing()` කියන static method එක. මේ methods interface එකේ නමින් කෙලින්ම call කරන්න පුළුවන්.
අවසන් වශයෙන්...
ඉතින් යාලුවනේ, Java 8 කියන්නේ Java ecosystem එකට ආපු ලොකුම update එකක්. Lambdas, Streams, Optional, default methods වගේ features නිසා අපිට පුළුවන් clean, concise, modern, සහ maintain කරන්න පහසු කෝඩ් ලියන්න. මේවා දැන් හැම Java project එකකම වගේ පාවිච්චි වෙනවා, ඒ නිසා මේවා ගැන හොඳ අවබෝධයක් තියෙන එක ඔයාට developer කෙනෙක් විදියට ලොකු වාසියක්.
මේ features වලින් ඔයාලගේ දෛනික කෝඩිං වැඩ ගොඩක් පහසු වෙයි කියලා මම හිතනවා. වැදගත්ම දේ තමයි, මේවා පොතෙන් විතරක් කියවලා හරියන්නේ නැහැ, අනිවාර්යයෙන්ම ඔයාලගේ IDE එකේ පොඩි project එකක් හදලා මේවා අත්හදා බලන්න. එතකොට තමයි හරියටම අල්ලගන්න පුළුවන්.
මේ post එක ගැන ඔයාලගේ අදහස්, ප්රශ්න පහළින් comment කරන්න. Java 8 features ගැන ඔයාලට තියෙන අත්දැකීම් මොනවද? ඔයාලගේ ප්රියතම feature එක මොකක්ද? අපි කතා කරමු!
එහෙනම් ආයෙත් අලුත් දෙයක් අරගෙන එනකම්, හැමෝටම ජය වේවා!