জাভা 8 বিভাজনে মাঝে মাঝে ফলাফল অ্যারের শুরুতে খালি স্ট্রিংগুলি সরিয়ে দেয়?


110

জাভা 8 এর আগে যখন আমরা খালি স্ট্রিংয়ের মতো বিভক্ত হয়

String[] tokens = "abc".split("");

চিহ্নিত করা জায়গায় বিভক্ত প্রক্রিয়া বিভক্ত হবে |

|a|b|c|

কারণ ""প্রতিটি চরিত্রের আগে এবং পরে খালি স্থান বিদ্যমান। সুতরাং ফলস্বরূপ এটি প্রথমে এই অ্যারে উত্পন্ন করবে

["", "a", "b", "c", ""]

এবং পরেরটি খালি স্ট্রিংগুলি সরিয়ে ফেলবে (কারণ আমরা সুস্পষ্টভাবে limitযুক্তিতে নেতিবাচক মান সরবরাহ করি নি ) সুতরাং এটি শেষ পর্যন্ত ফিরে আসবে

["", "a", "b", "c"]

জাভাতে 8 বিভাজনের প্রক্রিয়াটি পরিবর্তিত হয়েছে বলে মনে হচ্ছে। এখন আমরা যখন ব্যবহার

"abc".split("")

আমরা এর ["a", "b", "c"]পরিবর্তে অ্যারে পাব ["", "a", "b", "c"]তাই দেখে মনে হচ্ছে শুরুর ফাঁকা স্ট্রিংগুলিও সরানো আছে। উদাহরণস্বরূপ, তবে এই তত্ত্বটি ব্যর্থ

"abc".split("a")

শুরুর দিকে খালি স্ট্রিং সহ অ্যারে প্রদান করে ["", "bc"]

এখানে কি চলছে এবং জাভা 8-এ বিভাজনের নিয়ম কীভাবে পরিবর্তিত হয়েছে তা কেউ ব্যাখ্যা করতে পারেন?


জাভা 8 এটি ঠিক করছে বলে মনে হচ্ছে। এদিকে, s.split("(?!^)")কাজ মনে হচ্ছে।
shkschneider

2
আমার প্রশ্নে বর্ণিত @ শিক্সনিদার আচরণটি জাভা -৮ সংস্করণের পূর্বের বাগ নয়। এই আচরণটি বিশেষভাবে খুব কার্যকর ছিল না তবে এটি এখনও সঠিক ছিল (আমার প্রশ্নে দেখানো হয়েছে), সুতরাং আমরা এটি বলতে পারি না যে এটি "স্থির" ছিল। আমি এটি আরো উন্নতি মত দেখতে তাই আমরা ব্যবহার করতে পারে split("")(যারা Regex ব্যবহার করবেন না জন্য) রহস্যপূর্ণ পরিবর্তে split("(?!^)")বা split("(?<!^)")বা অন্য কয়েকজন regexes।
Pshemo

1
ফেডোরা 21, ফেডোরা 21 টি জাহাজ JDK 1.8 তে আপগ্রেড করার পরে একই ইস্যুটির মুখোমুখি হয়েছিল এবং এর কারণে আমার আইআরসি গেম অ্যাপ্লিকেশনটি ভেঙে গেছে।
লিউইয়ান 研 研

7
এই প্রশ্নটি জাভা ৮-এর এই ব্রেকিং পরিবর্তনের একমাত্র ডকুমেন্টেশন বলে মনে হচ্ছে ওরাকল এটিকে তাদের অসম্পূর্ণতার তালিকা থেকে বাদ দিয়েছে ।
সান ভ্যান গর্ডার

4
জেডিকে এই পরিবর্তনটির জন্য আমার কী ভুল তা সন্ধান করতে 2 ঘন্টা ব্যয় করেছে। কোডটি আমার কম্পিউটারে (জেডিকে 8) ঠিক আছে তবে অন্য মেশিনে (জেডিকে 7) রহস্যজনকভাবে ব্যর্থ হয়। ওরাকল প্রকৃতই উচিত ডকুমেন্টেশন আপডেট String.split (স্ট্রিং Regex) , বরং Pattern.split বা String.split তুলনায় (স্ট্রিং Regex, int- সীমা) হিসাবে এই পর্যন্ত সবচেয়ে সাধারণ ব্যবহার হয়। জাভা তার বহনযোগ্যতা ওরফে তথাকথিত WORA জন্য পরিচিত। এটি একটি বড় পশ্চাৎপদ-পরিবর্তন এবং একেবারেই ডকুমেন্টেড নয়।
পাওয়ার্ডবাইরাইস

উত্তর:


84

জাভা 7 এবং জাভা 8 এর মধ্যে String.split(যা কল করে Pattern.split) এর আচরণ পরিবর্তন হয়।

নথিপত্র

ডকুমেন্টেশন মধ্যে তুলনা Pattern.splitমধ্যে জাভা 7 এবং জাভা 8 , আমরা নিম্নলিখিত দফা মান্য যোগ করা হচ্ছে:

ইনপুট ক্রমের শুরুতে যখন ইতিবাচক-প্রস্থের ম্যাচ হয় তখন ফলাফল অ্যারের শুরুতে একটি ফাঁকা শীর্ষস্থানীয় স্ট্রিং অন্তর্ভুক্ত করা হয়। শুরুতে একটি শূন্য-প্রস্থের ম্যাচ তবে কখনও এ জাতীয় শূন্যস্থানীয় স্ট্রিং তৈরি করে না।

একই ধারা এছাড়াও যোগ করা হয় String.splitজাভা 8 তুলনায় জাভা 7

রেফারেন্স বাস্তবায়ন

আসুন Pattern.splitজাভা 7 এবং জাভা 8-তে রেফারেন্স বাস্তবায়নের কোডটি তুলনা করি The কোডটি গ্রেপকোড থেকে প্রাপ্ত হয়েছে, সংস্করণ 7u40-b43 এবং 8-b132 এর জন্য।

জাভা 7

public String[] split(CharSequence input, int limit) {
    int index = 0;
    boolean matchLimited = limit > 0;
    ArrayList<String> matchList = new ArrayList<>();
    Matcher m = matcher(input);

    // Add segments before each match found
    while(m.find()) {
        if (!matchLimited || matchList.size() < limit - 1) {
            String match = input.subSequence(index, m.start()).toString();
            matchList.add(match);
            index = m.end();
        } else if (matchList.size() == limit - 1) { // last one
            String match = input.subSequence(index,
                                             input.length()).toString();
            matchList.add(match);
            index = m.end();
        }
    }

    // If no match was found, return this
    if (index == 0)
        return new String[] {input.toString()};

    // Add remaining segment
    if (!matchLimited || matchList.size() < limit)
        matchList.add(input.subSequence(index, input.length()).toString());

    // Construct result
    int resultSize = matchList.size();
    if (limit == 0)
        while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
            resultSize--;
    String[] result = new String[resultSize];
    return matchList.subList(0, resultSize).toArray(result);
}

জাভা 8

public String[] split(CharSequence input, int limit) {
    int index = 0;
    boolean matchLimited = limit > 0;
    ArrayList<String> matchList = new ArrayList<>();
    Matcher m = matcher(input);

    // Add segments before each match found
    while(m.find()) {
        if (!matchLimited || matchList.size() < limit - 1) {
            if (index == 0 && index == m.start() && m.start() == m.end()) {
                // no empty leading substring included for zero-width match
                // at the beginning of the input char sequence.
                continue;
            }
            String match = input.subSequence(index, m.start()).toString();
            matchList.add(match);
            index = m.end();
        } else if (matchList.size() == limit - 1) { // last one
            String match = input.subSequence(index,
                                             input.length()).toString();
            matchList.add(match);
            index = m.end();
        }
    }

    // If no match was found, return this
    if (index == 0)
        return new String[] {input.toString()};

    // Add remaining segment
    if (!matchLimited || matchList.size() < limit)
        matchList.add(input.subSequence(index, input.length()).toString());

    // Construct result
    int resultSize = matchList.size();
    if (limit == 0)
        while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
            resultSize--;
    String[] result = new String[resultSize];
    return matchList.subList(0, resultSize).toArray(result);
}

জাভা 8-তে নিম্নলিখিত কোডটি যুক্ত করা ইনপুট স্ট্রিংয়ের শুরুতে শূন্য দৈর্ঘ্যের ম্যাচ বাদ দেয় যা উপরের আচরণটি ব্যাখ্যা করে।

            if (index == 0 && index == m.start() && m.start() == m.end()) {
                // no empty leading substring included for zero-width match
                // at the beginning of the input char sequence.
                continue;
            }

সামঞ্জস্য বজায় রাখা

জাভা 8 এবং তারপরে উপরের আচরণ অনুসরণ করা হচ্ছে

করতে splitধারাবাহিকভাবে সংস্করণ জুড়ে এবং জাভা 8 আচরণ সঙ্গে সামঞ্জস্যপূর্ণ আচরণ করবে:

  1. আপনার Regex যদি পারেন শূন্য দৈর্ঘ্যের স্ট্রিং মেলে, শুধু যোগ (?!\A)সময়ে শেষ Regex ও অ ক্যাপচারিং দলের মূল Regex মোড়ানো (?:...)(প্রয়োজন হলে)।
  2. যদি আপনার রেজেক্স শূন্য দৈর্ঘ্যের স্ট্রিংয়ের সাথে মেলে না , তবে আপনাকে কিছু করার দরকার নেই।
  3. রেজেক্স শূন্য-দৈর্ঘ্যের স্ট্রিংয়ের সাথে মেলে কিনা তা আপনি যদি না জানেন তবে পদক্ষেপ 1 এ দুটি ক্রিয়া করুন in

(?!\A) স্ট্রিংটির শুরুতে স্ট্রিংটি শেষ হয় না তা পরীক্ষা করে, যা বোঝায় যে স্ট্রিংয়ের শুরুতে ম্যাচটি খালি ম্যাচ।

জাভা 7 এবং পূর্বের আচরণ অনুসরণ করা

splitজাভা with এর সাথে পশ্চাদপটে সামঞ্জস্যপূর্ণ করার কোনও সাধারণ সমাধান নেই এবং এর আগে, splitআপনার নিজস্ব কাস্টম প্রয়োগের দিকে নির্দেশ করার সমস্ত উদাহরণ প্রতিস্থাপনের সংক্ষিপ্ততা ।


কোনও split("")কোড আমি কীভাবে কোড পরিবর্তন করতে পারি যাতে এটি বিভিন্ন জাভা সংস্করণ জুড়ে সামঞ্জস্য হয়?
ড্যানিয়েল

2
@Daniel: এটা এটি এগিয়ে সামঞ্জস্যপূর্ণ করতে যোগ করে (জাভা 8 আচরণ অনুসরণ) করা সম্ভব (?!^)করতে শেষ Regex ও অ ক্যাপচার দলের মূল Regex মোড়ানো (?:...)(প্রয়োজন হলে), কিন্তু আমি কোনো ভাবতে পারি না এটিকে পশ্চাদপটে সামঞ্জস্যপূর্ণ করার উপায় (জাভা 7 এবং পূর্বের পুরানো আচরণটি অনুসরণ করুন)।
nhahtdh

ব্যাখ্যার জন্য ধন্যবাদ. আপনি বর্ণনা করতে পারেন "(?!^)"? কোন পরিস্থিতিতে এটির থেকে আলাদা হবে ""? (আমি রেগেক্সে ভয়ানক!: - /)।
ড্যানিয়েল

1
@ ড্যানিয়েল: এর অর্থ Pattern.MULTILINEপতাকা দ্বারা প্রভাবিত হয় , যখন পতাকাটি \Aনির্বিশেষে সবসময় স্ট্রিংয়ের শুরুতে মেলে।
nhahtdh

30

এর ডকুমেন্টেশনে এটি নির্দিষ্ট করা হয়েছে split(String regex, limit)

এই স্ট্রিংয়ের শুরুতে যখন ইতিবাচক-প্রস্থের ম্যাচ হয় তখন ফলাফল অ্যারের শুরুতে একটি ফাঁকা শীর্ষস্থানীয় স্ট্রিং অন্তর্ভুক্ত করা হয়। শুরুতে একটি শূন্য-প্রস্থের ম্যাচ তবে কখনও এ জাতীয় শূন্যস্থানীয় স্ট্রিং তৈরি করে না।

ইন "abc".split("")আপনি এখন নেতৃস্থানীয় খালি সাবস্ট্রিং ফলে অ্যারের মধ্যে অন্তর্ভুক্ত করা হয় না শুরুতে একটি শূন্য-চওড়া ম্যাচ পেয়েছিলাম।

তবে আপনার দ্বিতীয় স্নিপেটে যখন আপনি বিভক্ত হয়েছিলেন তখন আপনি "a"একটি ইতিবাচক প্রস্থের ম্যাচ পেয়েছেন (এই ক্ষেত্রে 1), তাই খালি শীর্ষস্থানীয় স্ট্রিংটি প্রত্যাশা অনুযায়ী অন্তর্ভুক্ত করা হয়েছে।

(অপ্রাসঙ্গিক উত্স কোড সরানো)


3
এটা শুধু একটি প্রশ্ন। জেডিকে থেকে কোডের একটি টুকরো পোস্ট করা কি ঠিক আছে? গুগল - হ্যারি পটার - ওরাকল এর সাথে কপিরাইট সমস্যা মনে আছে?
পল ভার্গাস

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

12
@ পোলবার্গাস "ওপেন সোর্স" এর "উন্মুক্ত" কোনও কিছুর জন্য দাঁড়ায়।
মার্কো টপলনিক

2
@ জুউউউ: কেবলমাত্র প্রত্যেকে এটি দেখতে পাবে বলে এর অর্থ এই নয় যে আপনি এটি পুনরায় প্রকাশ করতে পারবেন
ব্যবহারকারী 102008

2
@ পোল ভার্গাস, আইএনএল তবে অন্যান্য অনেক অনুষ্ঠানে এই ধরণের পোস্ট উদ্ধৃতি / ন্যায্য ব্যবহারের পরিস্থিতিতে পড়ে। প্রসঙ্গটির আরও
অ্যালেক্স

14

split()জাভা 7 থেকে জাভা 8-তে ডক্সে সামান্য পরিবর্তন হয়েছিল Spec বিশেষত, নিম্নলিখিত বিবৃতিটি যুক্ত করা হয়েছিল:

এই স্ট্রিংয়ের শুরুতে যখন ইতিবাচক-প্রস্থের ম্যাচ হয় তখন ফলাফল অ্যারের শুরুতে একটি ফাঁকা শীর্ষস্থানীয় স্ট্রিং অন্তর্ভুক্ত করা হয়। শুরুতে একটি শূন্য-প্রস্থের ম্যাচ তবে কখনও এ জাতীয় শূন্যস্থানীয় স্ট্রিং তৈরি করে না।

(জোর আমার)

খালি স্ট্রিং বিভাজন শুরুর দিকে শূন্য-প্রস্থের ম্যাচ তৈরি করে, সুতরাং উপরে বর্ণিত অনুসারে ফলাফলের অ্যারের শুরুতে একটি খালি স্ট্রিং অন্তর্ভুক্ত করা হয় না। বিপরীতে, আপনার দ্বিতীয় উদাহরণ যা বিভক্ত হয় স্ট্রিংয়ের শুরুতে "a"একটি ইতিবাচক- প্রস্থের ম্যাচ উত্পন্ন করে, তাই খালি স্ট্রিংটি আসলে ফলাফলের অ্যারের শুরুতে অন্তর্ভুক্ত থাকে।


আরও কয়েক সেকেন্ড পার্থক্য তৈরি করে।
পল ভার্গাস

2
@ পোলবার্গাস আসলে এখানে আর্শজিই জউজউয়ের কয়েক সেকেন্ড আগে উত্তর পোস্ট করেছিলেন, তবে দুর্ভাগ্যক্রমে জউজউ আমার প্রশ্নের উত্তর এখানে আগেই দিয়েছিলেন । আমি ভাবছিলাম যে আমার এই প্রশ্নটি জিজ্ঞাসা করা উচিত কারণ আমি ইতিমধ্যে উত্তর জেনেছিলাম তবে এটি আকর্ষণীয় বলে মনে হয়েছিল এবং জৌউউ তার আগের মন্তব্যের জন্য কিছুটা খ্যাতির অধিকারী ছিলেন।
Pshemo

5
নতুন আচরণটি আরও যুক্তিসঙ্গত বলে মনে হচ্ছে , এটি অবশ্যই একটি পশ্চাদপটে সামঞ্জস্যতা বিরতি । এই পরিবর্তনের একমাত্র যুক্তি হ'ল এটি "some-string".split("")একটি বিরল ঘটনা।
ivstas

4
.split("")কোনও কিছুর সাথে মিল না রেখে বিভক্ত হওয়ার একমাত্র উপায় নয়। আমরা ইতিবাচক বর্ণনাহী রেজেক্স ব্যবহার করেছি যা jdk7 এ শুরুতেও মিলেছিল এবং খালি মাথা উপাদান তৈরি করেছিল যা এখন চলে গেছে। github.com/spray/spray/commit/…
jrudolph
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.