Fonksiyonel programlama nedir? Java'da Fonksiyonel programlama



Fonksiyonel programlama, bilgisayar bilimlerindeki bir programlama paradigmasıdır ve temel olarak matematiksel fonksiyon kavramına dayanır. Bu yaklaşımda, programlar bir dizi fonksiyonun birbirleriyle etkileşimi olarak modellenir. Fonksiyonel programlamanın bazı anahtar özellikleri şunlardır:


Saf Fonksiyonlar (Pure Functions): Fonksiyonlar, girdileri üzerinden sadece çıktılarını üreten ve yan etkisi olmayan (global veya statik veri durumunu değiştirmeyen) işlemlerdir. Bir fonksiyonun aynı girdiler için her zaman aynı çıktıyı vermesi beklenir.


Durumsuzluk (Statelessness): Fonksiyonel programlamada, programın durumu global değişkenlerle değil, fonksiyon çağrılarının dönüş değerleriyle yönetilir.


Birinci Sınıf ve Yüksek Seviye Fonksiyonlar (First-class and Higher-order Functions): Fonksiyonlar, birinci sınıf vatandaşlardır; yani, değişkenlere atanabilir, diğer fonksiyonlara argüman olarak geçilebilir veya diğer fonksiyonlar tarafından döndürülebilir.


Özyinelemeli (Recursive) ve Kuyruk Özyinelemesi (Tail Recursion): Fonksiyonel programlamada döngüler genellikle özyineleme (bir fonksiyonun kendisini çağırması) ile ifade edilir. Kuyruk özyinelemesi, özyinelemin performansını ve hafıza kullanımını optimize eder.


Soyutlama: Fonksiyonel programlama, daha yüksek seviye soyutlamalara olanak tanır, bu da kodun daha okunabilir ve yeniden kullanılabilir olmasını sağlar.


Etkisiz Fonksiyonlar (Immutable Data): Veri yapısının değişmez olması, paylaşılan durumun yan etkilerini önler ve programların daha tahmin edilebilir olmasını sağlar.


Fonksiyonel programlama dilleri arasında Haskell, Lisp, Scala, Erlang, ve F# bulunmaktadır. Bu paradigmalar, özellikle paralel işleme, veri akışı modellemesi ve reaktif programlama gibi alanlarda avantajlar sağlar. Fonksiyonel programlama yaklaşımlarının bazıları, Java, JavaScript, C#, ve Python gibi çok paradigmalı dillerde de kullanılabilir.


Java'da Fonksiyonel programlama


Java'da fonksiyonel programlama, Java 8 ile birlikte daha fazla önem kazandı. Java 8, fonksiyonel arayüzler, lambda ifadeleri ve Stream API gibi özelliklerle fonksiyonel programlama kavramlarını desteklemeye başladı. İşte Java'da fonksiyonel programlama örnekleri:


1. Lambda İfadeleri

Lambda ifadeleri, anonim fonksiyonları tanımlamak için kullanılır. Bunlar, fonksiyonel arayüzlerle birlikte çalışır.


java

Copy code

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");


// Klasik yaklaşım

Collections.sort(names, new Comparator<String>() {

    public int compare(String a, String b) {

        return a.compareTo(b);

    }

});


// Lambda ile

Collections.sort(names, (String a, String b) -> a.compareTo(b));

2. Fonksiyonel Arayüzler

Fonksiyonel arayüz, yalnızca bir soyut metoda sahip bir arayüzdür. @FunctionalInterface anotasyonu ile işaretlenebilir.


java

Copy code

@FunctionalInterface

interface Greeting {

    String sayHello(String name);

}


// Lambda ile kullanımı

Greeting greeting = (name) -> "Hello, " + name;

System.out.println(greeting.sayHello("Alice"));

3. Stream API

Stream API, koleksiyonlar üzerinde fonksiyonel tarzda işlemler yapmayı sağlar.


java

Copy code

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);


// Her elemanın karesini alıp yazdırmak

numbers.stream()

       .map(n -> n * n) // her elemanı karesiyle değiştirir

       .forEach(System.out::println); // sonuçları yazdırır

4. Method Referansları

Method referansları, var olan metotları kısa bir şekilde ifade etmek için kullanılır.


java

Copy code

List<String> cities = Arrays.asList("London", "Paris", "New York");


// Lambda ile

cities.forEach(city -> System.out.println(city));


// Method referansı ile

cities.forEach(System.out::println);

5. Optional

Optional, null değerlerle çalışmayı daha güvenli hale getiren bir sınıftır.


java

Copy code

Optional<String> optionalString = Optional.of("Hello");


// Değer varsa yazdır

optionalString.ifPresent(System.out::println);

Bu örnekler, Java'da fonksiyonel programlama yaklaşımlarının temellerini göstermektedir ve bu konseptler daha karmaşık senaryolarda da kullanılabilir. Fonksiyonel programlama, özellikle büyük veri setleri ve paralel işlemlerle çalışırken avantajlar sağlayabilir.


Java'daki fonksiyonel programlama özelliklerine daha detaylı bakalım:


6. Filter, Map ve Reduce

Stream API'nin filter, map ve reduce gibi metotları, koleksiyonlar üzerinde fonksiyonel işlemleri kolaylaştırır.


Filter: Bir akıştaki elemanları belirli bir kritere göre filtreler.


java

Copy code

List<String> words = Arrays.asList("apple", "banana", "cherry", "date");


// 'b' harfi ile başlayan kelimeleri filtrele

List<String> bWords = words.stream()

                           .filter(s -> s.startsWith("b"))

                           .collect(Collectors.toList());

System.out.println(bWords); // [banana]

Map: Akıştaki her elemanı başka bir forma dönüştürür.


java

Copy code

List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5);


// Her sayının karesini al

List<Integer> squaredNumbers = numberList.stream()

                                         .map(n -> n * n)

                                         .collect(Collectors.toList());

System.out.println(squaredNumbers); // [1, 4, 9, 16, 25]

Reduce: Akıştaki tüm elemanları tek bir sonuca indirger.


java

Copy code

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);


// Tüm sayıların toplamını bul

int sum = numbers.stream()

                 .reduce(0, (a, b) -> a + b);

System.out.println(sum); // 15

7. Collectors

Collectors sınıfı, Stream sonuçlarını çeşitli şekillerde toplamak veya dönüştürmek için kullanılır.


java

Copy code

List<String> names = Arrays.asList("John", "Jane", "Adam", "Tom");


// İsimleri virgülle ayrılmış bir string olarak birleştir

String result = names.stream()

                     .collect(Collectors.joining(", "));

System.out.println(result); // John, Jane, Adam, Tom

8. Paralel Akışlar

Java'da parallelStream() metodu, çok çekirdekli işlemcilerde verimli paralel işlemler için kullanılabilir.


java

Copy code

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);


// Paralel olarak toplama işlemi yap

int sumParallel = numbers.parallelStream()

                         .reduce(0, Integer::sum);

System.out.println(sumParallel); // 55

9. CompletableFuture

CompletableFuture, Java'da asenkron programlamayı kolaylaştıran bir sınıftır ve fonksiyonel programlama tarzında kullanılabilir.


java

Copy code

CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> "Hello");


// Asenkron olarak işlemi tamamladıktan sonra eylem yap

completableFuture.thenAccept(System.out::println);

Bu örnekler, Java'da fonksiyonel programlamanın çeşitli yönlerini göstermektedir. Fonksiyonel programlama, kodun daha okunabilir, daha az hata eğilimli ve daha kolay test edilebilir olmasını sağlar. Ayrıca, paralel işleme ve asenkron işlemler için de büyük avantajlar sunar. Java'da bu yaklaşımları kullanarak, daha etkili ve verimli programlar yazabilirsiniz.


10. BiFunction ve UnaryOperator

Java'daki BiFunction ve UnaryOperator gibi arayüzler, özelleşmiş fonksiyonel arayüzlerdir ve belirli türdeki işlemleri gerçekleştirmek için kullanılırlar.


BiFunction: İki argüman alıp bir sonuç döndüren bir fonksiyonel arayüzdür.


java

Copy code

BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;

System.out.println(add.apply(10, 20)); // 30

UnaryOperator: Tek bir tür üzerinde işlem yapan ve aynı türden bir sonuç döndüren bir fonksiyonel arayüzdür.


java

Copy code

UnaryOperator<Integer> square = x -> x * x;

System.out.println(square.apply(5)); // 25

11. Optional İşlemleri

Optional sınıfı, null değerlerle daha güvenli bir şekilde çalışmanızı sağlar ve zincirleme metodlar sunar.


java

Copy code

Optional<String> optionalString = Optional.of("Java");


// Map ve orElse kullanımı

String result = optionalString.map(String::toUpperCase)

                              .orElse("Default");

System.out.println(result); // JAVA


Java'da Method referansları,


ChatGPT

Java'da method referansları, Java 8 ile tanıtılan bir özelliktir ve lambda ifadelerinin kısa ve okunabilir bir alternatifidir. Bir method referansı, zaten tanımlanmış bir metodun tekrar kullanımını sağlar. Bu, özellikle fonksiyonel arayüzlerle birlikte kullanıldığında kodu daha temiz ve anlaşılır hale getirir.


Method referanslarının kullanımı genellikle dört ana formda gerçekleşir:


Statik Metod Referansları: ClassName::methodName

Örnek Üzerinden Metod Referansları: instance::methodName

Örnek Metodu Referansları (sınıf türünden): ClassName::methodName

Kurucu Referansları: ClassName::new

Örnekler

1. Statik Metod Referansları

Statik bir metodu referans almak için ClassName::methodName kullanılır.


java

Copy code

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");


// Lambda ile

names.forEach(name -> System.out.println(name));


// Method referansı ile

names.forEach(System.out::println);

2. Örnek Üzerinden Metod Referansları

Bir nesnenin örneği üzerinden metod referansı yapmak için instance::methodName kullanılır.


java

Copy code

String something = "Hello";

Function<String, String> converter = something::concat;

System.out.println(converter.apply(" World")); // Hello World

3. Örnek Metodu Referansları (Sınıf Türünden)

Bir sınıfın örneği üzerinden metod referansı yapmak için ClassName::methodName kullanılır, ancak bu sefer metod ilk parametre üzerinden çağrılır.


java

Copy code

List<String> strings = Arrays.asList("1", "2", "3");


// Lambda ile

List<Integer> integers = strings.stream()

                                .map(s -> Integer.parseInt(s))

                                .collect(Collectors.toList());


// Method referansı ile

List<Integer> integersWithMethodReference = strings.stream()

                                                   .map(Integer::parseInt)

                                                   .collect(Collectors.toList());

4. Kurucu Referansları

Bir sınıfın kurucusuna referans yapmak için ClassName::new kullanılır.


java

Copy code

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");


// Lambda ile

List<User> users = names.stream()

                        .map(name -> new User(name))

                        .collect(Collectors.toList());


// Kurucu referansı ile

List<User> usersWithConstructorReference = names.stream()

                                                .map(User::new)

                                                .collect(Collectors.toList());

Bu örnekler, Java'da method referanslarının nasıl kullanıldığını göstermektedir. Method referansları, kodunuzu daha okunabilir ve yönetilebilir hale getirebilir, özellikle tekrar eden işlevsellikler için lambda ifadelerine göre daha temiz bir alternatif sunar.

Please Select Embedded Mode To Show The Comment System.*

Daha yeni Daha eski

نموذج الاتصال