2017-11-13 21 views
7

chương trình của tôi có dòng này:Đi qua một hàm phi kết hợp để giảm

Function<String, Integer> f = (String s) -> s.chars().reduce(0, (a, b) -> 2 * a + b); 

Chức năng được thông qua để giảm không phải là kết. Tài liệu của Reduce nói rằng hàm được truyền phải là kết hợp.

Làm cách nào tôi có thể viết lại cụm từ này dưới dạng biểu thức không làm giảm hợp đồng giảm?

+3

Bạn không thể. Chỉ cần sử dụng một vòng lặp goold cũ. –

+0

Bạn đang nói về hàm 'f' hoặc' (a, b) -> 2 * a + b'? nếu nó là 'f', tôi nghĩ rằng nó an toàn để sử dụng nó trong bất kỳ luồng song song nào; nếu nó là '(a, b) -> 2', nó cũng sẽ ổn vì tôi không thấy lý do nào để làm:' s.chars(). parallel(). reduce (0, (a, b) - > 2 * a + b) ' –

Trả lời

4

Theo triển khai hiện tại và IFF bạn sẽ không sử dụng song song - bạn an toàn với những gì bạn có ngay bây giờ. Rõ ràng nếu bạn đồng ý với những tuyên bố từ chối trách nhiệm này.

Hoặc bạn rõ ràng có thể tạo ra các chức năng với một vòng lặp for:

Function<String, Integer> f = s -> { 
     int first = s.charAt(0) * 2 + s.charAt(1); 
     int total = first; 

     for (int x = 1; x < s.length() - 1; x++) { 
      total = total * 2 + s.charAt(x + 1); 
     } 

     return total; 

    }; 
+0

Đó thực sự là phần 'đang triển khai hiện tại' làm phiền tôi. Các nhà phát triển Java đã giữ quyền bình yên để thay đổi cách thức hoạt động của nó. –

+0

Thái Bình Dương? Bạn có nghĩa là trái ngược với việc có một cuộc chiến trên nó? –

+0

@NickODell yeah, đó là phần cay đắng. Bạn vẫn có thể tạo ra một 'hàm' trong số đó với một vòng lặp đơn giản (đã chỉnh sửa bài đăng) – Eugene

3

Bạn có thể chuyển đổi chức năng này để một chức năng kết hợp, như được giải thích trong this answer tại ví dụ về List.hashCode(). Sự khác biệt chỉ nằm trong hệ số (2 so với 31) và giá trị bắt đầu (1 so với 0).

Nó có thể được thích nghi với nhiệm vụ của bạn, đó là đặc biệt dễ dàng khi bạn có một đầu vào truy cập ngẫu nhiên giống như một String:

Function<String, Integer> f = 
    s -> IntStream.range(0, s.length()).map(i -> s.charAt(i)<<(s.length()-i-1)).sum(); 

Điều này thậm chí sẽ chạy song song, nhưng nó không chắc rằng bạn đã bao giờ gặp phải như vậy khổng lồ chuỗi mà một đánh giá song song cung cấp một lợi ích. Vì vậy, những gì còn lại, đó là hầu hết mọi người có thể xem xét giải pháp này ít có thể đọc được hơn một for vòng lặp đơn giản ...


Lưu ý rằng giải pháp trên thể hiện một hành vi tràn khác nhau, ví dụ nếu String có hơn 32 char s, do với việc sử dụng toán tử shift thay vì nhân với hai.
Việc sửa chữa cho vấn đề này làm cho các giải pháp hiệu quả hơn:

Function<String, Integer> f = s -> 
    IntStream.range(Math.max(0, s.length()-32), s.length()) 
      .map(i -> s.charAt(i)<<(s.length()-i-1)).sum(); 

Nếu chuỗi có hơn 32 char s, nó chỉ xử lý 32 char s cuối cùng, đó là đã đủ để tính toán kết quả tương tự như chức năng ban đầu của bạn.

+0

Tôi thực sự đang viết một hàm băm - tôi đã cố gắng cung cấp một ví dụ đơn giản, khép kín. Cảm ơn bạn đã liên kết đến câu hỏi khác - Tôi nghĩ rằng tôi đã tìm kiếm các bản sao đủ tốt, nhưng dường như không. –

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