2015-03-28 29 views
7

Tôi sẽ thông qua các biểu thức lambda trong java 8java biểu 8 lambda cho FilenameFilter

khi tôi đã thay đổi mã của thread nó làm việc tốt

new Thread(new Runnable() { 
    @Override 
    public void run() { 
     System.out.println("run"); 
    } 
}).start(); 

được chuyển thành biểu thức lambda như

new Thread(
    () -> System.out.println("Hello from thread") 
).start(); 

Nhưng tôi không thể chuyển đổi Biểu thức FilenameFilter

File file = new File("/home/text/xyz.txt"); 
file.list(new FilenameFilter() { 
    @Override 
    public boolean accept(File dir, String name) { 
     name.endsWith(".txt"); 
     return false; 
    } 
}); 

và không thành công chuyển đổi sang này như

file.list(new FilenameFilter() { 
    (File a1, String a2) -> { 
     return false; 
    } 
}); 

nó đem lại cho lỗi như trong nhật thực như

Nhiều dấu tại dòng này
- Cú pháp lỗi, chèn ";" để hoàn thành Bản Tuyên Bố
- Cú pháp lỗi, chèn "}" để hoàn thành khối
- Lỗi cú pháp, chèn "AssignmentOperator Expression" để hoàn thành Phân

+1

Tại sao nên sử dụng 'Tệp' nếu bạn sử dụng Java 8? Tại sao không java.nio.file? – fge

+0

Bạn nên chấp nhận câu trả lời, để biết rằng vấn đề đã được giải quyết ... – lodo

+0

nhờ @lodo để trả lời – SarthAk

Trả lời

31

Trước tiên, định dạng của bạn là khủng khiếp, sắp xếp nó ra!

Bây giờ, cú pháp lambda; để chuyển đổi các lớp nặc danh:

final FilenameFilter filter = new FilenameFilter() { 
    @Override 
    public boolean accept(File dir, String name) { 
     return false; 
    } 
}; 

Chúng ta bắt đầu bằng cách thay thế lớp nặc danh với một lambda tương đương đối với phương pháp đơn accept(File dir, String name):

final FilenameFilter filter = (File dir, String name) -> { 
    return false; 
}; 

Nhưng chúng ta có thể làm tốt hơn, chúng tôi không cần phải xác định các loại - trình biên dịch có thể làm việc những điều đó:

final FilenameFilter filter = (dir, name) -> { 
    return false; 
}; 

Và chúng tôi vẫn có thể làm tốt hơn, khi phương thức trả về boolean; nếu chúng ta có một tuyên bố duy nhất để đánh giá một boolean chúng ta có thể bỏ qua return và niềng răng:

final FilenameFilter filter = (dir, name) -> false; 

Đây có thể là bất kỳ tuyên bố, ví dụ:

final FilenameFilter filter = (dir, name) -> !dir.isDirectory() && name.toLowerCase().endsWith(".txt"); 

Tuy nhiên, File API là rất cũ, do đó, không sử dụng nó. Sử dụng nio API. Điều này đã được khoảng từ Java 7 năm 2011 do đó thực sự là không cớ:

final Path p = Paths.get("/", "home", "text", "xyz.txt"); 
final DirectoryStream.Filter<Path> f = path -> false; 
try (final DirectoryStream<Path> stream = Files.newDirectoryStream(p, f)) { 
    stream.forEach(System.out::println); 
} 

Và trên thực tế ví dụ bạn có một phương pháp cụ thể xây dựng thành Files rằng takes a Glob:

final Path p = Paths.get("/", "home", "text", "xyz.txt"); 
try (final DirectoryStream<Path> stream = Files.newDirectoryStream(p, "*.txt")) { 
    stream.forEach(System.out::println); 
} 

Hoặc, sử dụng hiện đại hơn Files.list:

final Path p = Paths.get("/", "home", "text", "xyz.txt"); 
final PathMatcher filter = p.getFileSystem().getPathMatcher("glob:*.txt"); 
try (final Stream<Path> stream = Files.list(p)) { 
    stream.filter(filter::matches) 
      .forEach(System.out::println); 
} 

Ở đây filter::matches là phương pháp tham chiếu e vì phương pháp PathMatcher.matches có thể được sử dụng để triển khai giao diện chức năng Predicate<Path> vì phải mất Path và trả về một boolean.


Là một sang một bên:

f.list(new FilenameFilter() { 

    @Override 
    public boolean accept(File dir, String name) { 
     name.endsWith(".txt"); 
     return false; 
    } 
}); 

Điều này làm cho không có ý nghĩa ...

+0

Bất kỳ lý do nào đằng sau việc không sử dụng API 'File' chỉ vì nó cũ? –

+2

@citizenconn đầu tiên và quan trọng nhất; API 'File' có báo cáo lỗi không đáng kể, hầu hết các phương thức trả về một' boolean', để lại nó cho bạn để tìm ra lý do tại sao một thao tác thất bại. Các vấn đề khác là thiếu tính năng, API NIO có một số lượng lớn các chức năng tiện ích cho hầu hết mọi thứ. Cuối cùng, thực sự _reading_ từ các tệp sử dụng API cũ là tiết và lỗi - NIO đơn giản hóa toàn bộ quá trình, ví dụ bộ mã mặc định là UTF-8 thay vì bất kỳ nền tảng hiện tại nào của bạn quyết định. Và đó là chỉ cho người mới bắt đầu ... –

2

Bạn không cần phải đặt tên lớp, nếu bạn sử dụng một lambda-biểu:

f.list(
    (File a1, String a2) -> { 
     return false; } 
    ); 

trong thực tế, trong ví dụ đầu tiên của bạn, bạn bỏ qua new Runnable().

+0

Định dạng này không kém phần kinh khủng và câu trả lời là _almost_ sai. –

5

Nó phải là đơn giản:

f.list((File a1, String a2) -> {return false;}); 

hoặc thậm chí:

f.list((a1,a2) -> {return false;}); 

Biểu thức lambda thay thế instantiation của các cá thể của lớp trừu tượng.

+3

Hoặc thậm chí '(tệp, n) -> sai'. Không có lý do gì để sử dụng một khối. –

2

FileNameFilter là một giao diện chức năng. Bạn không cần phải làm rõ nó một cách rõ ràng.

f.list((dir, name) -> name.endsWith(".txt")); 

Lưu ý rằng, f phải là một thư mục, không phải là tệp như trong ví dụ của bạn. Ví dụ của bạn nơi f1 là một tệp sẽ trả về null với bộ lọc được chỉ định.

+0

Chính xác giải pháp một dòng mà tôi đã tìm kiếm khi tôi tìm thấy "java 8 lambda biểu hiện cho FilenameFilter" trang. Cảm ơn bạn. – jschreiner

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