java - क्या आप जावा में मानों को संचय किए बिना संग्रह कर सकते हैं?




collections iterator (2)

जैसा कि डीडब्लूबी ने कहा, जावा के संग्रह एपीआई के साथ ऐसा करना संभव नहीं है, क्योंकि हर तत्व को स्मृति में संग्रहित किया जाना चाहिए। हालांकि, एक विकल्प है: यही वजह है कि जावा की स्ट्रीम एपीआई लागू की गई थी!

Stream आपको एक अनन्त संख्या में ऑब्जेक्ट की अनुमति देता है जो स्मृति में संग्रहीत नहीं हैं जब तक कि आप उन्हें एक Collection में एकत्रित नहीं करते।

IntStream#iterate के प्रलेखन से:

प्रारंभिक तत्व बीज के पुनरावृत्त अनुप्रयोग के द्वारा निर्मित एक अनंत अनुक्रमित आदेश दिया गया इंटरस्ट्रीम, बीज, एफ (बीज), एफ (एफ (बी)) आदि से युक्त धारा का उत्पादन करता है।

इंटस्ट्रीम में पहला तत्व (स्थिति 0) प्रदान किया गया बीज होगा। N> 0 के लिए, स्थिति n पर तत्व, नं।-1 स्थिति में तत्व को फ़ंक्शन को लागू करने का नतीजा होगा।

यहां कुछ उदाहरण दिए गए हैं जो आपने अपने प्रश्न में प्रस्तावित किए हैं:

public class Test {

    public static void main(String[] args) {
        IntStream.iterate(1, k -> 6 * k + 1);
        IntStream.iterate(10, i -> i + 1).filter(Test::isPrime);
        IntStream.iterate(1, n -> 2 * n - 1).filter(i -> i < 1_000_000);
    }

    private boolean isPrime(int a) {
        if (a < 2) {
            return false;
        }

        for(int i = 2; i < a; i++) {
            if ((a % i) == 0) {
                return false;
            }

            return true;
        }
    }
}

मेरे जावा संग्रह के बारे में एक सवाल है जैसे कि सेट या लिस्ट अधिक आम तौर पर ऑब्जेक्ट्स जिनका उपयोग आप प्रत्येक लूप के लिए कर सकते हैं। क्या कोई आवश्यकता है कि उनमें से तत्वों को वास्तव में किसी डाटा संरचना में कहीं जमा किया जाना है या क्या उन्हें केवल किसी प्रकार की ज़रूरत से वर्णित किया जा सकता है और जब आपको उनकी आवश्यकता होती है, तो उनकी गणना की जाती है? ऐसा लगता है कि ऐसा करना संभव है, लेकिन मुझे इस तरह से कुछ करने वाले जावा मानक संग्रह वर्ग दिखाई नहीं दे रहे हैं। क्या मैं किसी प्रकार के अनुबंध को तोड़ रहा हूँ?

मैं इन बातों का उपयोग करने के बारे में सोच रहा हूं, मुख्यतः गणित है उदाहरण के लिए कहें कि मैं 1 000 000 के तहत सभी प्रमुख संख्याओं का प्रतिनिधित्व करने वाला एक समूह बनाना चाहता हूं। यह स्मृति में इन्हें सहेजने के लिए एक अच्छा विचार नहीं है, बल्कि इसके बजाय एक विधि की जांच हो सकती है यदि कोई विशेष संख्या संग्रह में है या नहीं।

मैं जावा धाराओं के सभी विशेषज्ञों में भी नहीं हूं, लेकिन मुझे लगता है कि इन्हें जावा 8 स्ट्रीमों में प्रयोग करने योग्य होना चाहिए क्योंकि ऑब्जेक्ट्स में बहुत कम राज्य है (संग्रह में ऑब्जेक्ट तब तक मौजूद नहीं हैं जब तक आप उनसे पुनरावृत्त नहीं करते या संग्रह में कोई विशिष्ट ऑब्जेक्ट मौजूद है या नहीं) की जांच करें।

क्या लगभग असीम तत्वों के साथ संग्रह या इटरेटर होना संभव है, उदाहरण के लिए "फ़ॉर्म 6 * कश्मीर + 1 पर सभी नंबर", "10 से ऊपर सभी प्राइम" या "इस आधार पर फैले सभी वैक्टर"? एक अन्य चीज जो मैं सोच रहा हूँ, दो सेटों के संयोजन में 1 000 000 से नीचे के सभी प्राइमों के यूनियन और फॉर्म 2 ^ एन -1 पर सभी इंटिजर्स और 1 000 000 से नीचे मीर्सन प्राइम्स सूचीबद्ध करता है। मुझे लगता है कि यह आसान होगा कुछ गणितीय ऑब्जेक्ट्स के बारे में कारण अगर यह इस तरह से किया गया था और तत्वों को स्पष्ट रूप से तब तक नहीं बनाया गया जब तक कि वे वास्तव में आवश्यक न हों। शायद मैं गलत हूँ।

यह दो मॉकअप कक्षाएं हैं जिन्हें मैंने स्पष्ट किया है कि मैं क्या करना चाहता हूं। वे ठीक से काम नहीं करते जैसा मुझे उम्मीद थी (आउटपुट देखें) जिससे मुझे लगता है कि मैं किसी प्रकार के अनुबंध को तोड़ने वाला इंटरफ़ेस या इसे गलत तरीके से कार्यान्वित कर रहा हूं। यदि आप इसे देख रहे हैं या अगर इस तरह के कोड को संग्रह के ढांचे के तहत भी अनुमति दी गई है, तो यहां बताइए कि मैं क्या गलत कर रहा हूं।

import java.util.AbstractSet;
import java.util.Iterator;

public class PrimesBelow extends AbstractSet<Integer>{

    int max;
    int size;

    public PrimesBelow(int max) {
        this.max = max;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new SetIterator<Integer>(this);
    }

    @Override
    public int size() {
        if(this.size == -1){
            System.out.println("Calculating size");
            size = calculateSize();
        }else{
            System.out.println("Accessing calculated size");
        }
        return size;
    }

    private int calculateSize() {
        int c = 0;
        for(Integer p: this)
            c++;
        return c;
    }

    public static void main(String[] args){
        PrimesBelow primesBelow10 = new PrimesBelow(10);
        for(int i: primesBelow10)
            System.out.println(i);
        System.out.println(primesBelow10);
    }
}

import java.util.Iterator;
import java.util.NoSuchElementException;

public class SetIterator<T> implements Iterator<Integer> {
    int max;
    int current;
    public SetIterator(PrimesBelow pb) {
        this.max= pb.max;
        current = 1;
    }

    @Override
    public boolean hasNext() {
        if(current < max) return true;
        else return false;
    }

    @Override
    public Integer next() {
        while(hasNext()){
            current++;
            if(isPrime(current)){
                System.out.println("returning "+current);
                return current;
            }
        }
        throw new NoSuchElementException();
    }

    private boolean isPrime(int a) {
        if(a<2) return false;
        for(int i = 2; i < a; i++) if((a%i)==0) return false;
        return true;
    }
}

Main function gives the output
returning 2
2
returning 3
3
returning 5
5
returning 7
7
Exception in thread "main" java.util.NoSuchElementException
    at SetIterator.next(SetIterator.java:27)
    at SetIterator.next(SetIterator.java:1)
    at PrimesBelow.main(PrimesBelow.java:38)

संपादित करें: अगले () विधि में एक त्रुटि देखा इसे सही किया और आउटपुट को एक नया बदल दिया।


ठीक है, जैसा कि आप अपने (अब तय) उदाहरण के साथ देखते हैं, आप इसे आसानी से Iterables / Iterators साथ कर सकते हैं एक बैकिंग संग्रह होने के बजाय, उदाहरण केवल एक Iterable साथ अच्छे रहे Iterable जो आपको अधिकतम संख्या लेता है जो आप को प्राथमिकताएं गणना करना चाहते हैं आपको यह सुनिश्चित करने की ज़रूरत है कि आप hasNext() विधि ठीक से संभाल रहे हैं, इसलिए आपको next() से अनावश्यक अपवाद फेंकना नहीं पड़ता है।

जावा 8 धाराओं का प्रयोग आजकल इन प्रकार की चीज़ों को करने के लिए आसान हो सकता है, लेकिन ऐसा कोई कारण नहीं है कि आप "आभासी संग्रह" नहीं कर सकते हैं जो सिर्फ एक Iterable । यदि आप Collection लागू करना शुरू करते हैं तो यह कठिन हो जाता है, लेकिन फिर भी उपयोग मामलों पर निर्भर करता है, यह पूरी तरह से असंभव नहीं होगा: उदाहरण के लिए आप लागू कर सकते contains() जो प्राइम की जांच करता है, लेकिन आपको इसे गणना करना होगा और यह होगा बड़ी संख्या के लिए धीमा

एक (कुछ हद तक जटिल) एक अस्थायी संख्या का एक अर्ध-अनंत सेट का उदाहरण जो अपरिवर्तनीय है और कोई मान नहीं रखता है।

public class OddSet implements Set<Integer> {
    public boolean contains(Integer o) {
        return o % 2 == 1;
    }
    public int size() {
        return Integer.MAX_VALUE;
    }
    public boolean add(Integer i) {
        throw new OperationNotSupportedException();
    }

    public boolean equals(Object o) {
        return o instanceof OddSet;
    }
    // etc. etc.
}




set