2011-04-26 35 views
5

Tôi đã đọc một bài viết về Joel On Software về ý tưởng sử dụng các hàm bậc cao hơn để đơn giản hóa rất nhiều mã thông qua việc sử dụng bản đồ và giảm. Ông đã đề cập rằng điều này rất khó thực hiện trong Java. Bài viết: http://www.joelonsoftware.com/items/2006/08/01.htmlLàm cách nào để viết một hàm bậc cao hơn như bản đồ, hoặc giảm bớt trong java?

các ví dụ từ bài viết dưới đây, vòng qua một mảng, và sử dụng hàm fn đã được thông qua như là một cuộc tranh cãi trên mỗi phần tử trong mảng:

function map(fn, a) 
{ 
    for (i = 0; i < a.length; i++) 
    { 
     a[i] = fn(a[i]); 
    } 
} 

này sẽ được gọi tương tự vào thực tế dưới đây:

map(function(x){return x*2;}, a); 
map(alert, a); 

Lý tưởng tôi muốn viết chức năng bản đồ để hoạt động trên mảng hoặc Bộ sưu tập của bất kỳ loại nào nếu có thể.

Tôi đã tìm kiếm trên Internet và tôi gặp khó khăn khi tìm tài nguyên về chủ đề này. Thứ nhất, là các hàm ẩn danh có thể có trong java? Điều này có thể làm theo cách khác không? Nó sẽ có sẵn trong một phiên bản tương lai của java? Nếu có thể, làm thế nào tôi có thể làm điều đó? Tôi tưởng tượng rằng nếu điều này là không thể trong Java thì có một số loại 'mẫu'/kỹ thuật mà mọi người sử dụng để đạt được hiệu quả tương tự, như tôi tưởng tượng các hàm ẩn danh là một công cụ rất mạnh trong thế giới phần mềm. câu hỏi tương tự duy nhất tôi có thể tìm thấy là: Java generics - implementing higher order functions like map và nó hoàn toàn không có ý nghĩa với tôi.

Trả lời

6

Guava cung cấp bản đồ (nhưng nó được gọi là transform thay vào đó, và đang trong lớp tiện ích như ListsCollections2). Nó không cung cấp gấp/giảm, tuy nhiên.

Trong mọi trường hợp, cú pháp để sử dụng transform cảm thấy thực sự khó khăn khi sử dụng map trong Đề án. Nó giống như đang cố gắng viết bằng tay trái của bạn, nếu bạn thuận tay phải. Nhưng, đây là Java; bạn mong chờ điều gì. :-P

3

Các lớp ẩn danh của phương thức đơn lẻ cung cấp một cách tương tự, nhưng tiết kiệm hơn, cách viết một hàm ẩn danh trong Java. Ví dụ, bạn có thể có:

Iterable<Source> foos = ...; 
Iterable<Destination> mappedFoos = foos.map(new Function<Source, Destination>() 
{ 
    public Destination apply(Source item) { return ... } 
}); 

Đối với một ví dụ về một thư viện Java với một phong cách chức năng, xem Guava

+1

Thực tế dường như nếu/khi Java cuối cùng nhận được các biểu thức lambda, chúng sẽ được chuyển đổi thành một lớp ẩn danh như vậy. – hammar

2
interface Func<V,A> { 
    V call (A a); 
} 

static <V,A> List<V> map (Func<V,A> func, List<A> as) { 
    List<V> vs = new ArrayList<V>(as.size()); 
    for (A a : as) { 
     Vs.add(func.call(a)); 
    } 
    return vs; 
} 
0

Paguro has an open-source implementation of higher order functions. Thử nghiệm ban đầu cho thấy nó là 98% nhanh như vòng lặp forEach Java nguyên gốc. Các hoạt động mà nó hỗ trợ được áp dụng lazily mà không sửa đổi bộ sưu tập cơ bản. Nó xuất ra các phiên bản kiểu an toàn của các bộ sưu tập Clojure không thay đổi (và đôi khi có thể thay đổi). Transformable is built into Paguro's unmodifiable and immutable collections and interfaces. Để sử dụng một bộ sưu tập java.util thô làm đầu vào, chỉ cần bọc nó với hàm xform().

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