की समय जटिलता क्या है String#substring()
जावा में विधि ?
की समय जटिलता क्या है String#substring()
जावा में विधि ?
जवाबों:
नया जवाब
जावा 7 के जीवनकाल में अपडेट 6 के रूप में, substring
प्रतिलिपि बनाने के लिए बदले जाने का व्यवहार - इसलिए प्रत्येक को String
संदर्भित किया जाता है char[]
जिसे किसी अन्य वस्तु के साथ साझा नहीं किया जाता है, जहां तक मैं जागरूक हूं। तो उस बिंदु पर, substring()
एक ओ (एन) ऑपरेशन बन गया जहां एन सबस्ट्रिंग में संख्याएं हैं।
पुराना उत्तर: प्री-जावा Java
अनिर्धारित - लेकिन अभ्यास में ओ (1) यदि आप मानते हैं कि कोई कचरा संग्रह की आवश्यकता नहीं है, आदि।
यह एक String
ही अंतर्निहित के char[]
साथ एक नई वस्तु बनाता है, लेकिन अलग-अलग ऑफसेट और गणना मूल्यों के साथ। तो लागत सत्यापन करने और एक नई (यथोचित छोटी) वस्तु के निर्माण में लगने वाला समय है। यह ओ (1) है जहाँ तक संचालन की जटिलता के बारे में बात करना समझदारी है जो कचरा संग्रहण, सीपीयू कैश इत्यादि के आधार पर अलग-अलग हो सकता है। विशेष रूप से, यह सीधे मूल स्ट्रिंग की लंबाई या विकल्प पर निर्भर नहीं करता है ।
यह जावा के पुराने संस्करणों में O (1) था - जैसा कि जॉन ने कहा, उसने बस एक ही अंतर्निहित चार [], और एक अलग ऑफसेट और लंबाई के साथ एक नया स्ट्रिंग बनाया।
हालाँकि, यह वास्तव में जावा 7 अपडेट 6 से शुरू हुआ है।
चार [] साझाकरण को समाप्त कर दिया गया था, और ऑफसेट और लंबाई फ़ील्ड हटा दिए गए थे। सबस्ट्रिंग () अब बस सभी पात्रों को एक नए स्ट्रिंग में कॉपी करता है।
जावा 7 अपडेट 6 में Ergo, substring O (n) है
char[]
...
यह अब रैखिक जटिलता है। यह प्रतिस्थापन के लिए स्मृति रिसाव समस्या को ठीक करने के बाद है।
तो Java 1.7.0_06 से याद रखें कि String.substring में अब स्थिरांक के बजाय एक रैखिक जटिलता है।
जॉन के जवाब के लिए सबूत जोड़ना। मुझे एक ही संदेह था और यह जांचना चाहता था कि स्ट्रिंग की लंबाई का फंक्शनिंग फ़ंक्शन पर कोई प्रभाव पड़ता है या नहीं। निम्नलिखित पैरामीटर को जांचने के लिए कोड लिखा गया है, जो वास्तव में निर्भर करता है।
import org.apache.commons.lang.RandomStringUtils;
public class Dummy {
private static final String pool[] = new String[3];
private static int substringLength;
public static void main(String args[]) {
pool[0] = RandomStringUtils.random(2000);
pool[1] = RandomStringUtils.random(10000);
pool[2] = RandomStringUtils.random(100000);
test(10);
test(100);
test(1000);
}
public static void test(int val) {
substringLength = val;
StatsCopy statsCopy[] = new StatsCopy[3];
for (int j = 0; j < 3; j++) {
statsCopy[j] = new StatsCopy();
}
long latency[] = new long[3];
for (int i = 0; i < 10000; i++) {
for (int j = 0; j < 3; j++) {
latency[j] = latency(pool[j]);
statsCopy[j].send(latency[j]);
}
}
for (int i = 0; i < 3; i++) {
System.out.println(
" Avg: "
+ (int) statsCopy[i].getAvg()
+ "\t String length: "
+ pool[i].length()
+ "\tSubstring Length: "
+ substringLength);
}
System.out.println();
}
private static long latency(String a) {
long startTime = System.nanoTime();
a.substring(0, substringLength);
long endtime = System.nanoTime();
return endtime - startTime;
}
private static class StatsCopy {
private long count = 0;
private long min = Integer.MAX_VALUE;
private long max = 0;
private double avg = 0;
public void send(long latency) {
computeStats(latency);
count++;
}
private void computeStats(long latency) {
if (min > latency) min = latency;
if (max < latency) max = latency;
avg = ((float) count / (count + 1)) * avg + (float) latency / (count + 1);
}
public double getAvg() {
return avg;
}
public long getMin() {
return min;
}
public long getMax() {
return max;
}
public long getCount() {
return count;
}
}
}
जावा 8 में निष्पादन पर आउटपुट है:
Avg: 128 String length: 2000 Substring Length: 10
Avg: 127 String length: 10000 Substring Length: 10
Avg: 124 String length: 100000 Substring Length: 10
Avg: 172 String length: 2000 Substring Length: 100
Avg: 175 String length: 10000 Substring Length: 100
Avg: 177 String length: 100000 Substring Length: 100
Avg: 1199 String length: 2000 Substring Length: 1000
Avg: 1186 String length: 10000 Substring Length: 1000
Avg: 1339 String length: 100000 Substring Length: 1000
सबस्ट्रिंग फ़ंक्शन फ़ंक्शन स्ट्रिंग की लंबाई पर अनुरोध किए गए सबस्ट्रिंग की लंबाई पर निर्भर करता है।
निम्नलिखित में से खुद के लिए न्यायाधीश, लेकिन जावा के प्रदर्शन की कमियां कहीं और झूठ हैं, यहां स्ट्रिंग के विकल्प में नहीं। कोड:
public static void main(String[] args) throws IOException {
String longStr = "asjf97zcv.1jm2497z20`1829182oqiwure92874nvcxz,nvz.,xo" +
"aihf[oiefjkas';./.,z][p\\°°°°°°°°?!(*#&(@*&#!)^(*&(*&)(*&" +
"fasdznmcxzvvcxz,vc,mvczvcz,mvcz,mcvcxvc,mvcxcvcxvcxvcxvcx";
int[] indices = new int[32 * 1024];
int[] lengths = new int[indices.length];
Random r = new Random();
final int minLength = 6;
for (int i = 0; i < indices.length; ++i)
{
indices[i] = r.nextInt(longStr.length() - minLength);
lengths[i] = minLength + r.nextInt(longStr.length() - indices[i] - minLength);
}
long start = System.nanoTime();
int avoidOptimization = 0;
for (int i = 0; i < indices.length; ++i)
//avoidOptimization += lengths[i]; //tested - this was cheap
avoidOptimization += longStr.substring(indices[i],
indices[i] + lengths[i]).length();
long end = System.nanoTime();
System.out.println("substring " + indices.length + " times");
System.out.println("Sum of lengths of splits = " + avoidOptimization);
System.out.println("Elapsed " + (end - start) / 1.0e6 + " ms");
}
आउटपुट:
32768 बार प्रतिस्थापित किया जा रहा है विभाजन की लंबाई का योग = 1494414 बीता हुआ 2.446679 मि
यदि यह ओ (1) है या नहीं, निर्भर करता है। यदि आप स्मृति में केवल एक ही स्ट्रिंग का संदर्भ देते हैं, तो बहुत लंबी स्ट्रिंग की कल्पना करें , आप प्रतिस्थापन करते हैं और लंबे समय से संदर्भ को रोकते हैं। लंबे समय तक मेमोरी जारी करना अच्छा नहीं होगा?
जावा 1.7.0_06 से पहले : ओ (1)।
जावा 1.7.0_06 के बाद : O (n)। मेमोरी लीक की वजह से इसे बदल दिया गया था। खेतों के बाद offset
और count
स्ट्रिंग से हटा दिए जाने के बाद , प्रतिस्थापन कार्यान्वयन ओ (एन) बन गया।
अधिक जानकारी के लिए, कृपया देखें: http://java-performance.info/changes-to-string-java-1-7-0_06/