जावा में एक सूची को उलटना - इन-प्लेस और आउट-ऑफ-प्लेस

इस संक्षिप्त ट्यूटोरियल में, आप सीखेंगे कि जावा में किसी सूची को इन-प्लेस और आउट-ऑफ-प्लेस कैसे रिवर्स किया जाए।

इन-प्लेस और आउट-ऑफ-प्लेस को उलटना

सूचियों पर संचालन करते समय - आप इस बात पर विचार करना चाहेंगे कि क्या संचालन जगह में किया गया है (मूल वस्तु पर परिवर्तन लागू किए गए हैं), या क्या वे जगह से बाहर हैं (परिवर्तन एक प्रतिलिपि पर लागू होते हैं, और मूल वस्तु अपरिवर्तित है)।

कुछ भाषाएं और पुस्तकालय अलग-अलग डिफ़ॉल्ट व्यवहार पसंद करते हैं। जावा में, रिवर्सिंग सूचियों पर अधिकांश ऑपरेशन होंगे जगह में.

यदि यह आपका वांछित व्यवहार है - बढ़िया! यदि नहीं, तो आप प्रतिलिपि को उलटने से पहले सूची की एक प्रति बनाना चाहेंगे:

List list = new ArrayList(Arrays.asList(1, 2, 3));
List listCopy = new ArrayList(list);

नोट: RSI clone() तरीका नहीं होता है एक गहरी प्रति बनाएँ। का उपयोग कर एक सूची बनाना new ArrayList(list) नहीं होता है एक गहरी प्रति बनाएँ। गहरी प्रतियां बनाना हतोत्साहित किया जाता है, और सामान्य तरीके से करना आश्चर्यजनक रूप से कठिन होता है (और सूची में डेटा प्रकार के आधार पर कुछ मामलों में इसका कोई मतलब नहीं होता है)। यह आपको उलटने में सक्षम होने से नहीं रोकेगा list और नहीं के तत्व हैं listCopy हालांकि उलट दिया जा रहा है।

कलेक्शंस.रिवर्स ()

RSI Collections.reverse() विधि एक संग्रह को उलटने के लिए मानक विधि है, और "लापता" के रूप में कार्य करती है List.reverse() तरीका। यह सूची को जगह में उलट देता है:

List list = new ArrayList(Arrays.asList(1, 2, 3));
List listCopy = new ArrayList(list);

Collections.reverse(list);

System.out.println(list);     
System.out.println(listCopy); 

अमरूद की सूचियाँ। रिवर्स (सूची)

यदि आप अपने प्रोजेक्ट में पहले से ही Google अमरूद का उपयोग कर रहे हैं, तो आप इसका भी लाभ उठा सकते हैं Lists वर्ग, जो प्रदान करता है reverse() विधि, जो मूल सूची को जगह में क्रमबद्ध नहीं करती है, लेकिन एक प्रतिलिपि बनाती है और प्रतिलिपि को उलट देती है:

List list = new ArrayList(Arrays.asList(1, 2, 3));
List reversedList = Lists.reverse(list);

System.out.println(list);         
System.out.println(reversedList); 

यदि आपके पास यह पहले से नहीं है, तो आप मावेन का उपयोग करके अपने प्रोजेक्ट में Google अमरूद को अपनी निर्भरता में शामिल करके जोड़ सकते हैं pom.xml फ़ाइल:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
</dependency>

या ग्रैडल के माध्यम से:

implementation group: 'com.google.guava', name: 'guava'

नोट: यदि आपके पास पहले से Google अमरूद नहीं है, या आप इसे अपनी परियोजना के अन्य भागों के लिए उपयोग करने का इरादा नहीं रखते हैं - इसे केवल इस ऑपरेशन के लिए आयात न करें, और इसके साथ चिपके रहें Collections.reverse() तरीका। अमरूद एक बड़ी निर्भरता है, और यह एक प्रमुख ओवरकिल है जिसका उपयोग केवल इस ऑपरेशन के लिए किया जाता है।

List.add() और List.remove()

यदि आप सूची को उलटने के अलावा अतिरिक्त संचालन करना चाहते हैं - आप मूल सूची के माध्यम से पुनरावृति कर सकते हैं, तत्वों को अंत से हटा सकते हैं, उन्हें एक मनमानी विधि से पारित कर सकते हैं, और उन्हें सूची की शुरुआत में वापस जोड़ सकते हैं:


public static int process(int input) {
    return input;
}

List list = new ArrayList(Arrays.asList(1, 2, 3));

for (int i = 0, j = list.size()-1; i <= j; i++) {
    int lastValue = process(list.remove(j));
    list.add(i, lastValue);
}

System.out.println(list);  

बेंचमार्क

तो, सबसे तेज़ कौन सा है? यह इस बात पर भी निर्भर करता है कि आप ऑपरेशन को इन-प्लेस या आउट-ऑफ-प्लेस करना चाहते हैं।

इन-प्लेस रिवर्सल बेंचमार्क

आइए, आउट-ऑफ़-प्लेस से शुरू करते हुए, तीनों विधियों पर दोनों दृष्टिकोणों को बेंचमार्क करें:

List list = new Random().ints(100, 1, 11)
                .boxed()
                .collect(Collectors.toList());

int runs = 1000;

long start1 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    reverseListCollections(list);
}
long end1 = System.currentTimeMillis();
System.out.println(String.format("Collections.reverse() took: %s miliseconds", end1-start1));

long start2 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    reverseListGuava(list);
}
long end2 = System.currentTimeMillis();
System.out.println(String.format("Guava's Lists.reverse() took: %s miliseconds", end2-start2));

long start3 = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
    reverseListManually(list);
}
long end3 = System.currentTimeMillis();
System.out.println(String.format("Manually took: %s miliseconds", end3-start3));

System.out.println("Original list: " + list);

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

Collections.reverse() took: 3 miliseconds
Guava's Lists.reverse() took: 4 miliseconds
Manually took: 13 miliseconds
Original list: [6, 7, 9, 7, 2, 5, 4, 1, 3, 2, 2, 6, ...

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

क्या होता है जब हम तत्वों की संख्या को 100 से बढ़ाकर 1000 कर देते हैं?

Collections.reverse() took: 9 miliseconds
Guava's Lists.reverse() took: 4 miliseconds
Manually took: 133 miliseconds
Original list: [10, 2, 2, 6, 2, 4, 7, 3, 9, 2, 7, 5, ...

अमरूद 4ms का निशान बरकरार रखता है! मैनुअल दृष्टिकोण में सबसे खराब समय जटिलता है, और यह रैखिक रूप से बढ़ी है। Collections.reverse() स्केलिंग से कम पीड़ित हैं, लेकिन अमरूद के कार्यान्वयन को सबसे कम नुकसान हुआ है। हालांकि, ध्यान रखें कि हम अमरूद दृष्टिकोण के लिए सूची को मैन्युअल रूप से कॉपी नहीं करते हैं। जब हम "मूल" और "उलट" सूची रखने के विचार को छोड़ देंगे तो क्या बेंचमार्क बदल जाएगा?

आउट-ऑफ-प्लेस रिवर्सल बेंचमार्क

1000 तत्वों के साथ, और प्रत्येक सूची की एक गैर-उलट प्रतिलिपि पर काम कर रहा है (जिसे समय माप से बाहर रखा गया था), जब हम प्रत्येक विधि से मैन्युअल प्रतिलिपि हटाते हैं और कोड को फिर से चलाते हैं:

Collections.reverse() took: 7 miliseconds
Guava's Lists.reverse() took: 3 miliseconds
Manually took: 131 miliseconds
Original list: [6, 8, 10, 7, 3, 8, 7, 1, 1, 9, 5, ...

अमरूद अभी भी लगातार दोनों को मात देने का प्रबंधन करता है Collections.reverse() और मैनुअल दृष्टिकोण।

निष्कर्ष

इस संक्षिप्त मार्गदर्शिका में, आपने सीखा है कि जावा, इन-प्लेस और आउट-ऑफ-प्लेस में सूची को कैसे उलटना है, ऑपरेशन से मूल सूची को संरक्षित करना। हमने इस्तेमाल किया है Collections.reverse() विधि, गूगल अमरूद Lists.reverse() विधि और एक मैनुअल दृष्टिकोण।

समय टिकट:

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