2016-07-30 32 views
5

Tôi có điều này mã ví dụ mà tôi đã viết riêng cho câu hỏi này, nhưng nó phản ánh một kịch bản thực sự tôi đã phải đối mặt với tại nơi làm việc:biểu thức Lambda với các biến số bất biến bên ngoài được sử dụng trong các biểu hiện

List<String> names = Arrays.asList("ALICE", "Alice", "BOB", "Bob", "CHUCK", "Chuck"); 

Predicate<String> has_u_or_i_whenLowercased = Stream.of("u", "i") 
     .map(bit -> (Predicate<String>) (source -> source.toLowerCase(Locale.ENGLISH).contains(bit))) 
     .reduce(Predicate::or) 
     .orElse(p -> false); 

List<String> english = names.stream() 
     .filter(has_u_or_i_whenLowercased) 
     .collect(Collectors.toList()); 
System.out.println(english); 
System.out.println(english.size()); 

Nó tạo một vị ngữ kiểm tra xem chuỗi nguồn có chứa u hoặc i khi thấp hơn với ngôn ngữ tiếng Anh (EDIT:Có một tá cách tốt hơn và đơn giản hơn để thực hiện việc này, nhưng đây chỉ là một ví dụ. một tập dữ liệu nhỏ dựa trên số lượng tiêu chí tìm kiếm tùy ý). Tôi sẽ sử dụng biểu thức lambda này trên một số phương thức của một lớp.

Bây giờ, giả sử tôi muốn có một miền địa phương khác, sẽ được chuyển làm đối số cho phương thức sẽ sử dụng biểu thức lambda (không phải hàm tạo). Tại nơi làm việc, nó không phải là một miền địa phương tôi phải đối phó với, nhưng tôi đã xác định ranh giới của nó như là một biến bất biến.

Giải pháp đơn giản nhất tôi có thể nghĩ là có phương pháp "xây dựng" biểu thức lambda đó.

@Override 
public void run() { 
    List<String> names = Arrays.asList("ALICE", "Alice", "BOB", "Bob", "CHUCK", "Chuck"); 

    List<String> english = names.stream() 
      .filter(createUIPredicate(Locale.ENGLISH)) 
      .collect(Collectors.toList()); 
    System.out.println(english); 
    System.out.println(english.size()); 

    System.out.println("--"); 

    List<String> turkish = names.stream() 
      .filter(createUIPredicate(new Locale("tr", "TR"))) 
      .collect(Collectors.toList()); 
    System.out.println(turkish); 
    System.out.println(turkish.size()); 
} 

private Predicate<String> createUIPredicate(Locale locale) { 
    return Stream.of("u", "i") 
      .map(bit -> (Predicate<String>) (source -> source.toLowerCase(locale).contains(bit))) 
      .reduce(Predicate::or) 
      .orElse(p -> false); 
} 

Tuy nhiên tôi cảm thấy có điều gì đó sai trái với cách tiếp cận này. Nếu tôi tiêm một biến bất biến bên ngoài vào một giao diện chức năng, tôi nghĩ có lẽ tôi phải chuyển nó như một đối số biểu thức lambda thay vào đâu đó?

Khi đối mặt với biểu thức lambda có biến không thay đổi bên ngoài được sử dụng trong biểu thức và biến bất biến có thể khác nhau cho mỗi lần sử dụng trong luồng hoạt động trung gian, có cách tiếp cận cụ thể nào khớp với mẫu lập trình chức năng đã biết không?

+2

Việc triển khai cho Predicate là quá mức cần thiết và không được sử dụng bất kỳ nội dung nào của 'Stream'. Nó có thể đơn giản là 's -> Pattern.compile (". * U | i. * "). Khớp (s.toLowerCase (miền địa phương))'. MUCH dễ hiểu hơn và lý do. – Clashsoft

+0

@Clashsoft '' ". * [UIui]. *" '' Thậm chí còn dễ dàng hơn. – f1sh

+0

Bạn có ý gì bằng cách "chuyển nó thành đối số biểu thức lambda"? Tôi nghĩ rằng giải pháp của bạn là hoàn toàn hợp lý. (Nhưng một chút quá liều trong các khía cạnh khác như bình luận khác đã chỉ ra trước). Chắc chắn bạn có thể đơn giản hóa toàn bộ thứ bằng cách đóng gói mọi thứ vào một phương thức và gọi nó như sau: 'List turkish = filterUI (tên, locale mới (" tr "," TR "))' – martinhh

Trả lời

1

Không có sự khác biệt thực sự nhiều giữa giải pháp phương pháp của bạn và giải pháp lambda của bạn từ các nhận xét, cả hai tận dụng lợi thế của lambdas "đóng cửa" "có hiệu quả cuối cùng" biến. Cả hai đều khá phổ biến trong mã hàm Java 8 mà tôi đã viết.

private Predicate<String> build(Locale locale) { 
    return str -> str.toLowerCase(locale); 
} 

so:

Function<Locale, Predicate<String>> build = locale -> str -> str.toLowerCase(locale); 

Quyết định giữa hai chỉ là một trong những sở thích phong cách và/hay xây dựng được sử dụng chỉ trong vòng một phương pháp đơn hoặc ở nhiều nơi trong lớp học của bạn.

Các vấn đề liên quan