StringTokenizer
? Konversikan String
ke a char[]
dan ulangi itu? Sesuatu yang lain
StringTokenizer
? Konversikan String
ke a char[]
dan ulangi itu? Sesuatu yang lain
Jawaban:
Saya menggunakan for for untuk mengulangi string dan gunakan charAt()
untuk mendapatkan setiap karakter untuk memeriksanya. Karena String diimplementasikan dengan array, charAt()
metode ini adalah operasi waktu yang konstan.
String s = "...stuff...";
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
//Process char
}
Itu yang akan saya lakukan. Sepertinya yang paling mudah bagi saya.
Sejauh kebenarannya, saya tidak percaya yang ada di sini. Itu semua didasarkan pada gaya pribadi Anda.
String.charAt(int)
hanya melakukan value[index]
. Saya pikir Anda bingung chatAt()
dengan hal lain yang memberi Anda poin kode.
Dua pilihan
for(int i = 0, n = s.length() ; i < n ; i++) {
char c = s.charAt(i);
}
atau
for(char c : s.toCharArray()) {
// process c
}
Yang pertama mungkin lebih cepat, kemudian yang kedua mungkin lebih mudah dibaca.
Perhatikan sebagian besar teknik lain yang dijelaskan di sini memecah jika Anda berurusan dengan karakter di luar BMP (Unicode Basic Multilingual Plane ), yaitu titik kode yang berada di luar kisaran u0000-uFFFF. Ini hanya akan jarang terjadi, karena titik kode di luar ini sebagian besar ditugaskan ke bahasa mati. Tetapi ada beberapa karakter yang berguna di luar ini, misalnya beberapa titik kode yang digunakan untuk notasi matematika, dan beberapa digunakan untuk menyandikan nama yang tepat dalam bahasa Cina.
Jika demikian, kode Anda adalah:
String str = "....";
int offset = 0, strLen = str.length();
while (offset < strLen) {
int curChar = str.codePointAt(offset);
offset += Character.charCount(curChar);
// do something with curChar
}
The Character.charCount(int)
Metode membutuhkan Java 5 +.
Saya setuju bahwa StringTokenizer berlebihan di sini. Sebenarnya saya mencoba saran di atas dan mengambil waktu.
Pengujian saya cukup sederhana: buat StringBuilder dengan sekitar satu juta karakter, ubah menjadi String, dan lintasi masing-masingnya dengan charAt () / setelah mengonversi ke char array / dengan CharacterIterator seribu kali (tentu saja memastikan untuk lakukan sesuatu pada string sehingga kompiler tidak dapat mengoptimalkan seluruh loop :-)).
Hasilnya pada Powerbook 2,6 GHz saya (itu mac :-)) dan JDK 1.5:
Karena hasilnya sangat berbeda, cara yang paling mudah juga tampaknya menjadi yang tercepat. Menariknya, karakter () dari StringBuilder tampaknya sedikit lebih lambat daripada yang dimiliki String.
BTW Saya menyarankan untuk tidak menggunakan CharacterIterator karena saya menganggap penyalahgunaan karakter '\ uFFFF' sebagai "akhir iterasi" adalah hack yang sangat mengerikan. Dalam proyek-proyek besar selalu ada dua orang yang menggunakan jenis peretasan yang sama untuk dua tujuan yang berbeda dan kode crash secara misterius.
Inilah salah satu tesnya:
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");
Di Java 8 kita bisa menyelesaikannya sebagai:
String str = "xyz";
str.chars().forEachOrdered(i -> System.out.print((char)i));
str.codePoints().forEachOrdered(i -> System.out.print((char)i));
Method chars () mengembalikan sebuah IntStream
seperti yang disebutkan dalam doc :
Mengembalikan aliran int nol-memperluas nilai char dari urutan ini. Setiap karakter yang memetakan ke titik kode pengganti dilewatkan tanpa ditafsirkan. Jika urutan dimutasi saat aliran sedang dibaca, hasilnya tidak ditentukan.
Metode ini codePoints()
juga mengembalikan IntStream
sesuai dokumen:
Mengembalikan aliran nilai-nilai titik kode dari urutan ini. Setiap pasangan pengganti yang ditemui dalam urutan digabungkan seolah-olah oleh Character.toCodePoint dan hasilnya diteruskan ke aliran. Unit kode lainnya, termasuk karakter BMP biasa, pengganti yang tidak berpasangan, dan unit kode yang tidak ditentukan, adalah nol-diperluas ke nilai int yang kemudian diteruskan ke aliran.
Apa perbedaan antara char dan code point? Seperti disebutkan dalam artikel ini :
Unicode 3.1 menambahkan karakter tambahan, sehingga jumlah total karakter lebih dari 216 karakter yang dapat dibedakan dengan 16-bit tunggal
char
. Oleh karena itu,char
nilai tidak lagi memiliki pemetaan satu-ke-satu ke unit semantik mendasar di Unicode. JDK 5 diperbarui untuk mendukung serangkaian nilai karakter yang lebih besar. Alih-alih mengubah definisichar
tipe, beberapa karakter tambahan baru diwakili oleh pasangan pengganti dari duachar
nilai. Untuk mengurangi kebingungan penamaan, titik kode akan digunakan untuk merujuk ke nomor yang mewakili karakter Unicode tertentu, termasuk yang tambahan.
Akhirnya mengapa forEachOrdered
dan tidak forEach
?
Perilaku forEach
eksplisit nondeterministik di mana sebagai forEachOrdered
melakukan tindakan untuk setiap elemen aliran ini, dalam urutan pertemuan aliran jika aliran memiliki urutan pertemuan yang ditentukan. Jadi forEach
tidak menjamin bahwa pesanan akan disimpan. Periksa juga pertanyaan ini untuk lebih lanjut.
Untuk perbedaan antara karakter, titik kode, mesin terbang dan grapheme, periksa pertanyaan ini .
Ada beberapa kelas khusus untuk ini:
import java.text.*;
final CharacterIterator it = new StringCharacterIterator(s);
for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
// process c
...
}
char
disediakan Java . Java char
berisi 16 bit dan dapat menampung karakter Unicode hingga U + FFFF tetapi Unicode menentukan karakter hingga U + 10FFFF. Menggunakan 16 bit untuk mengkodekan hasil Unicode dalam pengkodean karakter panjang variabel. Sebagian besar jawaban pada halaman ini menganggap bahwa penyandian Java adalah penyandian panjang konstan, yang salah.
Jika Anda memiliki Guava di classpath Anda, berikut ini adalah alternatif yang cukup mudah dibaca. Guava bahkan memiliki implementasi Daftar kustom yang cukup masuk akal untuk kasus ini, jadi ini seharusnya tidak efisien.
for(char c : Lists.charactersOf(yourString)) {
// Do whatever you want
}
UPDATE: Seperti yang dicatat @Alex, dengan Java 8 ada juga yang CharSequence#chars
akan digunakan. Bahkan jenisnya adalah IntStream, sehingga dapat dipetakan ke karakter seperti:
yourString.chars()
.mapToObj(c -> Character.valueOf((char) c))
.forEach(c -> System.out.println(c)); // Or whatever you want
Jika Anda perlu mengulangi poin kode dari String
(lihat jawaban ini ) cara yang lebih pendek / lebih mudah dibaca adalah dengan menggunakan CharSequence#codePoints
metode yang ditambahkan di Java 8:
for(int c : string.codePoints().toArray()){
...
}
atau menggunakan streaming secara langsung, bukan untuk loop:
string.codePoints().forEach(c -> ...);
Ada juga CharSequence#chars
jika Anda ingin aliran karakter (meskipun itu adalah IntStream
, karena tidak ada CharStream
).
Saya tidak akan menggunakannya StringTokenizer
karena ini adalah salah satu kelas di JDK yang merupakan warisan.
Javadoc mengatakan:
StringTokenizer
adalah kelas lawas yang dipertahankan karena alasan kompatibilitas meskipun penggunaannya tidak disarankan dalam kode baru. Disarankan bahwa siapa pun yang mencari fungsi ini menggunakan metode splitString
ataujava.util.regex
paket sebagai gantinya.
Jika Anda memerlukan kinerja, maka Anda harus menguji lingkungan Anda. Tidak ada jalan lain.
Di sini contoh kode:
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);
Di Java online saya mendapatkan:
1 10349420
2 526130
3 484200
0
Di Android x86 API 17 saya mendapatkan:
1 9122107
2 13486911
3 12700778
0
Lihat Tutorial Java: Strings .
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);
}
}
Masukkan panjang int len
dan gunakan for
loop.
StringTokenizer benar-benar tidak cocok untuk tugas memecah string menjadi karakter individu. Dengan String#split()
Anda dapat melakukannya dengan mudah dengan menggunakan regex yang tidak cocok dengan apa pun, misalnya:
String[] theChars = str.split("|");
Tapi StringTokenizer tidak menggunakan regex, dan tidak ada string pembatas yang dapat Anda tentukan yang tidak cocok dengan apa pun di antara karakter. Ada adalah satu kecil yang lucu hack dapat Anda gunakan untuk mencapai hal yang sama: menggunakan string dirinya sebagai pembatas tali (membuat setiap karakter di dalamnya pembatas) dan memilikinya mengembalikan pembatas:
StringTokenizer st = new StringTokenizer(str, str, true);
Namun, saya hanya menyebutkan opsi-opsi ini untuk tujuan pemberhentian mereka. Kedua teknik memecah string asli menjadi string satu karakter, bukan primitif char, dan keduanya melibatkan banyak overhead dalam bentuk pembuatan objek dan manipulasi string. Bandingkan dengan memanggil charAt () di dalam for loop, yang hampir tidak menimbulkan overhead.
Menguraikan jawaban ini dan jawaban ini .
Di atas jawaban menunjukkan masalah banyak solusi di sini yang tidak mengulangi dengan nilai titik kode - mereka akan mengalami masalah dengan karakter pengganti . Dokumen java juga menguraikan masalah di sini (lihat "Representasi Karakter Unicode"). Bagaimanapun, inilah beberapa kode yang menggunakan beberapa karakter pengganti yang sebenarnya dari set Unicode tambahan, dan mengubahnya kembali menjadi String. Perhatikan bahwa .toChars () mengembalikan array karakter: jika Anda berurusan dengan pengganti, Anda harus memiliki dua karakter. Kode ini harus bekerja untuk setiap karakter Unicode.
String supplementary = "Some Supplementary: 𠜎𠜱𠝹𠱓";
supplementary.codePoints().forEach(cp ->
System.out.print(new String(Character.toChars(cp))));
Kode Contoh ini akan membantu Anda keluar!
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);
}
}
Jadi biasanya ada dua cara untuk beralih melalui string di java yang sudah dijawab oleh banyak orang di sini di utas ini, hanya menambahkan versi saya dulu. Pertama menggunakan
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
Jika kinerja dipertaruhkan maka saya akan merekomendasikan untuk menggunakan yang pertama dalam waktu yang konstan, jika tidak maka dengan yang kedua membuat pekerjaan Anda lebih mudah mengingat ketidakmampuan dengan kelas string di java.