StringTokenizer
? कन्वर्ट String
एक करने के लिए char[]
और दोहराएं उस पर? कुछ और?
StringTokenizer
? कन्वर्ट String
एक करने के लिए char[]
और दोहराएं उस पर? कुछ और?
जवाबों:
मैं स्ट्रिंग को पुनरावृत्त करने के लिए लूप के लिए उपयोग करता हूं और charAt()
प्रत्येक चरित्र को जांचने के लिए उपयोग करता हूं । चूंकि स्ट्रिंग एक सरणी के साथ कार्यान्वित की जाती है, इसलिए charAt()
विधि एक निरंतर समय ऑपरेशन है।
String s = "...stuff...";
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
//Process char
}
यही मैं करता। यह मुझे सबसे आसान लगता है।
जहाँ तक शुद्धता की बात है, मुझे विश्वास नहीं है कि यहाँ मौजूद है। यह सब आपकी व्यक्तिगत शैली पर आधारित है।
String.charAt(int)
केवल कर रहा है value[index]
। मुझे लगता है कि आप chatAt()
कुछ और के साथ भ्रमित कर रहे हैं जो आपको कोड अंक देता है।
दो विकल्प
for(int i = 0, n = s.length() ; i < n ; i++) {
char c = s.charAt(i);
}
या
for(char c : s.toCharArray()) {
// process c
}
पहला शायद तेज है, तो दूसरा शायद अधिक पठनीय है।
ध्यान दें कि यहां वर्णित अधिकांश तकनीकों को तोड़ दिया जाता है यदि आप बीएमपी (यूनिकोड बेसिक मल्टीलिंगुअल प्लेन ) के बाहर के वर्णों के साथ काम कर रहे हैं , यानी कोड पॉइंट जो कि u0000-uFFFF रेंज के बाहर हैं। यह केवल शायद ही कभी होगा, क्योंकि इसके बाहर कोड बिंदु ज्यादातर मृत भाषाओं को सौंपे जाते हैं। लेकिन इसके बाहर कुछ उपयोगी पात्र हैं, उदाहरण के लिए गणितीय संकेतन के लिए उपयोग किए जाने वाले कुछ कोड बिंदु, और कुछ का उपयोग चीनी में उचित नामों को एनकोड करने के लिए किया जाता है।
उस स्थिति में आपका कोड होगा:
String str = "....";
int offset = 0, strLen = str.length();
while (offset < strLen) {
int curChar = str.codePointAt(offset);
offset += Character.charCount(curChar);
// do something with curChar
}
Character.charCount(int)
विधि जावा 5 + की आवश्यकता है।
मैं मानता हूं कि स्ट्रिंगट्रॉकेनाइजर यहां ओवरकिल है। वास्तव में मैंने ऊपर दिए गए सुझावों की कोशिश की और समय लिया।
मेरा परीक्षण काफी सरल था: लगभग एक लाख वर्णों के साथ एक स्ट्रिंगबर्स्ट बनाएं, इसे एक स्ट्रिंग में परिवर्तित करें, और उनमें से प्रत्येक को charAt () / / के बाद चार्ट वर्ण में बदलने के साथ / एक हजार अक्षरों के साथ एक हजार बार / निश्चित रूप से सुनिश्चित करें। स्ट्रिंग पर कुछ करें ताकि कंपाइलर पूरे लूप को दूर न कर सके :-))।
मेरी 2.6 गीगाहर्ट्ज पॉवरबुक (जो कि मैक :-)) और जेडीके 1.5 पर परिणाम:
जैसा कि परिणाम काफी अलग हैं, सबसे सीधा तरीका भी सबसे तेज़ लगता है। दिलचस्प बात यह है कि एक स्ट्रिंगबर्ल का चार्ज () स्ट्रिंग के एक की तुलना में थोड़ा धीमा लगता है।
BTW मैं सुझाव देता हूं कि कैरेक्टरेटर का उपयोग न करें क्योंकि मैं '\ uFFFF' चरित्र के अपने दुरुपयोग को "पुनरावृत्ति का अंत" के रूप में मानता हूं जो वास्तव में भयानक हैक है। बड़ी परियोजनाओं में हमेशा दो लोग होते हैं जो दो अलग-अलग उद्देश्यों के लिए एक ही तरह की हैक का उपयोग करते हैं और कोड वास्तव में रहस्यमय तरीके से क्रैश होता है।
यहाँ परीक्षणों में से एक है:
int count = 1000;
...
System.out.println("Test 1: charAt + String");
long t = System.currentTimeMillis();
int sum=0;
for (int i=0; i<count; i++) {
int len = str.length();
for (int j=0; j<len; j++) {
if (str.charAt(j) == 'b')
sum = sum + 1;
}
}
t = System.currentTimeMillis()-t;
System.out.println("result: "+ sum + " after " + t + "msec");
में जावा 8 हम इसे के रूप में हल कर सकते हैं:
String str = "xyz";
str.chars().forEachOrdered(i -> System.out.print((char)i));
str.codePoints().forEachOrdered(i -> System.out.print((char)i));
विधि वर्ण () डॉकIntStream
में उल्लिखित है :
इस क्रम से चार मानों को बढ़ाते हुए int शून्य की धारा लौटाता है। कोई भी चार्ट जो एक सरोगेट कोड बिंदु पर मैप करता है, उसे बिना किसी व्याख्या के पास किया जाता है। यदि धारा को पढ़ा जा रहा है, तो अनुक्रम उत्परिवर्तित है, परिणाम अपरिभाषित है।
विधि codePoints()
भी IntStream
डॉक्टर के अनुसार रिटर्न करती है :
इस क्रम से कोड बिंदु मानों की एक धारा लौटाता है। अनुक्रम में सामना किए गए किसी भी सरोगेट जोड़े को संयुक्त रूप से किया जाता है जैसे कि Character.toCodePoint द्वारा किया जाता है और परिणाम स्ट्रीम में पास किया जाता है। साधारण बीएमपी वर्ण, अशिक्षित सरोगेट और अपरिभाषित कोड इकाइयाँ सहित कोई भी अन्य कोड इकाइयाँ उन अंतर मानों के लिए शून्य-विस्तारित होती हैं जिन्हें तब स्ट्रीम में पास किया जाता है।
कैसे चार और कोड बिंदु अलग है? जैसा कि इस लेख में बताया गया है :
यूनिकोड 3.1 ने अनुपूरक वर्ण जोड़े, कुल वर्णों की संख्या 216 से अधिक वर्णों तक ला दी, जिन्हें एक एकल 16-बिट द्वारा प्रतिष्ठित किया जा सकता है
char
। इसलिए,char
मान का अब यूनिकोड में मौलिक अर्थ इकाई के लिए एक-से-एक मानचित्रण नहीं है। JDK 5 चरित्र मूल्यों के बड़े सेट का समर्थन करने के लिए अद्यतन किया गया था।char
प्रकार की परिभाषा को बदलने के बजाय , कुछ नए पूरक वर्णों का प्रतिनिधित्व दोchar
मूल्यों की सरोगेट जोड़ी द्वारा किया जाता है । नामकरण भ्रम को कम करने के लिए, एक कोड बिंदु का उपयोग उस संख्या को संदर्भित करने के लिए किया जाएगा जो एक विशेष यूनिकोड चरित्र का प्रतिनिधित्व करता है, जिसमें पूरक भी शामिल हैं।
आखिर क्यों forEachOrdered
और क्यों नहीं forEach
?
forEach
स्पष्ट रूप से nondeterministic का व्यवहार जहां forEachOrdered
धारा के मुठभेड़ क्रम में इस धारा के प्रत्येक तत्व के लिए एक क्रिया करता है, यदि धारा में एक मुठभेड़ आदेश है। इसलिए forEach
गारंटी नहीं देता कि ऑर्डर रखा जाएगा। इस प्रश्न को और भी देखें।
एक चरित्र, एक कोड बिंदु, एक ग्लिफ़ और एक अंगूर के बीच अंतर के लिए , इस प्रश्न की जांच करें ।
इसके लिए कुछ समर्पित वर्ग हैं:
import java.text.*;
final CharacterIterator it = new StringCharacterIterator(s);
for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
// process c
...
}
char
प्रदान किए जाने की तुलना में अधिक स्थान की आवश्यकता होती है । एक जावा char
में 16 बिट होते हैं और यू + एफएफएफएफ तक यूनिकोड के पात्रों को पकड़ सकता है लेकिन यूनिकोड यू + 10 एफएफएफ तक के वर्णों को निर्दिष्ट करता है। 16 बिट्स का उपयोग करके यूनिकोड के परिणाम को एक चर लंबाई वर्ण एन्कोडिंग में एन्कोड किया जाता है। इस पृष्ठ पर अधिकांश उत्तर मानते हैं कि जावा एन्कोडिंग एक निरंतर लंबाई एन्कोडिंग है, जो गलत है।
यदि आपके पास अपने क्लासपाथ पर अमरूद है , तो निम्नलिखित एक बहुत ही पठनीय विकल्प है। अमरूद में इस मामले के लिए काफी समझदार कस्टम सूची कार्यान्वयन है, इसलिए यह अक्षम नहीं होना चाहिए।
for(char c : Lists.charactersOf(yourString)) {
// Do whatever you want
}
अद्यतन: जैसा कि @Alex ने उल्लेख किया है, जावा 8 के साथ भी CharSequence#chars
उपयोग करना है। यहां तक कि प्रकार IntStream है, इसलिए इसे चार्ट में मैप किया जा सकता है जैसे:
yourString.chars()
.mapToObj(c -> Character.valueOf((char) c))
.forEach(c -> System.out.println(c)); // Or whatever you want
यदि आपको कोड के बिंदुओं के माध्यम से पुनरावृति करने की आवश्यकता है String
(इस उत्तर को देखें ) एक छोटा / अधिक पठनीय तरीका है CharSequence#codePoints
जावा 8 में जोड़े गए विधि का उपयोग करना :
for(int c : string.codePoints().toArray()){
...
}
या लूप के बजाय सीधे स्ट्रीम का उपयोग कर:
string.codePoints().forEach(c -> ...);
CharSequence#chars
यदि आप पात्रों की एक धारा चाहते हैं, तो भी है (हालांकि यह एक है IntStream
, क्योंकि कोई नहीं है CharStream
)।
मैं इसका उपयोग नहीं करूंगा StringTokenizer
क्योंकि यह JDK की विरासत की कक्षाओं में से एक है।
जावदोक कहता है:
StringTokenizer
एक विरासत वर्ग है जिसे संगतता कारणों से रखा जाता है, हालांकि इसका उपयोग नए कोड में हतोत्साहित किया जाता है। यह अनुशंसा की जाती है कि इस कार्यक्षमता को प्राप्त करने वाला कोई भी इसके बजायString
याjava.util.regex
पैकेज की विभाजन विधि का उपयोग करे।
यदि आपको प्रदर्शन की आवश्यकता है, तो आपको अपने पर्यावरण पर परीक्षण करना होगा । कोई और तरीका नहीं।
यहाँ उदाहरण कोड:
int tmp = 0;
String s = new String(new byte[64*1024]);
{
long st = System.nanoTime();
for(int i = 0, n = s.length(); i < n; i++) {
tmp += s.charAt(i);
}
st = System.nanoTime() - st;
System.out.println("1 " + st);
}
{
long st = System.nanoTime();
char[] ch = s.toCharArray();
for(int i = 0, n = ch.length; i < n; i++) {
tmp += ch[i];
}
st = System.nanoTime() - st;
System.out.println("2 " + st);
}
{
long st = System.nanoTime();
for(char c : s.toCharArray()) {
tmp += c;
}
st = System.nanoTime() - st;
System.out.println("3 " + st);
}
System.out.println("" + tmp);
पर जावा ऑनलाइन मैं मिलता है:
1 10349420
2 526130
3 484200
0
Android पर x86 API 17 मुझे मिलता है:
1 9122107
2 13486911
3 12700778
0
जावा ट्यूटोरियल देखें : स्ट्रिंग्स ।
public class StringDemo {
public static void main(String[] args) {
String palindrome = "Dot saw I was Tod";
int len = palindrome.length();
char[] tempCharArray = new char[len];
char[] charArray = new char[len];
// put original string in an array of chars
for (int i = 0; i < len; i++) {
tempCharArray[i] = palindrome.charAt(i);
}
// reverse array of chars
for (int j = 0; j < len; j++) {
charArray[j] = tempCharArray[len - 1 - j];
}
String reversePalindrome = new String(charArray);
System.out.println(reversePalindrome);
}
}
लंबाई डालें int len
और for
लूप का उपयोग करें ।
StringTokenizer अपने व्यक्तिगत पात्रों में एक स्ट्रिंग को तोड़ने के कार्य के लिए पूरी तरह से अनुपयुक्त है। साथ String#split()
आपको लगता है कि आसानी से कर सकते एक regex कि कुछ भी नहीं है, जैसे मेल खाता का उपयोग करके:
String[] theChars = str.split("|");
लेकिन StringTokenizer regexes का उपयोग नहीं करता है, और वहाँ कोई सीमांकक स्ट्रिंग नहीं है जो आप निर्दिष्ट कर सकते हैं कि वर्णों के बीच कुछ भी मेल नहीं खाएगा। वहाँ है स्वयं स्ट्रिंग का उपयोग सीमांकक स्ट्रिंग के रूप में (एक परिसीमक उस में हर चरित्र बनाने) और है यह सीमांकक वापसी: एक प्यारा थोड़ा तुम इसी कार्य को पूरा करने के लिए उपयोग कर सकते हैं हैक:
StringTokenizer st = new StringTokenizer(str, str, true);
हालाँकि, मैं केवल उन्हें खारिज करने के उद्देश्य के लिए इन विकल्पों का उल्लेख करता हूं। दोनों तकनीकें मूल प्राइमरी स्ट्रिंग को चार प्राथमिकताओं के बजाय वन-कैरेक्टर स्ट्रिंग्स में तोड़ती हैं, और दोनों ऑब्जेक्ट निर्माण और स्ट्रिंग हेरफेर के रूप में ओवरहेड का एक बड़ा सौदा शामिल करते हैं। तुलना करें कि लूप के लिए कॉलिंग () लूप में, जो लगभग ओवरहेड नहीं है।
इस जवाब और इस जवाब पर विस्तार से ।
ऊपर दिए गए उत्तर कई समाधानों की समस्या की ओर इशारा करते हैं, जो कोड पॉइंट वैल्यू द्वारा पुनरावृति नहीं करते हैं - उन्हें किसी भी सरोगेट चार्ट से परेशानी होगी । जावा डॉक्स भी इस मुद्दे को रेखांकित करता है ("यूनिकोड कैरेक्टर रिप्रेजेंटेशन" देखें)। किसी भी तरह, यहाँ कुछ कोड है जो पूरक यूनिकोड सेट से कुछ वास्तविक सरोगेट वर्णों का उपयोग करता है, और उन्हें वापस स्ट्रिंग में परिवर्तित करता है । ध्यान दें कि .toChars () वर्णों की एक सरणी देता है: यदि आप सरोगेट्स के साथ काम कर रहे हैं, तो आपको आवश्यक रूप से दो वर्ण होंगे। यह कोड किसी भी यूनिकोड वर्ण के लिए काम करना चाहिए ।
String supplementary = "Some Supplementary: 𠜎𠜱𠝹𠱓";
supplementary.codePoints().forEach(cp ->
System.out.print(new String(Character.toChars(cp))));
यह उदाहरण कोड आपकी सहायता करेगा!
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class Solution {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 10);
map.put("b", 30);
map.put("c", 50);
map.put("d", 40);
map.put("e", 20);
System.out.println(map);
Map sortedMap = sortByValue(map);
System.out.println(sortedMap);
}
public static Map sortByValue(Map unsortedMap) {
Map sortedMap = new TreeMap(new ValueComparator(unsortedMap));
sortedMap.putAll(unsortedMap);
return sortedMap;
}
}
class ValueComparator implements Comparator {
Map map;
public ValueComparator(Map map) {
this.map = map;
}
public int compare(Object keyA, Object keyB) {
Comparable valueA = (Comparable) map.get(keyA);
Comparable valueB = (Comparable) map.get(keyB);
return valueB.compareTo(valueA);
}
}
इसलिए आम तौर पर जावा में स्ट्रिंग के माध्यम से पुनरावृति करने के दो तरीके हैं जो पहले से ही इस धागे में कई लोगों द्वारा उत्तर दिए गए हैं, बस इसके संस्करण को जोड़ना सबसे पहले उपयोग कर रहा है
String s = sc.next() // assuming scanner class is defined above
for(int i=0; i<s.length; i++){
s.charAt(i) // This being the first way and is a constant time operation will hardly add any overhead
}
char[] str = new char[10];
str = s.toCharArray() // this is another way of doing so and it takes O(n) amount of time for copying contents from your string class to character array
यदि प्रदर्शन दांव पर है, तो मैं निरंतर समय में पहले एक का उपयोग करने की सिफारिश करूंगा, अगर ऐसा नहीं है तो दूसरे के साथ जा रहा है जो जावा में स्ट्रिंग कक्षाओं के साथ अपरिवर्तनीयता को देखते हुए आपके काम को आसान बनाता है।