2015-09-18 12 views
7

Cách tốt nhất để soạn một hàm java FunctionConsumer là gì? Ví dụ: Ví dụ cho một số Function<Object, String> f và một số Consumer<String> c thì thực hiện f.andThen(c) sẽ cảm thấy tự nhiên, tuy nhiên đó không phải là cách giao diện hoạt động.Soạn một hàm Java và người tiêu dùng

Hai tùy chọn tôi thấy là một trong hai thay thế Consumer<String> c với Function<String, Void> c hoặc thay đổi Consumer<String> c-BiConsumer<Function<Object, String>, String> c và làm

accept(Function<Object, String> f, Object o) { 
    String thing = f.apply(o); 
    //do something with thing 
} 

là một trong những tốt hơn so với người kia? Có cách nào tốt hơn?

+0

Bạn có thể cung cấp trường hợp sử dụng cho điều này không? – Tunaki

+0

Tôi muốn viết lớp 'Consumer' cho riêng mình. Nó sẽ mất khoảng 10 dòng mã. –

+1

@Tunaki một trường hợp sử dụng đơn giản sẽ là nếu chúng tôi có một đối tượng mà chúng tôi muốn sắp xếp theo chuỗi khác nhau (chức năng) và sau đó chúng tôi muốn xuất nó ở đâu đó như cơ sở dữ liệu hoặc thiết bị đầu cuối (người tiêu dùng) – kag0

Trả lời

10

Đây có phải là những gì bạn đang cố gắng làm không?

Consumer<Object> composed = o -> c.accept(f.apply(o)); 

Nếu bạn thấy mình phải đối mặt với vấn đề này rất nhiều, bạn có thể tạo ra một phương pháp tĩnh để làm điều này (nhưng nó thực sự giá trị nó?):

static<T,R> Consumer<T> applyAndAccept(Function<? super T,? extends R> f, Consumer<R> c){ 
    return t -> c.accept(f.apply(t)); 
} 
+2

Đôi khi nó có giá trị: bạn có thể sử dụng hai tham chiếu phương pháp mát mẻ thay vì lambda nhàm chán duy nhất. Nếu tham chiếu phương thức của bạn là cá thể ràng buộc và cá thể được lưu trữ trong biến không cuối cùng, thì phiên bản lambda có thể trông thực sự vụng về. Trong bối cảnh này, phương pháp tĩnh được đề xuất của bạn thậm chí còn tốt hơn phương thức mặc định không tồn tại 'vàThen (Consumer)', bởi vì kiểu tham chiếu phương thức sẽ được suy ra tự động. –

+1

@TagirValeev Tôi đồng ý, khả năng sử dụng tham chiếu phương pháp là một điểm cộng lớn. Tôi chỉ không chạy vào 'Function'-'Consumer' tình hình thường xuyên đủ, nhưng có lẽ những người khác làm. Những gì tôi làm bump vào tất cả các thời gian là sự cần thiết để soạn 'Chức năng' và' Predicate'. – Misha

0

không Đây có phải là được thực hiện bằng cách sử dụng mapforEach?

public void test() { 
    Function<Object, String> f = (Object t) -> t.toString(); 
    Consumer<String> c = (String t) -> { 
     System.out.println(t); 
    }; 
    List<Object> data = new ArrayList<>(); 
    data.stream().map(f).forEach(c); 
} 
+1

Về cơ bản, bạn không thực thi bất cứ điều gì, bởi vì luồng của bạn thiếu thao tác đầu cuối. Việc xử lý luồng cũng chỉ là một ví dụ về việc sử dụng 'Consumer'. Chúng cũng có thể hữu ích ở những nơi khác. –

+0

@TagirValeev - Thú vị - thêm '.toArray()' dường như sửa chữa điều đó. – OldCurmudgeon

+2

Đây là hành vi lạm dụng 'peek'. Chỉ cần làm '.map (f) .forEach (c)' hoặc '.map (f) .forEachOrdered (c)' nếu 'c' không phải là thread-safe. – Misha

0

Bạn có thể tạo một bản sao của java.util.function Giao diện giao tiếp trong mã của riêng bạn. Gọi nó là ConsumableFunction và thay đổi tất cả các kiểu tham số phương thức mặc định và trả về các giá trị từ Function thành ConsumableFunction. Sau đó, thêm chức năng mặc định sau đây:

default Consumer<T> atLast(Consumer<R> consumer) { 
    Objects.requireNonNull(consumer); 
    return (T t) -> consumer.accept(apply(t)); 
} 

Bây giờ chúng ta tất cả implmementations Chức năng của bạn thực hiện ConsumableFunction để thay thế. Sau đó, bạn có thể viết mã như sau:

Consumer<A> consumerForA = functionFromAToB 
    .andThen(functionFromBToC) 
    .andThen(functionFromCToD) 
    .atLast(consumerForD); 
Các vấn đề liên quan