[Java] जावा में एक सूची में फिर से शुरू करने के तरीके


Answers

प्रश्न में सूचीबद्ध प्रत्येक प्रकार का उदाहरण:

ListIterationExample.java

import java.util.*;

public class ListIterationExample {

     public static void main(String []args){
        List<Integer> numbers = new ArrayList<Integer>();

        // populates list with initial values
        for (Integer i : Arrays.asList(0,1,2,3,4,5,6,7))
            numbers.add(i);
        printList(numbers);         // 0,1,2,3,4,5,6,7

        // replaces each element with twice its value
        for (int index=0; index < numbers.size(); index++) {
            numbers.set(index, numbers.get(index)*2); 
        }
        printList(numbers);         // 0,2,4,6,8,10,12,14

        // does nothing because list is not being changed
        for (Integer number : numbers) {
            number++; // number = new Integer(number+1);
        }
        printList(numbers);         // 0,2,4,6,8,10,12,14  

        // same as above -- just different syntax
        for (Iterator<Integer> iter = numbers.iterator(); iter.hasNext(); ) {
            Integer number = iter.next();
            number++;
        }
        printList(numbers);         // 0,2,4,6,8,10,12,14

        // ListIterator<?> provides an "add" method to insert elements
        // between the current element and the cursor
        for (ListIterator<Integer> iter = numbers.listIterator(); iter.hasNext(); ) {
            Integer number = iter.next();
            iter.add(number+1);     // insert a number right before this
        }
        printList(numbers);         // 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

        // Iterator<?> provides a "remove" method to delete elements
        // between the current element and the cursor
        for (Iterator<Integer> iter = numbers.iterator(); iter.hasNext(); ) {
            Integer number = iter.next();
            if (number % 2 == 0)    // if number is even 
                iter.remove();      // remove it from the collection
        }
        printList(numbers);         // 1,3,5,7,9,11,13,15

        // ListIterator<?> provides a "set" method to replace elements
        for (ListIterator<Integer> iter = numbers.listIterator(); iter.hasNext(); ) {
            Integer number = iter.next();
            iter.set(number/2);     // divide each element by 2
        }
        printList(numbers);         // 0,1,2,3,4,5,6,7
     }

     public static void printList(List<Integer> numbers) {
        StringBuilder sb = new StringBuilder();
        for (Integer number : numbers) {
            sb.append(number);
            sb.append(",");
        }
        sb.deleteCharAt(sb.length()-1); // remove trailing comma
        System.out.println(sb.toString());
     }
}
Question

जावा भाषा में कुछ नया होने के नाते मैं अपने आप को सभी तरीकों से (या कम से कम गैर-रोगजनक) से परिचित करने की कोशिश कर रहा हूं, जो कि किसी सूची (या शायद अन्य संग्रह) और प्रत्येक के फायदे या नुकसान के माध्यम से पुन: प्रयास कर सकता है।

एक List<E> list वस्तु को देखते हुए, मुझे सभी तत्वों के माध्यम से लूप करने के निम्न तरीकों के बारे में पता है:

loop for मूल (बेशक, लूप के साथ-साथ समकक्ष होते हैं)

// Not recommended (see below)!
for (int i = 0; i < list.size(); i++) {
    E element = list.get(i);
    // 1 - can call methods of element
    // 2 - can use 'i' to make index-based calls to methods of list

    // ...
}

नोट: जैसा कि @amarseillan ने इंगित किया है, यह रूप List पुन: प्रयास करने के लिए एक खराब विकल्प है, क्योंकि get विधि का वास्तविक कार्यान्वयन एक Iterator का उपयोग करते समय उतना कुशल नहीं हो सकता है। उदाहरण के लिए, LinkedList कार्यान्वयन को i-th तत्व प्राप्त करने के लिए पहले के सभी तत्वों को पार करना होगा।

उपर्युक्त उदाहरण में भविष्य में पुनरावृत्ति को और अधिक कुशल बनाने के लिए List कार्यान्वयन के लिए "इसकी जगह को सहेजने" का कोई तरीका नहीं है। एक ArrayList यह वास्तव में कोई फर्क नहीं पड़ता, क्योंकि जटिलता / get लागत निरंतर समय (ओ (1) है) जबकि एक LinkedList लिए यह सूची के आकार (ओ (एन) के अनुपात के समान है।

अंतर्निहित Collections कार्यान्वयन की कम्प्यूटेशनल जटिलता के बारे में अधिक जानकारी के लिए, इस प्रश्न को देखें

लूप के लिए उन्नत ( इस सवाल में अच्छी तरह से समझाया गया )

for (E element : list) {
    // 1 - can call methods of element

    // ...
}

Iterator

for (Iterator<E> iter = list.iterator(); iter.hasNext(); ) {
    E element = iter.next();
    // 1 - can call methods of element
    // 2 - can use iter.remove() to remove the current element from the list

    // ...
}

ListIterator

for (ListIterator<E> iter = list.listIterator(); iter.hasNext(); ) {
    E element = iter.next();
    // 1 - can call methods of element
    // 2 - can use iter.remove() to remove the current element from the list
    // 3 - can use iter.add(...) to insert a new element into the list
    //     between element and iter->next()
    // 4 - can use iter.set(...) to replace the current element

    // ...
}

कार्यात्मक जावा

list.stream().map(e -> e + 1); // Can apply a transformation function for e

Iterable.forEach , Stream.forEach , ...

(जावा 8 के स्ट्रीम एपीआई से एक नक्शा विधि (देखें @ i_am_zero का जवाब)।)

जावा 8 संग्रह वर्ग जो Iterable लागू Iterable (उदाहरण के लिए, सभी List एस) में अब एक विधि है, जिसका प्रयोग ऊपर दिखाए गए for बजाय किया जा सकता है। (यहां एक और सवाल है जो अच्छी तुलना प्रदान करता है।)

Arrays.asList(1,2,3,4).forEach(System.out::println);
// 1 - can call methods of an element
// 2 - would need reference to containing object to remove an item
//     (TODO: someone please confirm / deny this)
// 3 - functionally separates iteration from the action
//     being performed with each item.

Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
// Same capabilities as above plus potentially greater
// utilization of parallelism
// (caution: consequently, order of execution is not guaranteed,
// see [Stream.forEachOrdered][stream-foreach-ordered] for more
// information about this).

अगर कोई है तो अन्य तरीके क्या हैं?

(बीटीडब्ल्यू, मेरी रुचि प्रदर्शन को अनुकूलित करने की इच्छा से बिल्कुल नहीं है; मैं सिर्फ यह जानना चाहता हूं कि डेवलपर के रूप में मेरे लिए कौन से फॉर्म उपलब्ध हैं।)




आप हमेशा थोड़ी देर के साथ पहले और तीसरे उदाहरणों को स्विच कर सकते हैं और थोड़ा और कोड। यह आपको कार्य-समय का उपयोग करने में सक्षम होने का लाभ देता है:

int i = 0;
do{
 E element = list.get(i);
 i++;
}
while (i < list.size());

बेशक, इस तरह की चीज NullPointerException का कारण बन सकती है यदि list.size () 0 देता है, क्योंकि यह हमेशा कम से कम एक बार निष्पादित हो जाता है। यह परीक्षण करके तय किया जा सकता है कि तत्व अपने गुण / विधियों का उपयोग करने से पहले शून्य है। फिर भी, लूप के लिए उपयोग करना बहुत आसान और आसान है




एक जेडीके 8-शैली पुनरावृत्ति:

public class IterationDemo {

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
        list.stream().forEach(elem -> System.out.println("element " + elem));
    }
}



पिछड़ी खोज के लिए आपको निम्न का उपयोग करना चाहिए:

for (ListIterator<SomeClass> iterator = list.listIterator(list.size()); iterator.hasPrevious();) {
    SomeClass item = iterator.previous();
    ...
    item.remove(); // For instance.
}

यदि आप किसी स्थिति को जानना चाहते हैं, तो iterator.previousIndex () का उपयोग करें। यह एक आंतरिक लूप लिखने में भी मदद करता है जो सूची में दो पदों की तुलना करता है (इटरेटर बराबर नहीं हैं)।




जावा 8 में हमारे पास संग्रह कक्षाओं में पुन: प्रयास करने के कई तरीके हैं।

Iterable के लिए उपयोग करना

Iterable लागू करने वाले संग्रह (उदाहरण के लिए सभी सूचियों) अब forEach विधि के लिए है। हम जावा 8 में पेश method-reference उपयोग कर सकते हैं।

Arrays.asList(1,2,3,4).forEach(System.out::println);

प्रत्येक और स्ट्रीम के लिए स्ट्रीम का उपयोग करना

Stream रूप में हम एक सूची में भी पुन: प्रयास कर सकते हैं:

Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
Arrays.asList(1,2,3,4).stream().forEachOrdered(System.out::println);

हमें forEachOrdered लिए forEach forEachOrdered चाहिए क्योंकि प्रत्येक के लिए व्यवहार स्पष्ट रूप से nondeterministic है, क्योंकि स्ट्रीम के मुठभेड़ क्रम में स्ट्रीम के मुठभेड़ क्रम में, स्ट्रीम के मुठभेड़ क्रम में, प्रत्येक धारा के लिए प्रत्येक कार्य करने के लिए कार्रवाई करता है। तो प्रत्येक के लिए गारंटी नहीं है कि आदेश रखा जाएगा।

धाराओं के साथ लाभ यह है कि हम जहां भी उपयुक्त हों समानांतर धाराओं का उपयोग भी कर सकते हैं। यदि उद्देश्य केवल आदेश के बावजूद वस्तुओं को मुद्रित करना है तो हम समांतर धारा का उपयोग इस प्रकार कर सकते हैं:

Arrays.asList(1,2,3,4).parallelStream().forEach(System.out::println);