2015-09-23 8 views
5

का उपयोग करते समय एकाधिक स्ट्रीमिंग से बचने के लिए मेरे पास jooq के साथ डेटाबेस से पूछताछ करने और स्ट्रीम के साथ परिणाम संसाधित करने का एक संयोजन है। हालांकि मुझे लगता है कि मेरा कोड बहुत पठनीय नहीं है और पर्याप्त संक्षेप में नहीं है। मैं अपने इरादे को बेहतर तरीके से व्यक्त करने के तरीके में अपना कोड कैसे सुधार सकता हूं।संग्रह

sql 
    .select(field("USER_NAME", String.class)) 
    .from(table("CWD_USER")) 
    .fetch() 
    .stream() 
    .map(f -> f.getValue(field("USER_NAME", String.class))) 
    .collect(Collectors.groupingBy(s -> StringUtils.split(s, "-")[0], Collectors.counting())) 
    .entrySet().stream() 
    .sorted(new java.util.Comparator<Entry<String, Long>>() { 
     @Override 
     public int compare(Entry<String, Long> o1, 
       Entry<String, Long> o2) { 
      return o2.getValue().compareTo(o1.getValue()); 
     } 
    }) 
    .forEach(e -> System.out.println(String.format("%13s: %3d", e.getKey(), e.getValue()))); 

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

+3

यहां तक ​​कि अगर आप के अस्तित्व को पता नहीं है [ 'Map.Entry.comparingByValue (...) '] (http://docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html#comparingByValue--), मुझे नहीं लगता कि आपको क्यों लगता है कि आपको इसका उपयोग करना है 'तुलनाकर्ता' के लिए आंतरिक वर्ग, जैसा कि आप पहले से ही अपने कोड के अन्य स्थानों पर लैम्ब्डा अभिव्यक्तियों को जान चुके हैं। – Holger

+1

बस संदर्भ के लिए, संबंधित लैम्ब्डा '.sorted ((o1, o2) -> o2.getValue() तुलना करें। (O1.getValue()))'। @ होल्गर को इंगित करने के लिए धन्यवाद। –

+0

'मैं पहली बार jooq से परिणाम स्ट्रीम करता हूं तो मैं एकत्रित मानचित्र को स्ट्रीम करता हूं' - नहीं। आप परिणामों को jooq से स्ट्रीम करते हैं और यही वह है। आपके उदाहरण में दिखाए गए कोई अतिरिक्त स्ट्रीम नहीं हैं, कुछ इंटरमीडिएट ऑपरेशंस और वास्तव में एक टर्मिनल ऑपरेशन वाला एक एकल स्ट्रीम है। यह बताता है कि धाराएं कैसे काम करती हैं। यदि आप धाराओं की मूल कार्यक्षमता से "बचें" चाहते हैं तो आपको क्लासिक फोरैच/के लिए/loops - loops का उपयोग करने की आवश्यकता है। लेकिन ईमानदारी से: यह एक डाउनग्रेड होगा ... धाराएं बहुत संक्षिप्त और सुंदर हैं - आपका स्वयं का कोड इसका प्रदर्शन करता है। समान कार्यक्षमता के बिना स्ट्रीम के कम से कम 100 लाइनों की आवश्यकता होगी। – specializt

उत्तर

5

मैं JOOQ भाग के बारे में नहीं कह सकता, लेकिन स्ट्रीम एपीआई भाग ठीक दिखता है। सॉर्टिंग से पहले गणनाओं को जानने के लिए आपको मध्यस्थ रूप से एकत्र करना होगा। ध्यान दें कि इस तरह के तुलनित्र पहले से ही जेडीके में लागू किया गया है: यह Map.Entry.comparingByValue() है। आप (उलटे क्रम में सॉर्ट करने के लिए Comparator.reverseOrder() पैरामीटर जोड़ने) का उपयोग कर सकते यह: जब तक यह एक अधिक जटिल क्वेरी की एक काफी सरल संस्करण है

sql 
    .select(field("USER_NAME", String.class)) 
    .from(table("CWD_USER")) 
    .fetch() 
    .stream() 
    .map(f -> f.getValue(field("USER_NAME", String.class))) 
    .collect(Collectors.groupingBy(s -> StringUtils.split(s, "-")[0], Collectors.counting())) 
    .entrySet().stream() 
    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) 
    .forEach(e -> System.out.println(String.format("%13s: %3d", e.getKey(), e.getValue()))); 
2

, मैं एसक्यूएल करने के लिए सभी तर्क के लिए कदम होगा। बराबर SQL क्वेरी (Oracle बोली का उपयोग) है:

SELECT PREFIX, COUNT(*) 
FROM (
    SELECT SUBSTR(USER_NAME, 1, INSTR(USER_NAME, '-') - 1) AS PREFIX 
    FROM CWD_USER 
) T 
GROUP BY PREFIX 
ORDER BY COUNT(*) 

या, jOOQ साथ:

sql.select(field("PREFIX", String.class), count()) 
    .from(
    select(substring(
     field("USER_NAME", String.class), 
     inline(1), 
     position(field("USER_NAME", String.class), inline("-")).sub(inline(1)) 
    ).as("PREFIX")) 
    .from(table("CWD_USER")) 
    ) 
    .groupBy(field("PREFIX", String.class)) 
    .orderBy(count()) 
    .fetch(); 
संबंधित मुद्दे