2016-11-09 19 views
8

Tôi cố gắng để sắp xếp List của người lao động theo tên thì tuổi sử dụng Java8 Comparator, tôi đã tạo ra bên dưới Comparator nhưng nó mang lại cho tôi một lỗi biên dịchso sánh và thenComparing cho biên dịch lỗi

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 

nhưng nó hoạt động nếu tôi chỉ định rõ ràng Loại

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

hoặc bằng cách tạo ra hai Compartor s và chuỗi

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 

tôi đã xác định loại Comparator<String> ở phía bên trái nhưng tại sao loại tự động suy luận không tìm đúng loại, phấn đấu để xác định rõ ràng.

Ai đó có thể làm rõ điều này?

Đây là mã

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); 

đầu ra

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

Tôi không phải là chuyên gia về suy luận kiểu chung, nhưng tôi đoán đây chỉ là "quá nhiều suy luận tự động". Có lẽ, nó không thể tìm ra loại phương thức 'compare()' vì nó không có bất kỳ kiểu nào để "neo" nó, không giống như phương thức chuỗi nơi bạn đưa ra một kiểu cho kết quả của 'so sánh (một cách rõ ràng)) '. Bất kể, tôi nghĩ rằng nó sẽ dễ đọc hơn khi viết 'Comparator' của riêng bạn, và chỉ gọi là 'split' một lần. Không có giải thưởng cho việc ép mã vào các dòng ít nhất có thể. – ajb

+1

Nhập mục tiêu không hoạt động thông qua các lời gọi phương thức xích, xem [tại đây] (http://stackoverflow.com/a/28834656/2711488) và [tại đây] (http://stackoverflow.com/a/26883991/2711488) và [ở đây] (http://stackoverflow.com/a/31383947/2711488). Tuy nhiên, bạn chỉ có thể sử dụng 'Comparator.comparing (s -> s.replaceFirst (" \\ s + "," "))' thay vì so sánh hai giai đoạn của bạn và kết quả sẽ giống nhau ... – Holger

+0

'Comparator.comparing ((Chuỗi s) -> s.split ("\\ s +") [0]) .soComparingInt (s -> Integer.parseInt (s.split ("\\ s +") [1])) 'hoạt động nhưng tại sao' String' này là bắt buộc, nó có thể suy ra từ 'Comparator ', nó là một hạn chế trong suy luận kiểu? BTW sử dụng 'phiên bản java" 1.8.0_60 "' – Saravana

Trả lời

2

Java cần biết một loại tất cả các biến. Trong nhiều lambdas nó có thể suy ra một kiểu, nhưng trong đoạn mã đầu tiên của bạn, nó không thể đoán loại s. Tôi nghĩ rằng cách tiêu chuẩn để giải quyết vấn đề đó sẽ được tuyên bố một cách rõ ràng:

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

Nếu bạn nhìn vào this answer, nó có một khai báo kiểu tương tự trong đối số để Comparator.comparing().

Phương pháp của bạn, rõ ràng đưa ra các đối số kiểu của comparing(), rõ ràng là hoạt động.

Đối với phương pháp khác của bạn, khai báo hai bộ so sánh, tôi khá tự tin rằng trong trường hợp này Java có thể suy ra từ String ở phía bên trái của nhiệm vụ, giống như trong thông thường List <String> = new ArrayList<>();. Khi bạn tiếp tục gọi thenComparing() trong cùng một biểu thức, Java không còn có thể thấy rằng loại từ phía bên trái có liên quan. Nó sẽ có một chút giống như int size = new ArrayList<>().size(); Điều này cũng hoạt động:

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]) .soComparingInt (s -> Integer.parseInt (s.split ("\\ s +") [1])) hoạt động nhưng tại sao Chuỗi này là cần thiết, nó có thể suy ra từ Comparator , nó là một hạn chế trong suy luận kiểu? BTW sử dụng phiên bản java "1.8.0_60" – Saravana

+2

Làm cách nào bạn suy ra điều đó? Bạn biết rằng 'thenComparing()' sẽ trả về một 'Comparator ' (để vừa với phía bên trái của phép gán), do đó 'compare()' cần trả về 'Comparator ', do đó 's' cần phải là một 'Chuỗi'. Trình biên dịch không đi qua nhiều bước này của lý luận. Vâng, đó là một hạn chế trong suy luận kiểu, nhưng tôi nghĩ đó là giới hạn được đưa ra vì mục đích khác nếu các quy tắc sẽ trở nên quá phức tạp và các lập trình viên sẽ không hiểu chúng. Đây là dự đoán tốt nhất của tôi. –

+1

Vấn đề lớn nhất là, mục tiêu gõ thông qua chuỗi invocations có thể thay đổi các phương pháp có sẵn cho lời gọi tiếp theo, mà thực sự được sử dụng để xác định loại mục tiêu trước đó, tức là với 'foo (x) .bar (y)', sự trở lại kiểu 'foo (x)' xác định xem có phương thức 'bar (…)' nào không, nhưng việc áp dụng kiểu gõ đích vào 'foo (x)' phụ thuộc vào phương thức 'bar (…)' thực sự đã chọn. – Holger