क्या कोई जावा में प्रत्येक लूप के लिए रिवर्स ऑर्डर में कर सकता है?


148

मुझे जावा का उपयोग करके रिवर्स ऑर्डर में एक सूची के माध्यम से चलाने की आवश्यकता है।

तो यह आगे कहाँ करता है:

for(String string: stringList){
//...do something
}

क्या प्रत्येक वाक्यविन्यास के लिए स्ट्रिंगलिस्ट को रिवर्स ऑर्डर में पुनरावृत्त करने का कोई तरीका है ?

स्पष्टता के लिए: मुझे पता है कि किसी सूची को उल्टे क्रम में कैसे बदलना है, लेकिन यह जानना चाहते हैं (जिज्ञासा के लिए) प्रत्येक शैली के लिए यह कैसे करना है ।


5
"प्रत्येक के लिए" लूप की बात यह है कि आपको बस प्रत्येक तत्व पर एक ऑपरेशन करने की आवश्यकता है, और आदेश महत्वपूर्ण नहीं है। प्रत्येक के लिए तत्वों को पूरी तरह से यादृच्छिक क्रम में संसाधित किया जा सकता है, और यह अभी भी वही कर रहा है जो इसके लिए डिज़ाइन किया गया था। यदि आपको तत्वों को एक विशेष तरीके से संसाधित करने की आवश्यकता है, तो मैं इसे मैन्युअल रूप से करने का सुझाव दूंगा।
मूसबुल्ला

जावा संग्रह पुस्तकालय। वास्तव में भाषा के साथ कुछ भी नहीं करना है। दोष जोश बलोच।
टॉम हॉल्टिन -

7
@ मुसूबोल्ला: लेकिन एक सूची के रूप में एक आदेश दिया गया संग्रह है, निश्चित रूप से इसके आदेश को सम्मानित किया जाएगा, चाहे? इसलिए प्रत्येक के लिए सूची के तत्वों को यादृच्छिक क्रम में संसाधित नहीं किया जाएगा।
ली कोवलकोव्स्की

5
@ मुसूबोल्ला जो सच नहीं है। शायद Setव्युत्पन्न संग्रह के मामले में । संग्रह foreachकी iterator()विधि से लौटे पुनरावृति के क्रम में पुनरावृत्ति की गारंटी देता है । docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
robert

जवाबों:


151

Collections.reverse विधि वास्तव में मूल सूची के तत्वों के साथ एक नई सूची को उल्टे क्रम में कॉपी करती है, इसलिए इसमें मूल सूची के आकार के संबंध में O (n) प्रदर्शन होता है।

एक अधिक कुशल समाधान के रूप में, आप एक डेकोरेटर के रूप में एक सूची के उल्टे दृश्य को प्रस्तुत करने वाले डेकोरेटर को लिख सकते हैं। आपके डेकोरेटर द्वारा लौटाए गए इट्रेटर रिवर्स ऑर्डर में तत्वों पर चलने के लिए सजाए गए सूची के लिटरेटर का उपयोग करेंगे।

उदाहरण के लिए:

public class Reversed<T> implements Iterable<T> {
    private final List<T> original;

    public Reversed(List<T> original) {
        this.original = original;
    }

    public Iterator<T> iterator() {
        final ListIterator<T> i = original.listIterator(original.size());

        return new Iterator<T>() {
            public boolean hasNext() { return i.hasPrevious(); }
            public T next() { return i.previous(); }
            public void remove() { i.remove(); }
        };
    }

    public static <T> Reversed<T> reversed(List<T> original) {
        return new Reversed<T>(original);
    }
}

और आप इसका उपयोग इस तरह करेंगे:

import static Reversed.reversed;

...

List<String> someStrings = getSomeStrings();
for (String s : reversed(someStrings)) {
    doSomethingWith(s);
}

22
यह मूल रूप से Google का Iterables.reverse करता है, हां :)
जॉन स्कीट

10
मुझे पता है कि एक 'नियम' है जिसे हमें जॉन के उत्तर को स्वीकार करना होगा :) लेकिन .. मैं इस एक को स्वीकार करना चाहता हूं (भले ही वे अनिवार्य रूप से एक ही हों) क्योंकि मुझे किसी अन्य 3 पार्टी लाइब्रेरी को शामिल करने की आवश्यकता नहीं है (हालांकि कुछ तर्क दे सकते हैं कि यह कारण OO के एक मुख्य लाभ को तोड़ता है - पुन: प्रयोज्य)।
रॉन टफिन

छोटी त्रुटि: सार्वजनिक शून्य हटाने () में, रिटर्न स्टेटमेंट नहीं होना चाहिए, यह सिर्फ होना चाहिए: i.remove ();
जेसपर

10
संग्रह.श्रवण () एक उलटी प्रतिलिपि वापस नहीं करता है, लेकिन एक पैरामीटर के रूप में पारित सूची पर कार्य करता है। पुनरावृत्ति के साथ अपने समाधान की तरह, हालांकि। वास्तव में सुरुचिपूर्ण।
er4z0r

96

एक सूची के लिए, आप Google अमरूद लाइब्रेरी का उपयोग कर सकते हैं :

for (String item : Lists.reverse(stringList))
{
    // ...
}

ध्यान दें कि पूरे संग्रह को उल्टा नहीं करता है , या ऐसा कुछ भी नहीं करता है - यह सिर्फ रिवर्स क्रम में पुनरावृत्ति और यादृच्छिक अभिगम की अनुमति देता है। यह पहले संग्रह को उलटने की तुलना में अधिक कुशल है।Lists.reverse

एक मनमाना चलने को उलटने के लिए, आपको यह सब पढ़ना होगा और फिर इसे "रीप्ले" करना होगा।

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


1
हमारा कोडबेस लार्वालैब्स ( larvalabs.com/collections ) द्वारा जारी कॉमन्स कलेक्शंस के जेनरेट किए गए संस्करण का भारी उपयोग करता है । Apache Commons के लिए SVN रेपो के माध्यम से देखते हुए, यह स्पष्ट है कि कॉमन्स कलेक्शन के जावा 5 संस्करण को जारी करने में अधिकांश काम किया जाता है, उन्होंने अभी इसे जारी नहीं किया है।
Skaffman

मुझें यह पसंद है। यदि यह इतना उपयोगी नहीं होता, तो मैं उस प्लग को कॉल करता।
जियोवा 4

मुझे आश्चर्य है कि जकार्ता ने अपाचे कॉमन्स को अपडेट करने के लिए कभी परेशान क्यों नहीं किया।
उरी

3
उन्होंने इसे अपडेट किया है, यही मैं कह रहा हूं। उन्होंने अभी इसे जारी नहीं किया है।
स्केफमैन

23
Iterables.reverse को हटा दिया गया है, इसके बजाय Lists.reverse या ImmutableList.reverse का उपयोग करें।
गैरेट हॉल

39

सूची (सेट के विपरीत) एक आदेश दिया गया संग्रह है और इस पर पुनरावृति अनुबंध द्वारा आदेश को संरक्षित करता है। मैंने रिवर्स ऑर्डर में स्टैक से पुनरावृति की उम्मीद की होगी, लेकिन दुर्भाग्य से ऐसा नहीं है। तो सबसे सरल उपाय जो मैं सोच सकता हूं वह यह है:

for (int i = stack.size() - 1; i >= 0; i--) {
    System.out.println(stack.get(i));
}

मुझे एहसास है कि यह "प्रत्येक" लूप समाधान के लिए नहीं है। मैं Google संग्रह जैसी नई लाइब्रेरी शुरू करने के बजाय लूप के लिए उपयोग करूंगा।

संग्रह .reverse () भी काम करता है, लेकिन यह सूची को अद्यतन करता है क्योंकि प्रतिलिपि को उल्टे क्रम में वापस करने का विरोध किया जाता है।


3
यह दृष्टिकोण सरणी आधारित सूचियों (जैसे ArrayList) के लिए ठीक हो सकता है लेकिन यह लिंक्ड सूचियों के लिए उप-इष्टतम होगा क्योंकि प्रत्येक प्राप्त करने के लिए प्रत्येक सूची को शुरू से अंत तक (या संभवतः अंत से शुरुआत तक) पीछे हटाना होगा। नेट के समाधान के रूप में एक चतुर पुनरावृत्ति का उपयोग करना बेहतर है (सूची के सभी कार्यान्वयन के लिए इष्टतम)।
क्रिस

1
इसके अलावा, यह ओपी में उस अनुरोध से भटक जाता है जो स्पष्ट रूप से for eachवाक्यविन्यास के लिए कहता है
पॉल डब्ल्यू

8

यह मूल सूची में गड़बड़ी करेगा और लूप के बाहर भी बुलाया जाना चाहिए। इसके अलावा, आप हर बार जब आप लूप को रिवर्स करना चाहते हैं - तो क्या यह सच होगा यदि Iterables.reverse ideasलागू किया गया था?

Collections.reverse(stringList);

for(String string: stringList){
//...do something
}

5

AFAIK मानक पुस्तकालय में एक मानक "रिवर्स_िटरेटर" प्रकार की चीज नहीं है जो प्रत्येक वाक्यविन्यास का समर्थन करता है जो पहले से ही एक वाक्यगत चीनी है जो वे भाषा में देर से लाए थे।

आप इसके लिए कुछ कर सकते हैं (आइटम तत्व: myList.clone ()। उल्टा ()) और संबंधित मूल्य का भुगतान करें।

यह आपको महंगी परिचालनों को करने के सुविधाजनक तरीके न देने की स्पष्ट घटना के साथ भी सुसंगत लगता है - एक सूची के बाद से, परिभाषा के अनुसार, ओ (एन) यादृच्छिक अभिगम जटिलता हो सकती है (आप एकल-लिंक के साथ इंटरफ़ेस को लागू कर सकते हैं), रिवर्स पुनरावृति O (N ^ 2) होने के कारण समाप्त हो सकती है। बेशक, अगर आपके पास एक ArrayList है, तो आप उस कीमत का भुगतान नहीं करते हैं।


आप एक ListIterator को पीछे की ओर चला सकते हैं, जिसे Iterator के भीतर लपेटा जा सकता है।
टॉम हॉल्टिन -

@Tom: अच्छी बात है। हालाँकि, इटरेटर के साथ आप अभी भी छोरों के लिए पुरानी शैली को परेशान कर रहे हैं, और आप अभी भी शुरू करने के लिए अंतिम तत्व प्राप्त करने के लिए लागत का भुगतान कर सकते हैं ... मैंने अपने उत्तर में क्वालीफायर जोड़ा, हालांकि, धन्यवाद।
उरी

Deque में एक उल्टा चलने वाला है।
माइकल मुंसी

2

यह एक विकल्प हो सकता है। आशा है कि अंतिम तत्व से शुरू करने का एक बेहतर तरीका है जबकि लूप से अंत तक।

public static void main(String[] args) {        
    List<String> a = new ArrayList<String>();
    a.add("1");a.add("2");a.add("3");a.add("4");a.add("5");

    ListIterator<String> aIter=a.listIterator();        
    while(aIter.hasNext()) aIter.next();

    for (;aIter.hasPrevious();)
    {
        String aVal = aIter.previous();
        System.out.println(aVal);           
    }
}

2

के रूप में टिप्पणी : आप अपाचे कॉमन्स का उपयोग करने में सक्षम होना चाहिएReverseListIterator

Iterable<String> reverse 
    = new IteratorIterable(new ReverseListIterator(stringList));

for(String string: reverse ){
    //...do something
}

के रूप में @rogerdpack कहा , आप रैप करने के लिए की जरूरत है ReverseListIteratorएक के रूप में Iterable


1

बिना कुछ कस्टम कोड लिखे जो आपको एन्यूमरेटर देगा जो आपके लिए तत्वों को उलट देगा।

आपको Iterable का कस्टम कार्यान्वयन बनाकर जावा में करने में सक्षम होना चाहिए जो तत्वों को रिवर्स ऑर्डर में वापस कर देगा।

फिर, आप रैपर को तुरंत भेज देंगे (या विधि को कॉल कर सकते हैं, जो आपके पास है) जो Iterable कार्यान्वयन को लौटाएगा जो प्रत्येक लूप के लिए तत्व को उलट देता है।



1

यदि आप प्रत्येक सिंटैक्स का उपयोग बॉक्स से बाहर करना चाहते हैं और रिवर्स ऑर्डर में जाना चाहते हैं तो आपको अपने संग्रह को रिवर्स करना होगा।


1

उपरोक्त सभी उत्तर केवल आवश्यकता को पूरा करते हैं, या तो किसी अन्य विधि को लपेटकर या कुछ विदेशी कोड को कॉल करके;

यहाँ जावा 4 वें संस्करण , अध्याय 11.13.1 एडॉप्टरमेथोडीडिओम में थिंकिंग से कॉपी किया गया समाधान है ;

यहाँ कोड है:

// The "Adapter Method" idiom allows you to use foreach
// with additional kinds of Iterables.
package holding;
import java.util.*;

@SuppressWarnings("serial")
class ReversibleArrayList<T> extends ArrayList<T> {
  public ReversibleArrayList(Collection<T> c) { super(c); }
  public Iterable<T> reversed() {
    return new Iterable<T>() {
      public Iterator<T> iterator() {
        return new Iterator<T>() {
          int current = size() - 1; //why this.size() or super.size() wrong?
          public boolean hasNext() { return current > -1; }
          public T next() { return get(current--); }
          public void remove() { // Not implemented
            throw new UnsupportedOperationException();
          }
        };
      }
    };
  }
}   

public class AdapterMethodIdiom {
  public static void main(String[] args) {
    ReversibleArrayList<String> ral =
      new ReversibleArrayList<String>(
        Arrays.asList("To be or not to be".split(" ")));
    // Grabs the ordinary iterator via iterator():
    for(String s : ral)
      System.out.print(s + " ");
    System.out.println();
    // Hand it the Iterable of your choice
    for(String s : ral.reversed())
      System.out.print(s + " ");
  }
} /* Output:
To be or not to be
be to not or be To
*///:~

क्यों int current = size() - 1सही है? क्यों नहीं int current = this.size() - 1याint current = super.size() - 1
qiwen ली


0

निश्चित रूप से इस सवाल का देर से जवाब। एक संभावना एक लूप में लिस्टआईटर का उपयोग करना है। यह बृहदान्त्र-सिंटैक्स के रूप में साफ नहीं है, लेकिन यह काम करता है।

List<String> exampleList = new ArrayList<>();
exampleList.add("One");
exampleList.add("Two");
exampleList.add("Three");

//Forward iteration
for (String currentString : exampleList) {
    System.out.println(currentString); 
}

//Reverse iteration
for (ListIterator<String> itr = exampleList.listIterator(exampleList.size()); itr.hasPrevious(); /*no-op*/ ) {
    String currentString = itr.previous();
    System.out.println(currentString); 
}

ListIterator सिंटैक्स का श्रेय "जावा में एक सूची पर पुनरावृति करने के तरीके" को जाता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.