2014-12-14 40 views
5

Tôi đang bắt đầu sử dụng API 8 luồng java. Tôi muốn chuyển đổi danh sách "tập hợp kết quả sql" thành các đối tượng miền, tức là cấu trúc tổng hợp.Java 8 Streams: xây dựng các đối tượng đa cấp/tổng hợp

Đối tượng miền: người dùng có bộ sưu tập quyền, mỗi quyền có một bộ sưu tập gồm năm ứng dụng. Ví dụ: John có 2 quyền (MODERATOR và DEV). phép người điều hành của nó là chỉ áp dụng cho năm 2014 và 2015 phép dev của nó chỉ có thể áp dụng cho 2014.

class User { 
    // some primitives attributes 
    List<Permission> permission; 
} 

class Permission { 
    // some primitives attributes 
    List<Integer> years; 
} 

Bây giờ tôi thực hiện một truy vấn và nhận được một danh sách các kết quả bằng phẳng, một cái gì đó như:

[1, "moderator", 2014] 
[1, "moderator", 2015] 
[1, "dev", 2014] 
[2, "dev", 2010] 
[2, "dev", 2011] 
[2, "dev", 2012] 

1 và 2 là userId.

Tôi đã thử xây dựng khác nhau nhưng cuối cùng nó phức tạp hơn nhiều so với thông thạo. Và đã không làm việc :)
Tôi đọc trong một cuốn sách Java 8 rằng nó "đơn giản" để xây dựng các đối tượng dompain với người thu gom.
tôi đã khóc một chút khi tôi đọc rằng: '(

tôi đã cố gắng

sb.collect(
    collectingAndThen(
     groupingBy(
      Mybean::getUserId, 
      collectingAndThen(
       groupingBy(Monbean::getPermissionId, mapping(convertPermission, toList())), 
       finisherFonction) 
      ), 
     convertUser) 
); 

và có một địa ngục của thất bại Generics biên soạn

  • cách tốt nhất để xây dựng đa mức hợp là những gì. đối tượng miền bằng cách sử dụng java 8 luồng?
  • là bộ sưu tậpVà/sau đó hoàn thành một ý tưởng hay?
  • hoặc bạn chỉ sử dụng groupingBy theo sau là một hàm ánh xạ?
  • bạn chuyển đổi các phân loại cho một đối tượng (loại chức năng lập bản đồ mức độ đầu tiên?)

Bởi vì vào cuối Tôi muốn thoát khỏi bản đồ và nhận một kết quả List<User> (Tôi nghĩ rằng tôi có thể thêm một bản đồ gọi trên mục nhậpSet để hoàn thành việc chuyển đổi).

+0

"Kết quả căn hộ" của bạn là gì? Mảng của các đối tượng? – mkobit

Trả lời

4

Hãy để tôi cung cấp cho bạn một vài tùy chọn và bạn quyết định giao diện nào rõ ràng nhất với bạn. Tôi giả sử rằng hàm tạo Người dùng là User(int userId, List<Permission> permissions) và hàm tạo Quyền là Permission(String permissionId, List<Integer> years)

Tùy chọn 1: Cách tiếp cận trực tiếp. Nhóm theo userid, xây dựng danh sách quyền cho từng userid và tạo đối tượng User. Cá nhân, tôi thấy điều này làm tổ nhiều trong những người sưu tập khó theo dõi.

List<User> users = beans.stream() 
    .collect(
     groupingBy(
      MyBean::getUserid, 
      collectingAndThen(
       groupingBy(
        MyBean::getPermission, 
        mapping(MyBean::getYear, toList()) 
       ), 
       t -> t.entrySet().stream() 
        .map(e -> new Permission(e.getKey(), e.getValue())) 
        .collect(toList()) 
      ) 
     ) 
    ).entrySet().stream() 
    .map(e -> new User(e.getKey(), e.getValue())) 
    .collect(toList()); 

Tùy chọn 2: Tương tự như trên nhưng làm cho người thu thập quyền riêng biệt để rõ ràng.

Collector<MyBean, ?, List<Permission>> collectPermissions = collectingAndThen(
    groupingBy(MyBean::getPermission, mapping(MyBean::getYear, toList())), 
    t -> t.entrySet().stream() 
     .map(e -> new Permission(e.getKey(), e.getValue())) 
     .collect(toList()) 
); 

List<User> users = beans.stream() 
    .collect(groupingBy(MyBean::getUserid, collectPermissions)) 
    .entrySet().stream() 
    .map(e -> new User(e.getKey(), e.getValue())) 
    .collect(toList()); 

Tùy chọn 3: Đầu tiên cuộn đậu thành bản đồ của userid để lập bản đồ cho phép vào danh sách năm (Map<Integer, Map<String, List<Integer>>). Sau đó, xây dựng các đối tượng miền ra khỏi bản đồ

List<User> users = beans.stream().collect(
    groupingBy(
     MyBean::getUserid, 
     groupingBy(
      MyBean::getPermission, 
      mapping(MyBean::getYear, toList()) 
     ) 
    ) 
).entrySet().stream() 
    .map(u -> new User(
      u.getKey(), 
      u.getValue().entrySet().stream() 
       .map(p -> new Permission(p.getKey(), p.getValue())) 
       .collect(toList()) 
     ) 
    ).collect(toList()); 
+0

Xin chào, Cảm ơn bạn đã trả lời. Tôi chơi với người sưu tầm tối hôm qua và hiểu rõ hơn về API :) Tôi đã không thử giải pháp của bạn nhưng dường như với tôi rằng điều này có thể thực hiện công việc! Xin cảm ơn sự giúp đỡ của bạn. Tôi đồng ý với bạn: lồng nhau groupingBy là khó làm theo và khó viết quá (lỗi loại biên dịch). Nó có vẻ dễ dàng hơn (ít nhất là đối với tôi) để viết các phương pháp chuyển đổi đơn nhất, tạo ra chúng. Tôi sẽ cung cấp cho tùy chọn 3 một thử. Sở thích của bạn là gì? – Archange

+0

Tôi có thể thêm một chút phức tạp: nếu tôi muốn xử lý "giá trị null". Mẫu yêu thích của bạn là gì? ánh xạ tới bộ tích lũy Hashmap mới? thứ gì khác ? Các suecase là người dùng có thể có 0 hoặc n quyền và một giấy phép có thể có 0 hoặc n năm. tạm biệt – Archange

2

Bộ kết hợp collectingAndThen được thiết kế để khi hình thức trung gian tích lũy khác với hình thức cuối cùng mong muốn. Đây là trường hợp của bộ sưu tập joining() (trong đó biểu mẫu trung gian là StringBuilder, nhưng biểu mẫu cuối cùng là String) và cũng có thể được sử dụng để bao bọc các bộ sưu tập có thể thay đổi bằng trình bao bọc không thể thay đổi sau khi quá trình thu thập hoàn tất. Vì vậy, tôi không nghĩ rằng đây là công cụ bạn đang tìm kiếm.

Nếu bạn đang tìm kiếm "quyền truy cập bởi người sử dụng", điều này sẽ làm các trick:

Map<UserId, List<Permission>> 
    queryResults.stream() 
       .collect(qr -> qr.getId(), 
         mapping(qr -> qr.getPermission() + ":" + qr.getDate(), 
           toList())); 

này sẽ cho kết quả:

1 -> [ moderator:2014, moderator:2015, dev:2014 ] 
2 -> [ dev:2010, dev:2011, dev:2012 ] 

Ý tưởng là: - Bạn đang nhóm bởi "id" (trường đầu tiên của truy vấn của bạn) - Đối với mỗi bản ghi, bạn chọn một số chức năng của các trường còn lại (ở đây, tôi đã sử dụng chuỗi ký tự cho rõ ràng, nhưng bạn có thể tạo một đối tượng đang giữ quyền và năm), và gửi rằng đến bộ thu hạ lưu - Sử dụng Bộ sưu tập.toList() làm trình thu thập ở hạ lưu, sau đó sẽ là "giá trị" của Map được tạo bởi groupingBy.

+0

Xin chào, cảm ơn vì bài đăng của bạn. Tôi hiểu câu trả lời này nhưng nó không chính xác những gì tôi đang tìm kiếm. Ở cuối, các giá trị bản đồ không phải là các đối tượng miền tổng hợp. – Archange

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