2016-11-09 12 views
8

derlemek verir ama bana derleyici hata veriyorkarşılaştıran ve thenComparing ben Java8 <code>Comparator</code> kullanarak adı daha sonra yaşa göre çalışanların <code>List</code> sıralamak çalışıyorum, ben <code>Comparator</code> aşağıda oluşturduk hatayı

Type mismatch: cannot convert from Comparator<Object> to <unknown>

Comparator<String> c = Comparator.comparing(s -> s.split("\\s+")[0]) 
      .thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1])); //compile error 

Ancak açık bir şekilde Tür

belirtiyorsa çalışır

veya iki Compartor s yaratma ve zincir

Comparator<String> name = Comparator.comparing(s -> s.split("\\s+")[0]); 
    Comparator<String> age = Comparator.comparingInt(s -> Integer.parseInt(s.split("\\s+")[1])); 
    Comparator<String> cc = name.thenComparing(age); //works 

Ben sol tarafta türünü Comparator<String> belirttiniz ama neden oto tür kesmesi doğru Tipi bulamıyor ve açıkça belirtmek için bekliyor tarafından 03.210.

Birisi bunu açıklayabilir mi?

İşte kod

String[] arr = { "alan 25", "mario 30", "alan 19", "mario 25" }; 
    Comparator<String> c = Comparator.<String, String> comparing(s -> s.split("\\s+")[0]) 
      .thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1])); 
    List<String> sorted = Arrays.stream(arr).sorted(c).collect(Collectors.toList()); 
    System.out.println(sorted); 

çıktı Java bütün değişkenlerin bir tür bilmelidir

[alan 19, alan 25, mario 25, mario 30] 
+0

Ben genel tür çıkarsama konusunda uzman değilim, ama bu sadece "çok fazla otomatik çıkarsama" dir tahmin ediyorum. Muhtemelen, karşılaştırma yapan sonuca açıkça bir tür verdiğiniz zincirleme yönteminden farklı olarak, "karşılaştırmak()" yönteminin türünü anlayamaz.) '. Ne olursa olsun, kendi “Comparator” kelimenizi yazmak ve sadece bir defa “split” olarak adlandırmak daha kolay okunabileceğini düşünüyorum. Kodu mümkün olan en az çizgiye sıkıştırmak için ödül yok. – ajb

+1

Hedef yazma, zincirleme yöntem çağırmalarıyla çalışmaz, bkz. [Here] (http://stackoverflow.com/a/28834656/2711488) ve [here] (http://stackoverflow.com/a/26883991/2711488) ve [burada] (http://stackoverflow.com/a/31383947/2711488). Ancak, iki aşamalı karşılaştırıcınız yerine 'Comparator.comparing (s -> s.replaceFirst (" \\ s + "," "))' işlevini kullanabilirsiniz ve sonuç aynı olacaktır… – Holger

+0

'Comparator.comparing ((Dize s) -> s.split ("\\ s +") [0]) ve sonraComparingInt (s -> Integer.parseInt (s.split ("\\ s +") [1])) 'niçin bu' String' gereklidir, ancak 'Comparatorer ' den çıkarılabilir, bu tür çıkarımda bir sınırlama mıdır? BTW, "java sürümü" 1.8.0_60 " – Saravana

cevap

2

olduğunu. Birçok lambda'da bir tür çıkartabilir, ancak ilk kod snippet'inizde s türünü tahmin edemez. Ben bu sorunu çözmek için standart yol açıkça beyan etmek olacağını düşünüyorum: Eğer this answer bakarsak

Comparator<String> c = Comparator.comparing((String s) -> s.split("\\s+")[0]) 
      .thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1])); 

, bu Comparator.comparing() için argüman benzer tip tanımlama bölümüne sahiptir. Sizin yönteminiz, açıkça comparing()'un tür argümanlarını veriyorsanız, açıkça işe yarıyor.

Diğer yönteminiz için, iki karşılaştırıcıyı açıklamak gerekirse, bu durumda Java'nın, geleneksel List <String> = new ArrayList<>();'da olduğu gibi, atamanın sol tarafındaki String'dan çıkabileceği konusunda oldukça eminim. Aynı ifadede thenComparing() numaralı telefonu aradığınızda, Java artık sol taraftaki türün alakalı olduğunu göremez. O Bu da çalışır int size = new ArrayList<>().size(); gibi biraz olacaktır:

Comparator<String> name = Comparator.comparing(s -> s.split("\\s+")[0]); 
    Comparator<String> c = name.thenComparingInt(s -> Integer.parseInt(s.split("\\s+")[1])); 
+1

@ ole-vv Comparator.comparing ((String s) -> s.split ("\\ s +") [0]) ve sonraComparingInt (s -> Integer.parseInt (s.split ("\\ s +") [1])) ancak bu dizenin neden işlediği Gerekli, Karşılaştırıcı 'dan çıkarım yapabilir, bu tür çıkarımda bir sınırlama mıdır? "1.8.0_60" java sürümünü kullanarak BTW – Saravana

+2

Bunu nasıl çıkarıyorsunuz? Biliyorsunuz '' sonraComparing() '' Karşılaştırıcı ' (ödevin sol tarafına uyacak şekilde) döndürmelidir, bu nedenle '(' 'karşılaştırmak') 'Karşılaştırıcı ' döndürmelidir, bu nedenle 's' 'String'. Derleyici bu pek çok mantık yürütme aşamasından geçmez. Evet, bu tür bir çıkarımda bir sınırlamadır, ancak bence bu bir sınırlamadır, çünkü amaç, kuralların çok karmaşıklaşmasına neden olacaktır ve programcılar bunları anlamayacaktır. Bu benim en iyi tahminim. –

+1

En büyük sorun, zincirleme çağırmalarla hedef yazmanın, daha önceki çağrı için mevcut yöntemleri değiştirebilmesidir. Bu, önceki 'hedef türün, yani' foo (x) .bar (y) 'ile dönmenin belirlenmesi için kullanılmıştır. foo (x) türünün hangi yöntemde kullanılacağını ve hangilerinin kullanılacağını belirler, ancak “foo (x)” ye hedef yazmayı uygulamak, aslında seçilen “bar (…)” yöntemine bağlıdır. – Holger

İlgili konular