2015-05-17 66 views
11

ilk denemesi saymak ...java 8 - dere, harita ve java 8 akışları ile ayrı

Ben bir açık artırmada bir öğe için bir kullanıcının bir teklifi temsil bir nesne Teklif var. Teklifler listem var ve kullanıcının bir teklifte kaç (açık) ihalede bulunduğunu gösteren bir harita oluşturmak istiyorum.

bu onun almak benim:

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()) 
     ); 

O inşaat, ama hile gibi ben haritanın giriş setleri akışı neden ben yerine ilk akışınızda bir manipülasyon yapmanın, hissediyorum. .. bunu yapmanın daha doğru bir yol olmalı, ama ... onu anlamaya

Teşekkür

+3

Tekliflerinizin beyanını ekleyebilir misiniz? – Nick

cevap

15

iki kez groupingBy gerçekleştirebilirsiniz olamazdı:

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

Bu şekilde, her kullanıcının her açık artırmada kaç tane teklifi vardır. Dolayısıyla dahili haritanın boyutu, kullanıcının katıldığı açık artırmaların sayısıdır. Daha fazla bilgiye ihtiyacınız yoksa, bunu yapabilirsiniz:

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

Bu tam olarak neye ihtiyacınız olduğunu: kullanıcıların eşleştirmesini için müzayedeler kullanıcı sayısı katıldı.

Güncelleme: sizin örnek daha yakın olan benzer bir çözüm de var:

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

Evet, yorum ekledim, çünkü eklediklerinizin olması gerektiğini anladım. Düşünmeden önce yayın yapıyordum. – Radiodef

+3

Mükemmel! Bu tam olarak ne aradığımı, nasıl kullanılacağını anlayamadığım "collectingAndThen" yöntemidir. Çok teşekkürler :) – Zemer

0

Tagir Valeev cevabı doğru bir (1) 'dir. İşte tam olarak aynı işi yapan bir Collector for the groupBy:

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)); 
     } 
    }));