2015-05-17 11 views
11

मेरा पहला प्रयास गिनती ...जावा 8 - धारा, नक्शा और जावा 8 धाराओं के साथ अलग

मैंने किसी चीज़ बोली है, जो एक नीलामी में एक आइटम के लिए एक उपयोगकर्ता की बोली का प्रतिनिधित्व करता है। मेरे पास बोलियों की एक सूची है, और मैं एक नक्शा बनाना चाहता हूं जो इस बात की गणना करता है कि उपयोगकर्ता ने बोली कितनी (विशिष्ट) नीलामी की है।

इस इस पर मेरी ले है:

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

यह काम करता है, लेकिन मुझे लगता है जैसे मैं धोखा दे रहा हूँ, क्योंकि मैं नक्शा के प्रवेश सेट स्ट्रीम, बजाय प्रारंभिक धारा पर एक हेरफेर करने का। .. ऐसा करने का एक और अधिक सही तरीका होना चाहिए, लेकिन मैं इसे समझ नहीं सकता है ...

धन्यवाद

+3

क्या आप बोलियां ऑब्जेक्ट की अपनी घोषणा शामिल कर सकते हैं? – Nick

उत्तर

15

आप groupingBy दो बार प्रदर्शन कर सकते हैं:

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

इस तरह आपके पास प्रत्येक नीलामी में प्रत्येक उपयोगकर्ता की कितनी बोलियां हैं। तो आंतरिक मानचित्र का आकार उपयोगकर्ता द्वारा भाग लेने वाली नीलामी की संख्या है। आप अतिरिक्त जानकारी की जरूरत नहीं है, तो आप ऐसा कर सकते हैं:

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

यह आपको वास्तव में क्या जरूरत है: उपयोगकर्ताओं की मैपिंग की नीलामी उपयोगकर्ता की संख्या भाग लिया।

अद्यतन: वहाँ भी है समान समाधान जो अपने उदाहरण के करीब है:

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

हाँ मैंने अपनी टिप्पणी हटा दी क्योंकि मुझे एहसास हुआ कि यह वही होना चाहिए जो आपने अभी जोड़ा है। मैं सोचने से पहले पोस्ट कर रहा था। – Radiodef

+3

बढ़िया! यह वही है जो मैं ढूंढ रहा था, 'संग्रह और फिर' विधि, जिसे मैं समझ नहीं पाया कि इसका उपयोग कैसे किया जाए। बहुत बहुत धन्यवाद :) – Zemer

0

Tagir Valeev के जवाब सही एक (+1) है। यहां एक अतिरिक्त व्यक्ति है जो समूह के लिए अपने स्वयं के डाउनस्ट्रीम कलेक्टर का उपयोग कर बिल्कुल वही करता है:

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