2015-06-26 18 views
12

üzerine JDK'yi 8 Tüketiciyi uygula İşte benim kaynak kodu: Bu gayet iyi çalışıyorJava 8. ilgili bir sorum var dize

final Consumer<String> d = e -> System.out.println(e); 
final Function<String, String> upper = x -> x.toUpperCase(); 
final Function<String, String> lower = x -> x.toLowerCase(); 

new Thread(() -> d.accept(upper.apply("hello 1"))).run(); 
new Thread(() -> d.accept(lower.apply("hello 2"))).run(); 

ve aşağıdaki çıktıyı üretir:

HELLO 1 
hello 2 

sorum şimdi d.accept ve upper.apply yukarıdaki sözdizimi yalnızca olası bir tanesidir ya biraz daha "java 8 lambda" tarzı varsa son iki yazabilmişti eğer.

+1

Bu lambda'lar yerine _method references_ kullanmak için tüm ideal adaylardır. –

cevap

9

lambda ifadeleri veya fonksiyonel arayüzler hakkında hakkında hiçbir şey söylemeden önce, size gerçekten sorunlu hata hakkında konuşmak zorunda: bir iş parçacığı üzerinderun()aradığınız! Eğer yeni bir iş parçacığı başlatmak istiyorsanız kod sırayla çalıştırmak istiyorsanız, bir Thread (ama sadece Runnable) oluşturmayın, Thread örneğinde start() aramak zorunda. bahsedilen

, birleştirme fonksiyonlar, örneğin Java 8 fonksiyonel arayüzleri bazı default yöntem vardır iki Function s'yi Function.andThen(…) üzerinden zincirleyebilirsiniz ancak mevcut kombinasyonlar tamamlanmaktan uzaktır.

belli birleştirerek görev uygulamanızda tekrar ediyorsa, yarar yöntemleri oluşturmayı düşünebilirsiniz:

public static <T> Runnable bind(T value, Consumer<T> c) { 
    return()->c.accept(value); 
} 
public static <T,U> Consumer<U> compose(Function<U,T> f, Consumer<? super T> c) { 
    return u->c.accept(f.apply(u)); 
} 

new Thread(bind("Hello 1", compose(upper, d))).start(); 
new Thread(bind("Hello 2", compose(lower, d))).start(); 

Fakat bu üç parça daha akışı API için bir görev gibi bak:

Stream.of("Hello 1").map(upper).forEach(d); 
Stream.of("Hello 2").map(lower).forEach(d); 

Yeni iş parçacığının oluşturulmasını burada bırakmadım çünkü zaten herhangi bir fayda.

Gerçekten paralel işlem istiyorsanız, Çerezsiz bazında yapabilirsiniz:

"Hello 1".chars().parallel() 
    .map(Character::toUpperCase).forEachOrdered(c->System.out.print((char)c)); 

ama hala görevin basitlik verilen herhangi yarar ve sabit havai olmayacak paralel işlem. System.out :: println, dize :: toUpperCase:

+1

Paralel işlemeyle ilgili olarak: JDK8'deki varsayılan 'chars()' uygulaması gerçekten çok kötü. Muhtemelen uzun dizeler için bile fark edilebilir hızlanma elde edersiniz. JDK9'da daha iyi. –

+2

@Tagir Valeev: Bunu biliyorum ama detaylara çok fazla girmek istemedim.Sonuçta, Java 9'un daha iyi bölünme desteğiyle bile, bu sorunun görevi paralel yürütmeden yararlanamaz. Basit bir "toUpperCase" dönüşümünün paralel yürütmeden yararlanabileceği kadar uzun bir "String" olabileceğinden şüphe duyuyorum. Bu arada, Java 8 API'sı bu sınırlamanın üstesinden gelmek için bir yola sahiptir: 'string.chars()' 'yerine 'CharBuffer.wrap (string) .chars()' kullanın… – Holger

+0

Çok teşekkür ederim. Bu bana çok yardımcı oldu. Thread.run ile kesinlikle haklısınız. Bu sadece bir örnekti ve lambdalarla ilgisi var. –

3

Evet, sadece olası yazım bu. Aslında lambda kullandığınızda, aslında lambda mı yoksa verilen arabirimin (anonim sınıf veya hatta normal sınıf aracılığıyla) eski bir uygulama olup olmadığını bile bilmiyorsunuzdur. Yani, işlevsel arayüzü diğer herhangi bir Java arabirimi olarak kullanmanız gerekir: yöntemini açıkça arayın.

4

Ayrıca böyle yazabilirsiniz:

new Thread(() -> Stream.of("hello 1").map(upper).forEach(d)).run(); 
    new Thread(() -> Stream.of("hello 1").map(lower).forEach(d)).run(); 

Ya da daha directlry:

new Thread(() -> Stream.of("hello 1").map(String::toUpperCase).forEach(System.out::println)).run(); 
    new Thread(() -> Stream.of("hello 1").map(String::toLowerCase).forEach(System.out::println)).run();