2015-05-17 44 views
11

Lần thử đầu tiên của tôi với java 8 luồng ...java 8 - luồng, bản đồ và số khác biệt

Tôi có Giá thầu đối tượng, biểu thị giá thầu của người dùng cho một mặt hàng trong phiên đấu giá. tôi có một danh sách giá thầu và tôi muốn tạo bản đồ tính số lượng người dùng đã đặt giá thầu bao nhiêu (khác biệt).

đây là quan điểm của tôi về nó:

bids.stream() 
     .collect(
      Collectors.groupingBy(
        bid -> Bid::getBidderUserId, 
        mapping(Bid::getAuctionId, Collectors.toSet()) 
      ) 
     ).entrySet().stream().collect(Collectors.toMap(
      e-> e.getKey(),e -> e.getValue().size()) 
     ); 

Nó hoạt động, nhưng tôi cảm thấy như tôi đang lừa dối, nguyên nhân i dòng bộ entry của bản đồ, thay vì thực hiện một thao tác trên dòng đầu tiên. .. phải là một cách chính xác hơn để làm điều này, nhưng tôi không thể hình dung nó ra ...

Cảm ơn

+3

Bạn có thể đưa tuyên bố của bạn về đối tượng giá thầu không? – Nick

Trả lời

15

Bạn có thể thực hiện groupingBy hai lần:

Map<Integer, Map<Integer, Long>> map = bids.stream().collect(
     groupingBy(Bid::getBidderUserId, 
       groupingBy(Bid::getAuctionId, counting()))); 

Bằng cách này, bạn có bao nhiêu giá thầu mà mỗi người dùng có trong mỗi phiên đấu giá. Vì vậy, kích thước của bản đồ nội bộ là số lượng phiên đấu giá mà người dùng đã tham gia. Nếu bạn không cần thông tin bổ sung, bạn có thể thực hiện điều này:

Map<Integer, Integer> map = bids.stream().collect(
     groupingBy(
       Bid::getBidderUserId, 
       collectingAndThen(
         groupingBy(Bid::getAuctionId, counting()), 
         Map::size))); 

Đây chính xác là những gì bạn cần: ánh xạ người dùng đến số người dùng phiên đấu giá đã tham gia.

Cập nhật: có cũng giải pháp tương tự đó là gần gũi hơn với ví dụ của bạn: Câu trả lời

Map<Integer, Integer> map = bids.stream().collect(
     groupingBy(
       Bid::getBidderUserId, 
       collectingAndThen(
         mapping(Bid::getAuctionId, toSet()), 
         Set::size))); 
+1

Đúng, tôi đã xóa nhận xét của mình vì tôi nhận ra đó là những gì bạn vừa thêm vào. Tôi đã đăng bài trước khi suy nghĩ. – Radiodef

+3

Tuyệt vời! đây là chính xác những gì tôi đang tìm kiếm, phương pháp 'collectionsAndThen', mà tôi không thể tìm ra cách sử dụng. Cảm ơn rất nhiều :) – Zemer

0

Tagir Valeev là một trong những quyền (+1). Dưới đây là hình thức bổ sung thực hiện chính xác như vậy bằng cách sử dụng Bộ sưu tập thu gọn của riêng bạn cho nhómBởi:

Map<Integer, Long> map = bids.stream().collect(
       Collectors.groupingBy(Bid::getBidderUserId, 
            new Collector<Bid, Set<Integer>, Long>() { 

     @Override 
     public Supplier<Set<Integer>> supplier() { 
      return HashSet::new; 
     } 

     @Override 
     public BiConsumer<Set<Integer>, Bid> accumulator() { 
      return (s, b) -> s.add(b.getAuctionId()); 
     } 

     @Override 
     public BinaryOperator<Set<Integer>> combiner() { 
      return (s1, s2) -> { 
       s1.addAll(s2); 
       return s1; 
      }; 
     } 

     @Override 
     public Function<Set<Integer>, Long> finisher() { 
      return (s) -> Long.valueOf(s.size()); 
     } 

     @Override 
     public Set<java.util.stream.Collector.Characteristics> characteristics() { 
      return Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH)); 
     } 
    })); 
Các vấn đề liên quan