স্ক্যানার বনাম স্ট্রিংটোকেনাইজার বনাম স্ট্রিং.স্প্লিট


155

আমি কেবল জাভার স্ক্যানার ক্লাস সম্পর্কে শিখেছি এবং এখন আমি ভাবছি যে এটি কীভাবে স্ট্রিংটোকেনাইজার এবং স্ট্রিং.স্প্লিটের সাথে তুলনা করে / প্রতিযোগিতা করে। আমি জানি যে স্ট্রিংটোকেনাইজার এবং স্ট্রিং.স্প্লিটগুলি কেবল স্ট্রিংগুলিতেই কাজ করে, তাই আমি কেন স্ট্রিংয়ের জন্য স্ক্যানারটি ব্যবহার করতে চাই? স্ক্যানার কি কেবল বিভক্ত হওয়ার জন্য ওয়ান স্টপ-শপিংয়ের উদ্দেশ্যে রয়েছে?

উত্তর:


240

তারা অবশ্যই কোর্সের জন্য ঘোড়া।

  • Scannerএমন ক্ষেত্রে ডিজাইন করা হয়েছে যেখানে আপনাকে বিভিন্ন ধরণের ডেটা বের করে স্ট্রিংকে বিশ্লেষণ করতে হবে। এটি খুব নমনীয়, তবে কোনও নির্দিষ্ট এক্সপ্রেশন দ্বারা সীমাবদ্ধ স্ট্রিংগুলির অ্যারে পাওয়ার জন্য যুক্তিযুক্তভাবে আপনাকে সহজতম API দেয় না।
  • String.split()এবং Pattern.split()আপনাকে দ্বিতীয়টি করার জন্য একটি সহজ বাক্য গঠন দেয়, তবে এটি মূলত তারা যা করেন। আপনি যদি ফলাফলযুক্ত স্ট্রিংগুলি বিশ্লেষণ করতে চান বা নির্দিষ্ট টোকেনের উপর নির্ভর করে ডিলিমিটারটি অর্ধেক করে পরিবর্তন করতে চান তবে তারা আপনাকে এটিতে সহায়তা করবে না।
  • StringTokenizerএটি আরও বেশি সীমাবদ্ধ String.split(), এবং এটি ব্যবহার করতে কিছুটা ফিডিলার। এটি মূলত স্থির সাবস্ট্রিংগুলি দ্বারা বিসর্জনিত টোকেনগুলি টেনে আনার জন্য ডিজাইন করা হয়েছে। এই বিধিনিষেধের কারণে এটি প্রায় দ্বিগুণ দ্রুত String.split()। (আমার তুলনাString.split()StringTokenizer দেখুন এবং ।) এটি নিয়মিত এক্সপ্রেশন API এর পূর্বাভাস দেয়, যার String.split()একটি অংশ।

আপনি আমার সময়গুলি নোট করবেন যা String.split()এখনও একটি সাধারণ মেশিনে কয়েক মিলি সেকেন্ডে কয়েক হাজার স্ট্রিং টোকানাইজ করতে পারে । তদতিরিক্ত, এর চেয়েও সুবিধা রয়েছে StringTokenizerযে এটি আপনাকে একটি স্ট্রিং অ্যারে হিসাবে আউটপুট দেয় যা সাধারণত আপনি যা চান। Enumerationদ্বারা প্রদত্ত একটি ব্যবহার করা StringTokenizerবেশিরভাগ সময় "সিনট্যাক্টিক্যালি ফিউজি"। এই দৃষ্টিকোণ থেকে, StringTokenizerআজকাল জায়গার অপচয় হ'ল এবং আপনি পাশাপাশি ব্যবহার করতে পারেন String.split()


8
আপনি স্ট্রিং.স্প্লিট এবং স্ট্রিংটোকেনাইজারে যে পরীক্ষা চালিয়েছিলেন সেই একই পরীক্ষায় স্ক্যানারের ফলাফলগুলিও আকর্ষণীয় হবে।
ডেভ

2
আমাকে অন্য একটি প্রশ্নের উত্তর দিয়েছেন: "স্ট্রিংটোকেনাইজার ব্যবহার কেন নিরুৎসাহিত করা হচ্ছে, যেমন জাভা এপিআই নোটগুলিতে বলা হয়েছে?" এই পাঠ্য থেকে মনে হচ্ছে উত্তরটি "কারণ স্ট্রিং.স্প্লিট () যথেষ্ট দ্রুত"।
পা

1
তাহলে স্ট্রিংটোকেনাইজার এখন কি অনেক বেশি অবহেলিত?
স্টিভ মেকার

এর পরিবর্তে কী ব্যবহার করব? স্ক্যানার?
অ্যাড্রিয়ান

4
আমি বুঝতে পেরেছি এটি একটি পুরানো প্রশ্নের উত্তর, তবে আমাকে যদি ফ্লাইয়ের টোকেনগুলিতে বিশাল টেক্সট স্ট্রিমটি বিভক্ত করার প্রয়োজন হয় তবে StringTokenizerএখনও আমার সেরা বাজি না কারণ String.split()কেবল স্মৃতিশক্তি শেষ হয়ে যাবে?
সের্গেই তাচেনভ

57

আসুন বাদ দিয়ে শুরু করা যাক StringTokenizer। এটি পুরানো হয়ে আসছে এবং নিয়মিত প্রকাশগুলিও সমর্থন করে না। এর নথিতে বলা হয়েছে:

StringTokenizerএটি একটি উত্তরাধিকার শ্রেণি যা সামঞ্জস্যতার কারণে ধরে রাখা হয় যদিও এর ব্যবহারটি নতুন কোডে নিরুৎসাহিত করা হয়েছে। এটি প্রস্তাবিত হয় যে এই কার্যকারিতা সন্ধানকারী যে কেউ তার পরিবর্তে splitপদ্ধতি Stringবা java.util.regexপ্যাকেজটি ব্যবহার করুন।

সুতরাং আসুন এখনই এটি ফেলে দিন। যে পাতা split()এবং Scanner। তাদের মধ্যে পার্থক্য কী?

একটি জিনিস জন্য, split()কেবল একটি অ্যারে ফিরিয়ে দেয়, যা পূর্বাঞ্চ লুপ ব্যবহার করা সহজ করে তোলে:

for (String token : input.split("\\s+") { ... }

Scanner স্রোতের মতো আরও নির্মিত:

while (myScanner.hasNext()) {
    String token = myScanner.next();
    ...
}

অথবা

while (myScanner.hasNextDouble()) {
    double token = myScanner.nextDouble();
    ...
}

(এটির পরিবর্তে একটি বৃহত এপিআই রয়েছে , সুতরাং এটি সর্বদা এ জাতীয় সাধারণ জিনিসগুলির মধ্যেই সীমাবদ্ধ মনে করবেন না))

এই স্ট্রিম-স্টাইলের ইন্টারফেসটি সহজ পাঠ্য ফাইলগুলি বা কনসোল ইনপুট পার্সিংয়ের জন্য কার্যকর হতে পারে, যখন বিশ্লেষণ শুরু করার আগে আপনার কাছে সমস্ত ইনপুট থাকে না (বা পেতে পারেন না)।

ব্যক্তিগতভাবে, আমি কেবলমাত্র Scannerস্কুল প্রকল্পগুলির জন্যই মনে করতে পারি যখন আমি কমান্ড লাইন থেকে ব্যবহারকারী ইনপুট পেতে পারি। এটি এই ধরণের অপারেশনটিকে সহজ করে তোলে। তবে আমার যদি এমন একটি থাকে Stringযা আমি বিচ্ছেদ করতে চাই, এটি প্রায় কোনও মস্তিষ্কের সাথে যেতে হবে split()


20
স্ট্রিংটোকেনাইজার স্ট্রিং.স্প্লিট () এর মতো 2x গতিযুক্ত। আপনি যদি নিয়মিত এক্সপ্রেশন ব্যবহারের প্রয়োজন না হন, না!
অ্যালেক্স ওয়ার্ডেন

আমি Scannerএকটি প্রদত্ত নতুন লাইন অক্ষর সনাক্ত করতে ব্যবহৃত String। নতুন লাইন অক্ষর (এ বর্ণন প্ল্যাটফর্ম প্ল্যাটফর্ম থেকে বিভিন্ন রকমের হতে পারে যেহেতু Patternএর javadoc!) এবং ইনপুট স্ট্রিং সাথে সামঞ্জস্য থেকে নিশ্চিত করা হয় না System.lineSeparator(), আমি এটি Scannerআরো উপযুক্ত যেমন ইতিমধ্যে নতুন লাইন অক্ষর যখন কলিং জন্য কি দেখুন জানে nextLine()String.splitলাইন বিভাজকগুলি সনাক্ত করার জন্য আমাকে সঠিক রেজেক্স প্যাটার্নে খাওয়াতে হবে, যা আমি কোনও মানক স্থানে সঞ্চিত পাই না (এটি সর্বোত্তমভাবে আমি করতে পারি এটি Scannerক্লাসের উত্স থেকে অনুলিপি করা )।
ADTC

9

স্ট্রিংটোকেনাইজার সর্বদা ছিল। এটি সকলের থেকে দ্রুত, তবে গণনার মতো প্রতিমাটি অন্যদের মতো মার্জিত দেখাচ্ছে না।

জেডিকে ১.৪-এ বিভক্ত হয়ে ওঠে। টোকেনাইজারের চেয়ে ধীরে ধীরে তবে এটি ব্যবহার করা সহজ, এটি স্ট্রিং ক্লাস থেকে কলযোগ্য from

স্ক্যানারটি জেডিকে ২.৩ এ এসেছিল। এটি সর্বাধিক নমনীয় এবং বিখ্যাত সিএস স্ক্যানফ ফাংশন পরিবারের সমতুল্য সমর্থন করার জন্য জাভা এপিআইতে দীর্ঘস্থায়ী ব্যবধান পূরণ করে।


6

আপনার যদি স্ট্রিং অবজেক্ট থাকে তবে আপনি টোকনাইজ করতে চান, স্ট্রিং টোকেনাইজারের মাধ্যমে স্ট্রিংয়ের বিভাজন পদ্ধতিটি ব্যবহার করুন । যদি আপনি আপনার প্রোগ্রামের বাইরের কোনও উত্স থেকে যেমন কোনও ফাইল থেকে বা ব্যবহারকারীর কাছ থেকে পাঠ্য ডেটা পার্স করছেন তবে সেখান থেকে কোনও স্ক্যানার আসবে।


5
ঠিক তেমনি, কোন যুক্তি, কারণ নেই?
jan.supol

6

স্প্লিট ধীর, তবে স্ক্যানারের মতো ধীর নয়। স্ট্রিংটোকেনাইজার বিভাজনের চেয়ে দ্রুত। তবে, আমি জেনেছি যে আমি জেফাস্টপার্সার https://github.com/hughperkins/jfastparser এ যা করেছি, একটি গতি-উত্সাহ পেতে কিছুটা নমনীয়তার বাণিজ্য করে দ্বিগুণ গতি অর্জন করতে পারি

এক মিলিয়ন ডাবলসযুক্ত স্ট্রিংটিতে পরীক্ষা করা:

Scanner: 10642 ms
Split: 715 ms
StringTokenizer: 544ms
JFastParser: 290ms

কিছু জাভাডোকটি দুর্দান্ত হত, এবং আপনি যদি সংখ্যার ডেটা বাদে অন্য কিছু পার্স করতে চান?
নিকজে

ওয়েল, এটি গতির জন্য ডিজাইন করা হয়েছে, সৌন্দর্যের জন্য নয়। এটি বেশ সহজ, মাত্র কয়েকটি লাইন, তাই আপনি চাইলে পাঠ্য পার্সিংয়ের জন্য আরও কয়েকটি বিকল্প যুক্ত করতে পারেন।
হিউ পার্কিনস

4

স্ট্রিং.স্প্লিট স্ট্রিংটোকেনাইজারের চেয়ে অনেক ধীর গতির বলে মনে হচ্ছে। বিভাজনের সাথে একমাত্র সুবিধা হ'ল আপনি টোকেনগুলির একটি অ্যারে পাবেন। এছাড়াও আপনি বিভাজনে যে কোনও নিয়মিত অভিব্যক্তি ব্যবহার করতে পারেন। org.apache.commons.lang.StringUtils এর একটি বিভাজন পদ্ধতি রয়েছে যা দুটি যেকোনটির চেয়ে অনেক বেশি দ্রুত কাজ করে। স্ট্রিংটোকেনাইজার বা স্ট্রিং.স্প্লিট। তবে তিনটির সিপিইউ ব্যবহার প্রায় একই রকম। সুতরাং আমাদের এমন একটি পদ্ধতিও প্রয়োজন যা কম সিপিইউ নিবিড়, যা আমি এখনও খুঁজে পাচ্ছি না।


3
এই উত্তরটি কিছুটা অযৌক্তিক। আপনি বলেছিলেন যে আপনি এমন কিছু সন্ধান করছেন যা দ্রুত তবে "কম সিপিইউ নিবিড়"। যে কোনও প্রোগ্রাম সিপিইউ দ্বারা চালিত হয়। যদি কোনও প্রোগ্রাম আপনার সিপিইউ 100% ব্যবহার না করে, তবে এটি অবশ্যই I / O এর মতো অন্য কোনও কিছুর জন্য অপেক্ষা করবে। স্ট্রিং টোকেনাইজেশন নিয়ে আলোচনা করার সময় এটি কোনও সমস্যা হওয়ার কথা নয়, যদি না আপনি সরাসরি ডিস্ক অ্যাক্সেস করেন (যা আমরা এখানে উল্লেখযোগ্যভাবে করছি না)।
Jolta

4

আমি সম্প্রতি অত্যন্ত কর্মক্ষমতা সংবেদনশীল পরিস্থিতিতে স্ট্রিং.স্প্লিট () এর খারাপ অভিনয় সম্পর্কে কিছু পরীক্ষা-নিরীক্ষা করেছি। আপনি এটি দরকারী খুঁজে পেতে পারেন।

http://eblog.chrononsystems.com/hidden-evils-of-javas-stringsplit-and-stringr

সংক্ষিপ্তসারটি হ'ল স্ট্রিং.স্প্লিট () প্রতিবার একটি নিয়মিত এক্সপ্রেশন প্যাটার্ন সংকলন করে এবং এভাবে আপনি যদি পূর্বনির্ধারিত প্যাটার্ন অবজেক্টটি ব্যবহার করেন এবং স্ট্রিংয়ের কাজ করতে সরাসরি এটি ব্যবহার করেন তার তুলনায় আপনার প্রোগ্রামটি ধীর করতে পারে।


4
আসলে স্ট্রিং.স্প্লিট () সর্বদা প্যাটার্নটি সংকলন করে না। উত্সটি দেখুন, যদি 1.7 জাভা, আপনি দেখতে পাবেন যে প্যাটার্নটি একটি একক অক্ষর এবং পালানো এক নয়, এটি একটি চেক রয়েছে, এটি স্ট্রিংটিকে রেজিএক্সপ ছাড়াই বিভক্ত করবে, সুতরাং এটি বেশ দ্রুত হওয়া উচিত।
ক্রিজিসটফ ক্রোসো

1

ডিফল্ট পরিস্থিতিগুলির জন্য আমি প্যাটার্ন.স্প্লিট () এর পাশাপাশি পরামর্শ দেব তবে আপনার যদি সর্বোচ্চ পারফরম্যান্সের প্রয়োজন হয় (বিশেষত অ্যান্ড্রয়েডে আমার পরীক্ষা করা সমস্ত সমাধান বেশ ধীর) এবং আপনার কেবলমাত্র একটি চর দ্বারা বিভক্ত হওয়া দরকার, আমি এখন আমার নিজস্ব পদ্ধতি ব্যবহার করছি:

public static ArrayList<String> splitBySingleChar(final char[] s,
        final char splitChar) {
    final ArrayList<String> result = new ArrayList<String>();
    final int length = s.length;
    int offset = 0;
    int count = 0;
    for (int i = 0; i < length; i++) {
        if (s[i] == splitChar) {
            if (count > 0) {
                result.add(new String(s, offset, count));
            }
            offset = i + 1;
            count = 0;
        } else {
            count++;
        }
    }
    if (count > 0) {
        result.add(new String(s, offset, count));
    }
    return result;
}

একটি স্ট্রিংয়ের জন্য চর অ্যারে পেতে "abc" .toCharArray () ব্যবহার করুন। উদাহরণ স্বরূপ:

String s = "     a bb   ccc  dddd eeeee  ffffff    ggggggg ";
ArrayList<String> result = splitBySingleChar(s.toCharArray(), ' ');

1

একটি গুরুত্বপূর্ণ পার্থক্য হ'ল স্ট্রিং.স্প্লিট () এবং স্ক্যানার উভয়ই খালি স্ট্রিং উত্পাদন করতে পারে তবে স্ট্রিংটোকেনাইজার কখনই তা করে না।

উদাহরণ স্বরূপ:

String str = "ab cd  ef";

StringTokenizer st = new StringTokenizer(str, " ");
for (int i = 0; st.hasMoreTokens(); i++) System.out.println("#" + i + ": " + st.nextToken());

String[] split = str.split(" ");
for (int i = 0; i < split.length; i++) System.out.println("#" + i + ": " + split[i]);

Scanner sc = new Scanner(str).useDelimiter(" ");
for (int i = 0; sc.hasNext(); i++) System.out.println("#" + i + ": " + sc.next());

আউটপুট:

//StringTokenizer
#0: ab
#1: cd
#2: ef
//String.split()
#0: ab
#1: cd
#2: 
#3: ef
//Scanner
#0: ab
#1: cd
#2: 
#3: ef

কারণ স্ট্রিং.স্প্লিট () এবং স্ক্যানার.উজ ডেলিমিটার () এর ডিলিমিটারটি কেবল একটি স্ট্রিং নয়, একটি নিয়মিত প্রকাশ expression স্ট্রিংটোকেনাইজারের মতো আচরণ করার জন্য আমরা উপরের উদাহরণে "+" দিয়ে ডিলিমিটারটি প্রতিস্থাপন করতে পারি।


-5

স্ট্রিং.স্প্লিট () খুব ভাল কাজ করে তবে এর নিজস্ব সীমানা রয়েছে যেমন আপনি যদি একক বা ডাবল পাইপের (|) চিহ্নের ভিত্তিতে নীচে দেখানো একটি স্ট্রিং বিভক্ত করতে চান তবে এটি কাজ করে না। এই পরিস্থিতিতে আপনি স্ট্রিংটোকেনাইজার ব্যবহার করতে পারেন।

এবিসি | IJK


12
প্রকৃতপক্ষে, আপনি কেবল "এবিসি | আইজেকে" .স্প্লিট ("\\ |") দিয়ে আপনার উদাহরণটি বিভক্ত করতে পারেন;
টমো

"এবিসি || ডিএইফ ||" ।স্প্লিট ("\\ |") সত্যই কাজ করে না কারণ এটি দুটি খালি মানকে অগ্রাহ্য করবে, যা পার্সিংকে তার চেয়ে বেশি সংবেদনশীল করে তোলে।
আরমান্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.