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-uFFF সীমার বাইরে যে কোড পয়েন্টগুলি ব্যবহার করছেন, এখানে বর্ণিত অন্যান্য কৌশলগুলির বেশিরভাগটি ভেঙে যায় । এটি কেবল বিরল ঘটবে, কারণ এর বাইরের কোড পয়েন্টগুলি বেশিরভাগ মৃত ভাষায় নির্ধারিত হয়। তবে এর বাইরে কিছু দরকারী চরিত্র রয়েছে, উদাহরণস্বরূপ কিছু গাণিতিক স্বরলিপি ব্যবহারের জন্য কোড পয়েন্ট, এবং কিছু চীনাতে সঠিক নামগুলি এনকোড করতে ব্যবহৃত হত।
সেক্ষেত্রে আপনার কোডটি হবে:
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+ প্রয়োজন।
আমি সম্মত হই যে স্ট্রিংটোকেনাইজার এখানে ওভারকিল। আসলে আমি উপরের পরামর্শগুলি চেষ্টা করে সময় নিয়েছি took
আমার পরীক্ষাটি মোটামুটি সহজ ছিল: প্রায় দশ লক্ষ অক্ষর সহ একটি স্ট্রিংবিল্ডার তৈরি করুন, এটিকে একটি স্ট্রিংয়ে রূপান্তর করুন এবং তাদের প্রত্যেককে চরআউট () দিয়ে / ট্র্যাক করে চার্ট অ্যারেতে রূপান্তরিত করার পরে / একটি চরিত্রশিক্ষকের সাথে হাজার বার (অবশ্যই নিশ্চিত করে নিন স্ট্রিংয়ের উপর এমন কিছু করুন যাতে সংকলক পুরো লুপটিকে অপ্টিমাইজ করতে না পারে :-))।
আমার ২.6 গিগাহার্টজ পাওয়ার বইয়ের ফলাফল (এটি একটি ম্যাক :-)) এবং জেডিকে 1.5:
ফলাফলগুলি উল্লেখযোগ্যভাবে পৃথক হওয়ার কারণে, সবচেয়ে সোজা উপায়টিও দ্রুততম বলে মনে হয়। মজার বিষয় হল, স্ট্রিংবিল্ডারের চরআউট () স্ট্রিংয়ের চেয়ে কিছুটা ধীর গতির বলে মনে হচ্ছে।
বিটিডাব্লু আমি ক্যারেক্টারআইটার ব্যবহার না করার পরামর্শ দিই কারণ আমি 'F ইউএফএফএফএফ' চরিত্রের "পুনরাবৃত্তির সমাপ্তি" হিসাবে এর অপব্যবহারকে সত্যই এক ভয়ঙ্কর হ্যাক হিসাবে বিবেচনা করি। বড় প্রকল্পগুলিতে দু'জন ছেলেরা সবসময় দুটি ভিন্ন উদ্দেশ্যে একই ধরণের হ্যাক ব্যবহার করে এবং কোডটি সত্যই রহস্যজনকভাবে ক্র্যাশ করে।
পরীক্ষার মধ্যে একটি এখানে:
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
উল্লিখিত হিসাবে ফিরিয়ে দেয় :
এই ক্রম থেকে চার মানগুলি শূন্য-প্রসারিত করার একটি স্রোত প্রদান করে। যে কোনও চর যা কোনও সারোগেট কোড পয়েন্টে মানচিত্রগুলি ব্যাখ্যা ছাড়াই পাস করা হয়। স্রোতটি পড়ার সময় যদি ক্রমটি পরিবর্তন করা হয় তবে ফলাফলটি অনির্ধারিত।
পদ্ধতিটি ডক অনুসারে codePoints()
একটি ফেরত দেয় IntStream
:
এই ক্রম থেকে কোড পয়েন্ট মানগুলির একটি স্ট্রিম ফেরত দেয়। ক্রমটিতে যে কোনও সারোগেট জোড়ের মুখোমুখি হওয়াগুলি মিলিত হয় যেন চরিত্র.টোকোডপয়েন্ট দ্বারা এবং ফলাফলটি প্রবাহে চলে যায়। সাধারণ বিএমপি অক্ষর, আনপায়ার্ড সার্গেটস এবং অপরিজ্ঞাত কোড ইউনিট সহ অন্য কোনও কোড ইউনিটগুলি শূন্য-প্রসারিত ইনট মানগুলিতে প্রবাহিত হয় যা পরে প্রবাহে প্রেরণ করা হয়।
চর এবং কোড পয়েন্ট কীভাবে আলাদা? এই নিবন্ধে উল্লিখিত হিসাবে :
ইউনিকোড ৩.১ পরিপূরক অক্ষর যুক্ত করেছে, মোট অক্ষরের সংখ্যা 216 টির চেয়ে বেশি হয়ে গেছে যা একক 16-বিট দ্বারা পৃথক করা যায়
char
। অতএব,char
ইউনিকোডের মৌলিক শব্দার্থ ইউনিটে একটি মানটির আর এক থেকে এক ম্যাপিং নেই। অক্ষরের মানগুলির বৃহত্তর সেটকে সমর্থন করার জন্য জেডিকে 5 আপডেট করা হয়েছিল।char
প্রকারের সংজ্ঞা পরিবর্তনের পরিবর্তে কয়েকটি নতুন পরিপূরক চরিত্র দুটিchar
মানের একটি সারোগেট জুড়ি দ্বারা প্রতিনিধিত্ব করে । নামকরণের বিভ্রান্তি হ্রাস করার জন্য, একটি কোড পয়েন্ট এমন পরিসংখ্যানের জন্য ব্যবহার করা হবে যা পরিপূরকগুলি সহ নির্দিষ্ট ইউনিকোড চরিত্রের প্রতিনিধিত্ব করে।
অবশেষে কেন forEachOrdered
এবং না forEach
?
এর আচরণটি forEach
সুস্পষ্টভাবে নিরপেক্ষবাদী যেখানে forEachOrdered
স্ট্রিমটির প্রতিটি ক্রমের জন্য যখন এই স্ট্রিমের প্রতিটি উপাদানটির জন্য ক্রিয়া সম্পাদন করে, স্ট্রিমের এনকাউন্টার অর্ডে যদি স্ট্রিমের একটি সংজ্ঞায়িত ক্রম থাকে order সুতরাং 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
}
আপডেট: যেমন @ অ্যালেক্স উল্লেখ করেছেন, জাভা 8 এর CharSequence#chars
সাথে ব্যবহারেরও রয়েছে। এমনকি টাইপটি ইন্টারস্ট্রিম হয়, তাই এটি অক্ষরের মতো ম্যাপ করা যায়:
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
জেডিকে যে উত্তরাধিকার সূত্রে এটির একটি শ্রেণি ছিল তাই আমি ব্যবহার করব না ।
জাভাদোক বলেছেন:
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
অ্যান্ড্রয়েড x86 এপিআই 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
লুপ ব্যবহার করুন ।
স্ট্রিংটোকেনাইজার তার স্বতন্ত্র অক্ষরগুলিতে স্ট্রিং ভাঙার কাজটি সম্পূর্ণরূপে অসমর্থিত। আপনার সাথে String#split()
সহজেই এমন কোনও রেজেক্স ব্যবহার করে তা করতে পারেন যা কোনও কিছুর সাথে মেলে না, যেমন:
String[] theChars = str.split("|");
তবে স্ট্রিংটোকেনাইজার রিজেক্সগুলি ব্যবহার করে না, এবং এমন কোনও ডিলিমিটার স্ট্রিং নেই যা আপনি নির্দিষ্ট করতে পারবেন যা অক্ষরের মধ্যে কোনও কিছুর সাথে মিলবে না। সেখানে হয় স্ট্রিং নিজেই ব্যবহার বিভেদক স্ট্রিং হিসেবে (ক বিভেদক এটা প্রতিটি চরিত্র উপার্জন) এবং আছে এটা বিভেদক আসতে: এক বুদ্ধিমান সামান্য আপনি একই জিনিস সম্পন্ন করার জন্য ব্যবহার করতে পারেন হ্যাক:
StringTokenizer st = new StringTokenizer(str, str, true);
তবে আমি কেবল এই অপশনগুলি তাদের বরখাস্ত করার উদ্দেশ্যে উল্লেখ করেছি mention উভয় কৌশলই মূল স্ট্রিংটিকে চর আদিমের পরিবর্তে এক-চরিত্রের স্ট্রিংগুলিতে ভেঙে দেয় এবং উভয়ই অবজেক্ট তৈরি এবং স্ট্রিং ম্যানিপুলেশন আকারে ওভারহেডের একটি বিরাট পরিমাণে জড়িত। লুপের জন্য চারএটি () কল করার সাথে এর তুলনা করুন, যা কার্যত কোনও ওভারহেডের জন্য আসে না।
এই উত্তর এবং এই উত্তরটি বিশদভাবে জানাচ্ছি ।
উপরের উত্তরগুলি এখানে অনেকগুলি সমাধানের সমস্যা এখানে নির্দেশ করে যা কোড পয়েন্ট মান দ্বারা পুনরাবৃত্তি করে না - তাদের কোনও সার্গেট অক্ষরের সাথে সমস্যা হবে । জাভা ডক্সও এখানে সমস্যাটির রূপরেখা দেয় (দেখুন "ইউনিকোডের চরিত্রের উপস্থাপনা")। যাইহোক, এখানে এমন কিছু কোড রয়েছে যা পরিপূরক ইউনিকোড সেট থেকে কিছু প্রকৃত সারোগেট অক্ষর ব্যবহার করে এবং সেগুলিকে আবার স্ট্রিংয়ে রূপান্তর করে । নোট করুন যে .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
যদি পারফরম্যান্স ঝুঁকিতে থাকে তবে আমি প্রথমটিকে ধ্রুবক সময়ে ব্যবহার করার পরামর্শ দেব, যদি এটি না হয় তবে জাভাতে স্ট্রিং ক্লাসগুলির সাথে অপরিবর্তনীয়তা বিবেচনা করে দ্বিতীয়টি আপনার কাজটিকে আরও সহজ করে তোলে।