2016-04-03 17 views
12

Nhiều lambdas cho giao diện Function mang hình thứcChuyển đổi Người tiêu dùng đến chức năng

t -> { 
    // do something to t 
    return t; 
} 

Tôi làm điều này vì vậy thường xuyên mà tôi đã viết một phương pháp để nó như thế này.

static <T> Function<T, T> consumeThenReturn(Consumer<T> consumer) { 
    return t -> { 
     consumer.accept(t); 
     return t; 
    }; 
} 

Điều này cho phép tôi làm điều thật sự tốt đẹp như thế này:

IntStream.rangeClosed('A', 'Z') 
     .mapToObj(a -> (char) a) 
     .collect(Collectors.collectingAndThen(Collectors.toList(), consumeThenReturn(Collections::shuffle))) 
     .forEach(System.out::print); 

Có một cách khác để làm chuyển đổi như thế này mà không dựa vào phương pháp của riêng tôi? Có bất cứ điều gì trong các API mới tôi đã bỏ lỡ mà làm cho phương pháp của tôi thừa?

+4

Tôi không nghĩ là có: hãy xem mã 'Collectors.toList()' chẳng hạn, nó có '(trái, phải) -> {left.addAll (phải); trở về bên trái; }, '. Đó là vấn đề của các phương thức thay đổi đối số của chúng ... (side-note, bạn có thể có 'UnaryOperator ' thay vì 'Function ') – Tunaki

+3

Tôi sẽ đổi tên hàm thành ['tee'] (https: //en.wikipedia .org/wiki/Tee_ (lệnh)). – dasblinkenlight

+0

Mọi thứ đã được nói, nhưng tôi đang làm việc trên một cái gì đó đã làm điều này. https://github.com/TouK/ThrowingFunction/ bất kỳ đầu vào nào được đánh giá cao –

Trả lời

6

Có nhiều phương pháp có khả năng hữu ích có thể được thêm vào giao diện Function, ConsumerSupplier. Bạn đưa ra một ví dụ điển hình (chuyển đổi một số Consumer thành Function) nhưng có nhiều chuyển đổi hoặc tiện ích tiềm năng khác có thể được thêm vào. Ví dụ: sử dụng Function làm Consumer (bằng cách bỏ qua giá trị trả lại) hoặc dưới dạng Supplier (bằng cách cung cấp giá trị đầu vào). Hoặc chuyển đổi một số BiFunction thành Function bằng cách cung cấp một trong hai giá trị. Tất nhiên, tất cả những điều này có thể được thực hiện thủ công bằng mã hoặc được cung cấp thông qua các chức năng tiện ích như bạn đã chỉ ra nhưng có thể coi là có giá trị để có các cơ chế tiêu chuẩn hóa trong API, như tồn tại trong nhiều ngôn ngữ khác.

Đó là suy đoán về phía tôi, nhưng tôi đoán điều này phản ánh mong muốn của các nhà thiết kế ngôn ngữ muốn rời khỏi API càng sạch càng tốt. Tuy nhiên, tôi bị hấp dẫn bởi sự tương phản (ví dụ) với tập hợp rất phong phú của các tiện ích được cung cấp bởi ngôn ngữ để đảo ngược các đơn đặt hàng, so sánh với một số tiêu chí, xử lý các giá trị null, vv. nhưng đã được API cung cấp. Tôi muốn được nghe từ một trong những nhà thiết kế ngôn ngữ tại sao các phương pháp tiếp cận các giao diện này dường như không nhất quán.

+0

Điểm tuyệt vời về nội dung mới cho 'Trình so sánh'.Bạn có thể đã xử lý một 'Hàm' như là một' Consumer' mặc dù chỉ bằng cách truyền 'hàm :: apply'. Tôi đoán bỏ qua giá trị trả về hơi lạ hơn là trả lại đối số đầu tiên khi không có giá trị trả về. –

+3

Một ví dụ khác có vẻ là 'CompletableFuture', lần cuối tôi kiểm tra nó chứa gần 60 phương pháp ... –

+1

Bạn phải xem xét rằng Comparator là một giao diện cũ đã phát triển theo thời gian. Các java8 otoh là phiên bản đầu tiên với các giao diện chức năng. – the8472

0

Bộ sưu tập của Apache commons 4.x có những gì bạn đang tìm kiếm, tôi nghĩ vậy. tương đương của nó đối với FunctionConsumerTransformerClosure, tương ứng, và nó cung cấp một cách để soạn chúng bằng cách sử ClosureTransformer

Đó là tầm thường để chuyển đổi giữa các loại chức năng tương đương bằng cách gọi các SAM của một và gán nó vào người kia. Đưa nó tất cả cùng nhau, bạn có thể kết thúc với một Java 8 Function theo cách này:

Consumer<String> c = System.out::println; 
Function<String,String> f = ClosureTransformer.closureTransformer(c::accept)::transform; 

c::accept chuyển đổi Java 8 Consumer đến một tương đương Apache Commons 4 Closure, và trận chung kết ::transform chuyển đổi Apache Commons 4 Transformer để một Java tương đương 8 Function.

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