2010-10-13 14 views
31

से इटरेटर कैसे प्राप्त करें String ऑब्जेक्ट से मुझे Iterator<Character> की आवश्यकता है। जावा में कोई उपलब्ध फ़ंक्शन है जो मुझे यह प्रदान करता है या मुझे अपना कोड कोड करना है? जावा: स्ट्रिंग

+0

यह भी देखें http://stackoverflow.com/questions/1527856/how-can-i-iterate-through-the-unicode-codepoints-of-a-java-string – rogerdpack

उत्तर

29

एक विकल्प इस तरह से काम किया है उपयोग करने के लिए है Guava:

ImmutableList<Character> chars = Lists.charactersOf(someString); 
UnmodifiableListIterator<Character> iter = chars.listIterator(); 

यह अक्षर हैं जो दिया स्ट्रिंग के द्वारा समर्थित है का एक अपरिवर्तनीय सूची का उत्पादन (कोई प्रतिलिपि कॉपी)।

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

public static Iterator<Character> stringIterator(final String string) { 
    // Ensure the error is found as soon as possible. 
    if (string == null) 
    throw new NullPointerException(); 

    return new Iterator<Character>() { 
    private int index = 0; 

    public boolean hasNext() { 
     return index < string.length(); 
    } 

    public Character next() { 
     /* 
     * Throw NoSuchElementException as defined by the Iterator contract, 
     * not IndexOutOfBoundsException. 
     */ 
     if (!hasNext()) 
     throw new NoSuchElementException(); 
     return string.charAt(index++); 
    } 

    public void remove() { 
     throw new UnsupportedOperationException(); 
    } 
    }; 
} 
+2

संकेत के लिए धन्यवाद। तो मुझे लगता है, मेरे प्रश्न का उत्तर "नहीं" है। – Albert

+0

@ अल्बर्ट: हाँ, मुझे नहीं लगता कि मानक पुस्तकालय में कुछ भी है जो आप चाहते हैं। बस उस कोड को इंगित करना जो आप चाहते हैं वह एक ठोस, अच्छी तरह से परीक्षण पुस्तकालय में मौजूद है। – ColinD

+0

@ अल्बर्ट: आप निश्चित रूप से 'स्ट्रिंग # toCharArray()' विधि का उपयोग कर 'लूप' के लिए स्ट्रिंग चार-दर-चार के माध्यम से लूप कर सकते हैं। – Esko

0

सुनिश्चित नहीं है कि कोई और प्रत्यक्ष तरीका है लेकिन आप ऐसा कुछ कर सकते हैं;

Arrays.asList(string.toCharArray()).iterator(); 

स्क्रैच कि; Arrays.asList ऐसा नहीं करता जो मुझे लगता है कि यह कर रहा है।

संपादित करें 2: लगता है जैसे कि यह पिछले में 1.4

+0

लेकिन क्या यह बहुत अक्षम नहीं है? – Albert

+0

हाँ, यह सिर्फ एक तत्व 'Iterator ' बना देगा। – ColinD

+0

आप दोनों सही हैं। मैंने इसे जांच लिया है और शर्म में रोया है। टिप्पणी हटाना मेरा बहाना यह सच के लिए मेरा सबसे अच्छा दिन नहीं है। –

2
CharacterIterator it = new StringCharacterIterator("abcd"); 
// Iterate over the characters in the forward direction 
for (char ch=it.first(); ch != CharacterIterator.DONE; ch=it.next()) 
// Iterate over the characters in the backward direction 
for (char ch=it.last(); ch != CharacterIterator.DONE; ch=it.previous()) 
+2

यह 'Iterator 'नहीं है और मैं वास्तव में यहां केवल ऐसी चीज़ चाहता हूं। – Albert

+0

इस बारे में कैसे: http://www.java2s.com/Code/JavaAPI/java.util/implementsIteratorCharacter.htm – virgium03

+2

@ virgium03: 'Iterable' और' Iterator 'दोनों को कार्यान्वित करना वास्तव में एक बुरा विचार है और इसे कभी नहीं किया जाना चाहिए। – ColinD

0

एक संग्रह से अधिक Iterator पुनरावृति या जो कुछ भी यह लागू करता है। स्ट्रिंग क्लास इस इंटरफ़ेस को लागू नहीं करता है। तो कोई सीधा रास्ता नहीं है।

एक स्ट्रिंग पर फिर से शुरू करने के लिए आपको पहले से एक चार सरणी बनाना होगा और फिर इस char सरणी से संग्रह बनाना होगा।

+6

यह कहना गलत है कि 'Iterator' केवल संग्रह पर पुनरावृत्त होता है। 'इटरेटर' एक साधारण इंटरफ़ेस है जो इसे फिर से लागू करने के लिए लागू किए गए किसी भी चीज़ पर पुन: सक्रिय हो सकता है। – ColinD

+0

+1 आपके पास सही है कि केवल मुझे खो दिया है। –

17

यह मौजूद नहीं है, लेकिन इसे लागू करने के तुच्छ है:

class CharacterIterator implements Iterator<Character> { 

    private final String str; 
    private int pos = 0; 

    public CharacterIterator(String str) { 
     this.str = str; 
    } 

    public boolean hasNext() { 
     return pos < str.length(); 
    } 

    public Character next() { 
     return str.charAt(pos++); 
    } 

    public void remove() { 
     throw new UnsupportedOperationException(); 
    } 
} 

कार्यान्वयन शायद के रूप में यह हो जाता है के रूप में कुशल है।

2

संक्षिप्त उत्तर: नहीं, आपको इसे कोड करना होगा।

लांग जवाब: सूची और दोनों सेट प्राप्त करने के लिए एक विधि है एक Iterator (देखते हैं कुछ अन्य संग्रह कक्षाएं, लेकिन शायद नहीं अपने लिए क्या देख)। सूची और सेट इंटरफेस Collections Framework का एक हिस्सा हैं जो केवल वर्ण या इंटीजर जैसे वस्तुओं को जोड़ने/हटाने/पुन: सक्रिय करने की अनुमति देता है (char या int जैसे प्राइमेटिव नहीं)। Java 1.5 called auto-boxing में एक विशेषता है जो ऑब्जेक्ट रूपांतरण के लिए इस आदिम को छुपाएगी लेकिन मैं इसकी अनुशंसा नहीं करता हूं और यह इस मामले में आप जो चाहते हैं उसे प्रदान नहीं करेगा।

एक वैकल्पिक कि

implements Iterator<Character> 

अपनी खुद की एक कक्षा में स्ट्रिंग रैप करने के लिए होगा, लेकिन है कि अधिक काम हो सकता है की तुलना में इसके लायक है।

String s = ""; 
List<Character> list = new ArrayList<Character>(s.length()); 
for (int i = 0; i < s.length(); i++) { 
    // note that Character.valueOf() is preferred to new Character() 
    // you can omit the Character.valueOf() method 
    // and Java 1.5+ will auto-box the primitive into an Object 
    list.add(Character.valueOf(s.charAt(i))); 
} 
Iterator<Character> iterator = list.iterator(); 
+0

'सूची' और' सेट' ** ** ** 'Iterator' लागू नहीं कर रहे हैं। – whiskeysierra

+0

वे 'Iterable' इंटरफ़ेस को कार्यान्वित कर रहे हैं (जो एक 'इटरेटर()' फ़ंक्शन प्रदान करता है जो 'Iterator' देता है) ताकि ठीक है। लेकिन आपका कोड अक्षम है क्योंकि यह स्ट्रिंग की एक पूर्ण प्रति बनाता है। – Albert

+0

@ विली, आप सही हैं, सूची और सेट इंटरफेस संग्रह के उपनिवेश हैं जिनमें .interator() विधि शामिल है। यदि आप बारीकी से देखते हैं तो यह निजी उप-वर्गों वाले अमूर्त वर्गों को विस्तारित करके पूरा किया जाता है जो वास्तव में इटरेटर को लागू करते हैं, जो सूची या सेट के भीतर डेटा पर पुनरावृत्त होता है। मुझे यह कहना चाहिए था कि सूची और सेट दोनों एक इटरेटर प्राप्त करने के लिए एक विधि प्रदान करते हैं। –

1

कोई सीधा रास्ता:

यहाँ आप क्या चाहते करने के लिए एक कोड का टुकड़ा है। मुश्किल नहीं कोड है, हालांकि करने के लिए:

public static Iterator<Character> gimmeIterator(final String x) { 
     Iterator<Character> it = new Iterator<Character>() { 
      String str = x == null ? "" : x; 
      int pos = -1; // last read 
      public boolean hasNext() { return(pos+1 < str.length()); } 
      public Character next() { pos++; return str.charAt(pos);  } 
      public void remove() { 
       throw new UnsupportedOperationException("remove unsupported for this iterator"); 
      } 
     }; 
     return it; 
    } 
4

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

/** 
* @param string 
* @return list of characters in the string 
*/ 
public static List<Character> characters(final String string) { 
return new AbstractList<Character>() { 
     @Override 
    public Character get(int index) { 
      return string.charAt(index); 
     } 

     @Override 
    public int size() { 
      return string.length(); 
     } 
    }; 
} 
10
for (char c : myString.toCharArray()) { 

} 
+1

यह ऐसे लूप में काम करता है, लेकिन फिर भी 'char [] '' Iterable 'को असाइन करने योग्य नहीं है। –

+2

इसके अलावा, क्योंकि तार अपरिवर्तनीय हैं लेकिन सरणी नहीं हैं, इसे एक प्रतिलिपि बनाना है। – mhsmith

1

यह अपाचे कॉमन्स लैंग से थोड़ी मदद से किया जा सकता है (आप अमरूद का उपयोग नहीं करना चाहते हैं, और एक सच्चे java.util.Iterator चाहते हैं।

private static Iterator<Character> iterator(String string) { 
    return Arrays.asList(ArrayUtils.toObject(string.toCharArray())).iterator(); 
} 
0

जावा 8 या के साथ नया आप स्ट्रीम सुविधा का उपयोग कर सकते हैं। chars() विधि के साथ आप IntStream तक पहुंच सकते हैं। IntStreamiterator() विधि का समर्थन करता है जो OfInt इटरेटर देता है। OfInt लागू Iterator<Integer>

String str = "foobar"; 
OfInt ofit = str.chars().iterator(); 
Iterator<Integer> it = ofit; 

यह एक आदर्श जवाब है, जब से तुम इटरेटर < चरित्र > के लिए नहीं कहा है।

बीटीडब्ल्यू: str.codePoints() के साथ आप एक कोड बिंदु IntStream भी एक्सेस कर सकते हैं।

+0

आप कोडपॉइंट्स() का उल्लेख करते हैं। कोडपॉइंट्स() का एक महत्वपूर्ण पहलू यह है कि यह आपको सरोगेट वर्णों से निपटने की अनुमति देता है। [यह उत्तर] देखें (http://stackoverflow.com/a/40444598/99717)। –

0

यह गंदा लगता है, लेकिन आप रिक्त स्ट्रिंग सीमांकक के साथ स्कैनर इस्तेमाल कर सकते हैं:

Scanner scanner = new java.util.Scanner(myInput).useDelimiter(""); 

स्कैनर लागू करता Iterator, तो scanner अब लंबाई -1 तार है, जो करीब है की एक Iterator है।

को जारी रखने के गंदे, जावा 8 में आप तो ऐसा कर सकते हैं संक्षेप वर्ण से पुनरावृति करने के लिए (बहुत?):

for (String s: (Iterable<String>)() -> scanner) { 
    char c = s.charAt(0); 
    System.out.println(c); 
} 
क्यों () -> scanner कार्यों पर

जानकारी के लिए (और क्यों यह खतरनाक है, हालांकि हो सकता है इस उपयोग मामले में नहीं), Explain how this lambda can be assigned to an Iterable देखें।

संबंधित मुद्दे