ग्रोवी के साथ स्ट्रिंग संघनन


91

ग्रूवी में स्ट्रिंग्स को समेटने का सबसे अच्छा (मुहावरेदार) तरीका क्या है?

विकल्प 1:

calculateAccountNumber(bank, branch, checkDigit, account) {
    bank + branch + checkDigit + account
}

विकल्प 2:

calculateAccountNumber(bank, branch, checkDigit, account) {
    "$bank$branch$checkDigit$account"
}

मैंने पुरानी ग्रूवी वेबसाइट में इस विषय के बारे में एक दिलचस्प बिंदु स्थापित किया है: चीजें जो आप कर सकते हैं लेकिन बेहतर तरीके से छोड़ दें।

जैसा कि जावा में, आप स्ट्रिंग्स को "+" प्रतीक के साथ समेट सकते हैं। लेकिन जावा को केवल एक स्ट्रिंग के होने के लिए "+" अभिव्यक्ति की दो वस्तुओं में से एक की आवश्यकता होती है, भले ही वह पहले स्थान पर हो या आखिरी में। जावा आपके "+" एक्सप्रेशन की नॉन-स्ट्रिंग ऑब्जेक्ट में स्ट्रैसिंग () पद्धति का उपयोग करेगा। लेकिन ग्रूवी में, आपको बस अपने "+" अभिव्यक्ति के पहले आइटम को सही तरीके से लागू करना चाहिए () विधि को सही तरीके से लागू करना चाहिए, क्योंकि ग्रूवी खोज और इसका उपयोग करेगा। ग्रूवी जीडीके में, केवल संख्या और स्ट्रिंग / स्ट्रिंगबफ़र / चरित्र वर्गों में स्ट्रिंग को समेटने के लिए लागू प्लस () विधि है। आश्चर्य से बचने के लिए, हमेशा GStrings का उपयोग करें।

जवाबों:


122

मैं हमेशा दूसरी विधि (GString टेम्पलेट का उपयोग करके) के लिए जाता हूं, हालांकि जब आपके पास दो से अधिक पैरामीटर होते हैं, तो मैं उन्हें लपेटता हूं ${X}क्योंकि मुझे लगता है कि यह इसे अधिक पठनीय बनाता है।

इन तरीकों पर कुछ बेंचमार्क ( नागाई मैसाटो के उत्कृष्ट GBench मॉड्यूल का उपयोग करके ) चलाना भी दिखाता है कि गति अन्य तरीकों की तुलना में तेज़ है:

@Grab( 'com.googlecode.gbench:gbench:0.3.0-groovy-2.0' )
import gbench.*

def (foo,bar,baz) = [ 'foo', 'bar', 'baz' ]
new BenchmarkBuilder().run( measureCpuTime:false ) {
  // Just add the strings
  'String adder' {
    foo + bar + baz
  }
  // Templating
  'GString template' {
    "$foo$bar$baz"
  }
  // I find this more readable
  'Readable GString template' {
    "${foo}${bar}${baz}"
  }
  // StringBuilder
  'StringBuilder' {
    new StringBuilder().append( foo )
                       .append( bar )
                       .append( baz )
                       .toString()
  }
  'StringBuffer' {
    new StringBuffer().append( foo )
                      .append( bar )
                      .append( baz )
                      .toString()
  }
}.prettyPrint()

यह मुझे मेरी मशीन पर निम्न आउटपुट देता है:

Environment
===========
* Groovy: 2.0.0
* JVM: Java HotSpot(TM) 64-Bit Server VM (20.6-b01-415, Apple Inc.)
    * JRE: 1.6.0_31
    * Total Memory: 81.0625 MB
    * Maximum Memory: 123.9375 MB
* OS: Mac OS X (10.6.8, x86_64) 

Options
=======
* Warm Up: Auto 
* CPU Time Measurement: Off

String adder               539
GString template           245
Readable GString template  244
StringBuilder              318
StringBuffer               370

तो यह पठनीयता और गति के पक्ष में है, मैं टेम्प्लेट करने की सलाह दूंगा ;-)

ध्यान दें: आप जोड़ देते हैं तो toString()उत्पादन अन्य मैट्रिक्स के रूप में ही टाइप बनाने के लिए gstring तरीकों के अंत तक, और यह एक न्यायपूर्ण परीक्षण करते हैं, StringBuilderऔर StringBufferहरा गति के लिए gstring तरीकों। हालाँकि स्ट्रिंग के स्थान पर ज्यादातर चीजों के लिए स्ट्रिंग का इस्तेमाल किया जा सकता है (आपको बस मैप कीज़ और एसक्यूएल स्टेटमेंट के साथ सावधानी बरतने की ज़रूरत है), यह ज्यादातर इस अंतिम रूपांतरण के बिना छोड़ा जा सकता है

इन परीक्षणों को जोड़ना (जैसा कि टिप्पणियों में पूछा गया है)

  'GString template toString' {
    "$foo$bar$baz".toString()
  }
  'Readable GString template toString' {
    "${foo}${bar}${baz}".toString()
  }

अब हमें परिणाम मिलते हैं:

String adder                        514
GString template                    267
Readable GString template           269
GString template toString           478
Readable GString template toString  480
StringBuilder                       321
StringBuffer                        369

इसलिए जैसा कि आप देख सकते हैं (जैसा कि मैंने कहा था), यह स्ट्रिंगबर्ल या स्ट्रिंगबर्गर की तुलना में धीमी है, लेकिन स्ट्रिंग्स को जोड़ने की तुलना में अभी भी थोड़ा तेज है ...

लेकिन अभी भी बहुत अधिक पठनीय है।

नीचे ग्रामीणकर द्वारा टिप्पणी के बाद संपादित करें

नवीनतम गैबच को अपडेट किया जाता है, संघनन के लिए बड़े तार और एक स्ट्रिंगब्रिज के साथ एक परीक्षण जो कि एक अच्छे आकार के लिए शुरू होता है:

@Grab( 'org.gperfutils:gbench:0.4.2-groovy-2.1' )

def (foo,bar,baz) = [ 'foo' * 50, 'bar' * 50, 'baz' * 50 ]
benchmark {
  // Just add the strings
  'String adder' {
    foo + bar + baz
  }
  // Templating
  'GString template' {
    "$foo$bar$baz"
  }
  // I find this more readable
  'Readable GString template' {
    "${foo}${bar}${baz}"
  }
  'GString template toString' {
    "$foo$bar$baz".toString()
  }
  'Readable GString template toString' {
    "${foo}${bar}${baz}".toString()
  }
  // StringBuilder
  'StringBuilder' {
    new StringBuilder().append( foo )
                       .append( bar )
                       .append( baz )
                       .toString()
  }
  'StringBuffer' {
    new StringBuffer().append( foo )
                      .append( bar )
                      .append( baz )
                      .toString()
  }
  'StringBuffer with Allocation' {
    new StringBuffer( 512 ).append( foo )
                      .append( bar )
                      .append( baz )
                      .toString()
  }
}.prettyPrint()

देता है

Environment
===========
* Groovy: 2.1.6
* JVM: Java HotSpot(TM) 64-Bit Server VM (23.21-b01, Oracle Corporation)
    * JRE: 1.7.0_21
    * Total Memory: 467.375 MB
    * Maximum Memory: 1077.375 MB
* OS: Mac OS X (10.8.4, x86_64)

Options
=======
* Warm Up: Auto (- 60 sec)
* CPU Time Measurement: On

                                    user  system  cpu  real

String adder                         630       0  630   647
GString template                      29       0   29    31
Readable GString template             32       0   32    33
GString template toString            429       0  429   443
Readable GString template toString   428       1  429   441
StringBuilder                        383       1  384   396
StringBuffer                         395       1  396   409
StringBuffer with Allocation         277       0  277   286

3
मैं सुस्पष्टता के लिए GString टेम्प्लेट का उपयोग करने से असहमत नहीं हूँ, लेकिन आपको .toString()दो GString परीक्षणों में संलग्न परीक्षणों को फिर से चलाना चाहिए । मेरे रन से पता चलता है कि वे लगभग उसी तरह प्रदर्शन करते हैं String adder। मेरा अनुमान है कि आपने जो परीक्षण चलाया है, वह वास्तव में संगति को संभाल नहीं रहा है, इसलिए यह सिर्फ एक GString ऑब्जेक्ट बना रहा है और संदर्भ संग्रहीत कर रहा है। StringBuilderअभी भी सबसे तेज़ है, हाथ नीचे, अगर आपको Stringकिसी बिंदु पर ज़रूरत है ।
ओवरलेलियस जूल

1
मुझे किसी भी तरह दूसरी छमाही याद आती है! बेशक, भले ही आप GString"के रूप में " छोड़ दें , कुछ बिंदु पर इसे एक सच्चे में बदलना होगा String, (यहां तक ​​कि इसे प्रिंट करने के लिए भी), इसलिए सही समय अंतिम सेट है। अंत में GStringटेम्प्लेट की सुगमता समाप्त हो जाती है, StringBuilderजब समय समाप्त हो जाता है, इसलिए यह मूट है। :-)
१०:

2
@OverZealous आह्ह हाँ, हमेशा की तरह, झूठ, झूठ और बेंचमार्क; ;-) पठनीयता यहाँ महत्वपूर्ण है मुझे लगता है और जैसा कि हम पहले से ही Groovy का उपयोग कर रहे हैं, हमने कहा है कि नंगे-धातु का प्रदर्शन हमारा प्रमुख विचार नहीं है; -)
टाइम_बेट्स

1
हाँ, GStrings के महान लाभों में से एक यह है कि वे अंतिम क्षण तक तार में परिवर्तित नहीं होते हैं। जिसका अर्थ है, उदाहरण के लिए, यदि आप लॉगिंग थ्रेशोल्ड के नीचे लॉग 4j जैसे लॉगगर के साथ एक GString लॉग करते हैं, तो GString कभी भी परिवर्तित नहीं होती है।
ataylor

1
परीक्षण से क्या गायब है गणना की गई क्षमता के साथ स्ट्रिंगबर्ल है। कारण यह है कि फू + बार + बाज एक या दो बफर विस्तार का कारण होगा जो समय में जोड़ता है।
ruralcoder

19
def my_string = "some string"
println "here: " + my_string 

यह निश्चित नहीं है कि ऊपर दिए गए उत्तर को बेंचमार्क, स्ट्रिंग बफर, टेस्ट आदि में जाने की आवश्यकता क्यों है।


1
सादगी के लिए अपवोट करें। मुझे बस दो तारों को समेटने की जरूरत है। lol
harperville

1

वर्तमान हार्डवेयर पर tim_yates के उत्तर को पुन: प्रस्तुत करना और खोज को जांचने के लिए बायेंशिफ्ट () और कॉनकट () विधि को जोड़ना:

  'String leftShift' {
    foo << bar << baz
  }
  'String concat' {
    foo.concat(bar)
       .concat(baz)
       .toString()
  }

परिणाम शुद्ध स्ट्रिंग के लिए कॉनैट () को तेज समाधान दिखाता है, लेकिन यदि आप कहीं और स्ट्रिंग को संभाल सकते हैं, तो GString टेम्पलेट अभी भी आगे है, जबकि माननीय उल्लेख को बाएं () (बिटवाइज़र ऑपरेटर) और स्ट्रिंगरबफ़र () को प्रारंभिक के साथ जाना चाहिए आवंटन:

Environment
===========
* Groovy: 2.4.8
* JVM: OpenJDK 64-Bit Server VM (25.191-b12, Oracle Corporation)
    * JRE: 1.8.0_191
    * Total Memory: 238 MB
    * Maximum Memory: 3504 MB
* OS: Linux (4.19.13-300.fc29.x86_64, amd64)

Options
=======
* Warm Up: Auto (- 60 sec)
* CPU Time Measurement: On

                                    user  system  cpu  real

String adder                         453       7  460   469
String leftShift                     287       2  289   295
String concat                        169       1  170   173
GString template                      24       0   24    24
Readable GString template             32       0   32    32
GString template toString            400       0  400   406
Readable GString template toString   412       0  412   419
StringBuilder                        325       3  328   334
StringBuffer                         390       1  391   398
StringBuffer with Allocation         259       1  260   265
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.