- Basit bir veri sınıfını
recordile yazmak vevar'ı yerinde kullanmak - Lambda ifadeleri ve metot referansları yazmak
- Koleksiyonları akışlarla (
filter,map,sorted) işlemek ve hepsini bir projede birleştirmek
Java 30 yaşını geçti ama eskimedi: son yıllarda dile kodu epey kısaltan özellikler eklendi. Eskiden 40 satır tutan bir sınıf artık tek satırlık bir record'a, beş satırlık bir döngü de tek satırlık bir akışa dönüşüyor. Bu derste bu özelliklerle tanışacak, ardından kurs boyunca öğrendiklerini birleştirerek küçük ama gerçek bir proje, yani bir öğrenci not defteri geliştireceksin.
record ve var
Record (kayıt, Java 16'dan beri), değişmez verileri tutan bir sınıfın kısa yazılışıdır. record Point(int x, int y) yazdığında Java; private final alanları, yapıcıyı, x() ve y() metotlarını, ayrıca equals, hashCode ve toString metotlarını kendisi oluşturur. Bir record'a kendi metotlarını da ekleyebilirsin. var ise yerel bir değişkenin türünü derleyicinin belirlemesini sağlar.
public class Main {
public static void main(String[] args) {
Point a = new Point(3, 4);
Point b = new Point(3, 4);
System.out.println(a);
System.out.println(a.x() + a.y());
System.out.println(a.equals(b) + " " + (a == b));
System.out.println(a.distanceToOrigin());
var message = "Records save time";
var count = message.length();
System.out.println(message + " (" + count + " chars)");
}
}
record Point(int x, int y) {
double distanceToOrigin() {
return Math.sqrt(x * x + y * y);
}
}Point[x=3, y=4] 7 true false 5.0 Records save time (17 chars)
a.equals(b) sonucu true oldu: record'lar içeriklerine göre karşılaştırılır. a == b ise false'tur, çünkü bunlar iki ayrı nesnedir. Getter adlarında get olmadığına dikkat et: getX() değil, sadece x().
Lambdalar ve metot referansları
Lambda ifadesi, adı olmayan kısa bir fonksiyondur: n -> n * n, “n al, n * n döndür” demektir. Lambdalar fonksiyonel arayüzlerin, yani tek bir soyut metodu olan arayüzlerin yerine kullanılır: Predicate (koşulu sınar), Function (değeri dönüştürür), Comparator (iki nesneyi karşılaştırır). Bir lambda yalnızca hazır bir metodu çağırıyorsa, onu bir metot referansıyla daha da kısa yazabilirsin: System.out::println.
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
public class Main {
public static void main(String[] args) {
Predicate<Integer> isEven = n -> n % 2 == 0;
Function<Integer, Integer> square = n -> n * n;
System.out.println(isEven.test(4) + " " + square.apply(7));
List<String> names = new ArrayList<>(List.of("Murad", "Aysel", "Elvin", "Leyla"));
names.sort((a, b) -> a.compareTo(b));
names.removeIf(name -> name.startsWith("E"));
names.forEach(name -> System.out.print(name + " "));
System.out.println();
names.forEach(System.out::println);
}
}true 49 Aysel Leyla Murad Aysel Leyla Murad
Akışlar (Stream API)
Bir akış (stream), bir koleksiyonun elemanlarını bir üretim bandı gibi işler: filter koşula uyanları tutar, map her elemanı dönüştürür, sorted sıralar; toList, count, sum ya da average ise sonucu toplar. Akış, kaynak koleksiyonu değiştirmez. Kod “nasıl” değil “ne” yapılacağını söyler; bu yüzden kolay okunur.
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Integer> scores = List.of(78, 95, 62, 88, 45, 91);
List<Integer> passed = scores.stream()
.filter(s -> s >= 60)
.sorted()
.toList();
System.out.println(passed);
int total = scores.stream().mapToInt(Integer::intValue).sum();
double avg = scores.stream().mapToInt(Integer::intValue).average().orElse(0);
System.out.println(total + " " + avg);
String initials = List.of("Baku", "Ganja", "Shaki").stream()
.map(c -> c.substring(0, 1))
.collect(Collectors.joining("-"));
System.out.println(initials);
long count = scores.stream().filter(s -> s > 80).count();
System.out.println(count);
}
}[62, 78, 88, 91, 95] 459 76.5 B-G-S 3
Proje: öğrenci not defteri
- 1Veriyi modelle
Öğrenci, adı ve puan listesi olan bir
record'dur. Kompakt yapıcısı 0–100 aralığı dışındaki puanlarıIllegalArgumentExceptionile reddeder. - 2Hesaplamaları ekle
average()ortalama puanı bir akışla bulur ve tek ondalık basamağa yuvarlar;letter()ise bir switch ifadesiyle harf notu verir. - 3Not defteri sınıfını yaz
GradeBook, öğrencileriprivatebirArrayList'te tutar, sıralı bir rapor yazdırır ve sınıf ortalamasını hesaplar. - 4Hepsini main'de birleştir
Öğrencileri ekle, hatalı veriyi
try/catchile yakala ve raporu yazdır.
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
GradeBook book = new GradeBook();
book.add(new Student("Aysel", List.of(92, 88, 95)));
book.add(new Student("Murad", List.of(85, 78, 84)));
book.add(new Student("Leyla", List.of(58, 49, 61)));
book.add(new Student("Nigar", List.of(70, 65, 72)));
try {
book.add(new Student("Elvin", List.of(90, 120)));
} catch (IllegalArgumentException e) {
System.out.println("Skipped: " + e.getMessage());
}
book.printReport();
System.out.println("Class average: " + book.classAverage());
}
}
record Student(String name, List<Integer> scores) {
Student {
for (int s : scores) {
if (s < 0 || s > 100) throw new IllegalArgumentException(name + " has score " + s);
}
}
double average() {
double avg = scores.stream().mapToInt(Integer::intValue).average().orElse(0);
return Math.round(avg * 10) / 10.0;
}
String letter() {
return switch ((int) average() / 10) {
case 10, 9 -> "A";
case 8 -> "B";
case 7 -> "C";
case 6 -> "D";
default -> "F";
};
}
}
class GradeBook {
private final List<Student> students = new ArrayList<>();
void add(Student s) { students.add(s); }
double classAverage() {
double avg = students.stream().mapToDouble(Student::average).average().orElse(0);
return Math.round(avg * 10) / 10.0;
}
void printReport() {
students.stream()
.sorted(Comparator.comparingDouble(Student::average).reversed())
.forEach(s -> System.out.println(s.name() + ": " + s.average() + " (" + s.letter() + ")"));
}
}Skipped: Elvin has score 120 Aysel: 91.7 (A) Murad: 82.3 (B) Nigar: 69.0 (D) Leyla: 56.0 (F) Class average: 74.8
| Projede | Hangi konudan |
|---|---|
record Student, Student { ... } | record'lar, yapıcılar |
throw new IllegalArgumentException, try/catch | istisnalar |
switch ((int) average() / 10) | switch ifadeleri, tür dönüşümü |
private final List<Student> | kapsülleme, koleksiyonlar, generic'ler |
stream(), Student::average, s -> ... | akışlar, metot referansları, lambdalar |
Student { ... }, record'un kompakt yapıcısıdır: parametreleri tekrar yazmadan veriyi doğrulamanı sağlar; alanlar ise ardından otomatik doldurulur. Elvin'in 120 puanı kabul edilmedi ve not defterine girmedi, ama program çalışmaya devam etti; tıpkı istisnalar dersindeki gibi.
Önemli noktalar
record, değişmez bir veri sınıfını tek satırda oluşturur: alanlar, yapıcı, getter'lar,equalsvetoStringotomatik gelir.var, yerel bir değişkenin türünü derleyiciye belirletir, ama tür yine de sabittir.- Lambda (
x -> ...), fonksiyonel bir arayüzün kısa gerçekleştirimidir;Type::methodise bir metot referansıdır. - Akış:
stream()→filter/map/sorted→toList,count,sum,average; kaynak koleksiyon değişmez. - Gerçek bir proje kursun tüm parçalarını bir araya getirir: sınıflar, istisnalar, koleksiyonlar ve modern Java.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
record Point(int x, int y) için x koordinatı nasıl okunur?