जावा में संग्रह से वितरण की गणना करें

संख्याओं के संग्रह (या जिन वस्तुओं के फ़ील्ड का आप निरीक्षण करना चाहते हैं) को उन संख्याओं के वितरण में बदलना एक सामान्य सांख्यिकीय तकनीक है, और रिपोर्टिंग और डेटा-संचालित अनुप्रयोगों में विभिन्न संदर्भों में कार्यरत है।

एक संग्रह दिया:

1, 1, 2, 1, 2, 3, 1, 4, 5, 1, 3

आप एक गणना (प्रत्येक तत्व की आवृत्ति) के रूप में उनके वितरण का निरीक्षण कर सकते हैं, और परिणामों को मानचित्र में संग्रहीत कर सकते हैं:

{
"1": 5,
"2": 2,
"3": 2,
"4": 1,
"5": 1
}

या आप कर सकते हो मानक के अनुसार करना मानों की कुल संख्या के आधार पर मान - इस प्रकार उन्हें प्रतिशत में व्यक्त करते हैं:

{
"1": 0.45,
"2": 0.18,
"3": 0.18,
"4": 0.09,
"5": 0.09
}

या इन प्रतिशतों को a . में भी व्यक्त करें 0..100 के बजाय प्रारूप 0..1 प्रारूप.

इस गाइड में, हम देखेंगे कि आप संग्रह से वितरण की गणना कैसे कर सकते हैं - दोनों आदिम प्रकारों और ऑब्जेक्ट्स का उपयोग करके जिनके फ़ील्ड आप अपने आवेदन में रिपोर्ट करना चाहते हैं।

जावा में कार्यात्मक प्रोग्रामिंग समर्थन के अतिरिक्त - वितरण की गणना करना पहले से कहीं ज्यादा आसान है। हम संख्याओं के संग्रह और के संग्रह के साथ काम करेंगे Books:

public class Book {

    private String id;
    private String name;
    private String author;
    private long pageNumber;
    private long publishedYear;

   
}

जावा में संग्रह के वितरण की गणना करें

आइए पहले देखें कि आप आदिम प्रकारों के लिए वितरण की गणना कैसे कर सकते हैं। वस्तुओं के साथ काम करने से आप गणनाओं में अधिक लचीलापन प्रदान करने के लिए अपने डोमेन वर्गों से कस्टम विधियों को कॉल कर सकते हैं।

डिफ़ॉल्ट रूप से, हम प्रतिशत को से दुगने के रूप में प्रदर्शित करेंगे 0.00 सेवा मेरे 100.00.

आदिम प्रकार

आइए पूर्णांकों की एक सूची बनाएं और उनके वितरण को प्रिंट करें:

List integerList = List.of(1, 1, 2, 1, 2, 3, 1, 4, 5, 1, 3);
System.out.println(calculateIntegerDistribution(integerList));

वितरण की गणना इस प्रकार की जाती है:

public static Map calculateIntegerDistribution(List list) {
    return list.stream()
            .collect(Collectors.groupingBy(Integer::intValue,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.2f", count * 100.00 / list.size()))))));
}

यह विधि एक सूची को स्वीकार करती है और इसे स्ट्रीम करती है। स्ट्रीम करते समय, मान हैं द्वारा समूहीकृत उनका पूर्णांक मान - और उनके मान हैं गिना हुआ का उपयोग Collectors.counting(), a . में एकत्रित होने से पहले Map जहाँ कुंजियाँ इनपुट मानों का प्रतिनिधित्व करती हैं और युगल वितरण में उनके प्रतिशत का प्रतिनिधित्व करते हैं।

यहाँ प्रमुख विधियाँ हैं collect() जो स्वीकार करता है दो संग्राहक. की-कलेक्टर केवल प्रमुख मानों (इनपुट तत्वों) द्वारा समूहीकृत करके एकत्र करता है। मूल्य-संग्राहक के माध्यम से एकत्र करता है collectingAndThen() विधि, जो हमें करने की अनुमति देता है मूल्यों की गणना करें और फिर उन्हें किसी अन्य प्रारूप में प्रारूपित करें, जैसे कि count * 100.00 / list.size() जो हमें गिने हुए तत्वों को प्रतिशत में व्यक्त करने देता है:

{1=45.45, 2=18.18, 3=18.18, 4=9.09, 5=9.09}

मूल्य या कुंजी द्वारा वितरण क्रमबद्ध करें

वितरण बनाते समय - आप आमतौर पर मानों को क्रमबद्ध करना चाहेंगे। अधिक बार नहीं, यह द्वारा होगा कुंजी. जावा HashMaps प्रविष्टि के आदेश को संरक्षित करने की गारंटी न दें, तो हमें a . का उपयोग करना होगा LinkedHashMap जो करता है। इसके अतिरिक्त, मानचित्र को फिर से स्ट्रीम करना और इसे अभी फिर से एकत्र करना सबसे आसान है क्योंकि यह बहुत छोटा आकार और बहुत अधिक प्रबंधनीय है।

पिछला ऑपरेशन कई हज़ार रिकॉर्ड्स को छोटे मानचित्रों में जल्दी से संक्षिप्त कर सकता है, जो आपके द्वारा काम की जाने वाली कुंजियों की संख्या पर निर्भर करता है, इसलिए पुन: स्ट्रीमिंग महंगा नहीं है:

public static Map calculateIntegerDistribution(List list) {
    return list.stream()
            .collect(Collectors.groupingBy(Integer::intValue,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.2f", count.doubleValue() / list.size()))))))
            
            
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

वस्तुएँ

यह वस्तुओं के लिए कैसे किया जा सकता है? वही तर्क लागू होता है! एक पहचान समारोह के बजाय (Integer::intValue), हम इसके बजाय वांछित फ़ील्ड का उपयोग करेंगे - जैसे कि हमारी पुस्तकों के लिए प्रकाशित वर्ष। आइए कुछ पुस्तकें बनाएं, उन्हें एक सूची में संग्रहीत करें और फिर प्रकाशन वर्षों के वितरण की गणना करें:

सर्वोत्तम प्रथाओं, उद्योग-स्वीकृत मानकों और शामिल चीट शीट के साथ, Git सीखने के लिए व्यावहारिक मार्गदर्शिका देखें। Googling Git कमांड को रोकें और वास्तव में सीखना यह!

Book book1 = new Book("001", "Our Mathematical Universe", "Max Tegmark", 432, 2014);
Book book2 = new Book("002", "Life 3.0", "Max Tegmark", 280, 2017);
Book book3 = new Book("003", "Sapiens", "Yuval Noah Harari", 443, 2011);
Book book4 = new Book("004", "Steve Jobs", "Water Isaacson", 656, 2011);

List books = Arrays.asList(book1, book2, book3, book4);

के वितरण की गणना करते हैं publishedYear खेत:

public static Map calculateDistribution(List books) {
    return books.stream()
            .collect(Collectors.groupingBy(Book::getPublishedYear,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.2f", count * 100.00 / books.size()))))))
            
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

ठीक कीजिये "%.2f" फ़्लोटिंग पॉइंट परिशुद्धता सेट करने के लिए। इस में यह परिणाम:

{2011=50.0, 2014=25.0, 2017=25.0}

दी गई पुस्तकों में से 50% (2/4) 2011 में प्रकाशित हुई थी, 25% (1/4) 2014 में और 25% (1/4) 2017 में प्रकाशित हुई थी। क्या होगा यदि आप इस परिणाम को अलग तरीके से प्रारूपित करना चाहते हैं, और सामान्य करना चाहते हैं रेंज में 0..1?

जावा में संग्रह के सामान्यीकृत (प्रतिशत) वितरण की गणना करें

a . से प्रतिशत सामान्य करने के लिए 0.0...100.0 रेंज से a . तक 0..1 रेंज - हम बस अनुकूलित करेंगे collectingAndThen() कॉल करने के लिए नहीं गिनती को से गुणा करें 100.0 संग्रह के आकार से विभाजित करने से पहले।

पहले, द Long द्वारा लौटाया गया गिनती Collectors.counting() परोक्ष रूप से एक डबल (एक डबल मान के साथ गुणा) में परिवर्तित किया गया था - इसलिए इस बार, हम स्पष्ट रूप से प्राप्त करना चाहेंगे doubleValue() का count:

    public static Map calculateDistributionNormalized(List books) {
        return books.stream()
            .collect(Collectors.groupingBy(Book::getPublishedYear,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Double.parseDouble(String.format("%.4f", count.doubleValue() / books.size()))))))
            
            .entrySet()
            .stream()
            .sorted(comparing(e -> e.getKey()))
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

ठीक कीजिये "%.4f" फ़्लोटिंग पॉइंट परिशुद्धता सेट करने के लिए। इस में यह परिणाम:

{2011=0.5, 2014=0.25, 2017=0.25}

संग्रह के तत्व गणना (आवृत्ति) की गणना करें

अंत में - हम संग्रह के आकार से गिनती को विभाजित न करके संग्रह में तत्व गणना (सभी तत्वों की आवृत्ति) प्राप्त कर सकते हैं! यह पूरी तरह से गैर-सामान्यीकृत गणना है:

   public static Map calculateDistributionCount(List books) {
        return books
            .stream()
            .collect(Collectors.groupingBy(Book::getPublishedYear,
                    Collectors.collectingAndThen(Collectors.counting(),
                            count -> (Integer.parseInt(String.format("%s", count.intValue()))))))
            
            .entrySet()
            .stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(e -> Integer.parseInt(e.getKey().toString()),
                    Map.Entry::getValue,
                    (a, b) -> {
                        throw new AssertionError();
                    },
                    LinkedHashMap::new));
}

इसका परिणाम यह होगा:

{2011=2, 2014=1, 2017=1}

दरअसल, 2011 से दो किताबें हैं, और 2014 और 2017 से एक-एक।

निष्कर्ष

डेटा के वितरण की गणना करना डेटा-समृद्ध अनुप्रयोगों में एक सामान्य कार्य है, और इसके लिए बाहरी पुस्तकालयों या जटिल कोड के उपयोग की आवश्यकता नहीं होती है। कार्यात्मक प्रोग्रामिंग समर्थन के साथ, जावा ने संग्रह के साथ काम करना आसान बना दिया है!

इस संक्षिप्त मसौदे में, हमने इस बात पर एक नज़र डाली है कि आप किसी संग्रह में सभी तत्वों की आवृत्ति गणना कैसे कर सकते हैं, साथ ही वितरण मानचित्रों की गणना कैसे करें जो प्रतिशत के बीच सामान्यीकृत हैं 0 और 1 और 0 और 100 जावा में।

समय टिकट:

से अधिक स्टैकब्यूज