Javaの文字列操作など(スッキリJava実践編より)
Javaを使った文字列の色々な操作について書いてあります。書籍『スッキリわかるJava 実践編』に基づいたかなり基礎的な内容ですので、初心者向けの記事になります。書籍(以下、テキスト)にそって自分なりに触ってみた備忘録みたいなものです。
また、文字そのものを表す「文字コード」にも軽く触れています。
目次 Table of Contents
Javaにおける文字と文字列の違い
Java以外の言語には、「一つの文字」と文字が連なった「文字列」の違いをあまり意識しなくてもよい言語がありますが、Javaでは明確に区別しておく必要があります。スッキリJava(以下、テキスト)にも書いてありますが、Javaでは一つの文字をchar型で扱い、文字列をString型で扱います。ですがこのString型とは、文字の一つ一つを格納した配列になっており、各要素を連結したものを返すインスタンスです。
テキストの基礎編で、文字列の連結には”+”演算子を使ってきました。ですが、連結の回数が増えてくると処理時間がかかるということで、ここではStringBuilderやStringBufferを使う方法が解説されています。
実際に速度に違いがあるのかを確認してみます。
“Java”という文字列に”script”という文字列を10000回繰り返し連結する処理を+演算子とStringBuilderを使った方法で行い、それぞれの処理にかかった時間を比較します。比較には、処理の開始時間と終了時間の差分を使いました。
public class test{
public static void main(String[] args){
String str1 = “Java”;
String str2 = “script”;
long startTime = System.currentTimeMillis();
String s = str1;
for(int i = 0; i < 10000; i++){
s = s + str2;
}
long endTime = System.currentTimeMillis();
System.out.println((endTime – startTime) + “ms”);
System.out.println(“———-“);
startTime = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
sb.append(str1);
for(int i = 0; i < 10000; i++){
sb.append(str2);
}
sb.toString();
endTime = System.currentTimeMillis();
System.out.println((endTime – startTime) + “ms”);
}
}
10,000回の連結処理を、複数回行った結果です。このあたりテストする環境にもよるかもしれませんが、僕のパソコンでは平均500倍以上の差がでたことになります。明らかにStringBuilderによる連結の方が速いですね。
これは、Stringインスタンスが「不変性」を持っているためです。最初に String str = “hogehoge”; と文字列を生み出すと、strの内容は書き換えることができません。ですが、strに別の文字列を代入して上書きできるのは、「内部的に一度生成されたString型のstrが破棄されて、再度新たにnewされることで、あたかもstrの内容が上書きされたように見える」という処理がされているためです。文字列の連結回数がかなり多くなる場合は、StringBuilderやStringBufferを使うようにしましょう。
続いてテキストP34にさらっと書いてありますが、String型文字列をtoCharArray()メソッドを使って文字の配列に変換し、一文字一文字ゆっくり表示するサンプルです。
public class test{
public static void main(String[] args){
String str = “こんにちは!僕は今Javaを勉強しています。Javascriptではなく。”;
char[] data = str.toCharArray();
for(int i = 0; i < str.length(); i++){
long startTime = System.currentTimeMillis();
while((System.currentTimeMillis() ? startTime) < 300){
//
}
System.out.print(data[i]);
}
}
}
Javaの正規表現を使った文字列のマッチング
正規表現はあらゆるプログラミングで必須になる基礎文法です。ユーザーが入力した内容におかしなところがないかを判別するときなどに使います。例えば、ユーザー名を「半角英数8文字」で入力することを求められたとき、「_(アンダーバー)」やその他の記号・日本語などを入力すると弾かれますよね。あれです。キーボードからの入力内容をマッチングテストしてみます。
public class test{
public static void main(String[] args){
System.out.println(“ユーザー名を8文字で入力してください。(最初の文字は半角英、残りは半角英数))”);
String userName = new java.util.Scanner(System.in).nextLine();
if(isMatchUserName(userName)){
System.out.println(“マッチしました。”);
} else {
System.out.println(“正しく入力してください。”);
}
}
public static boolean isMatchUserName(String userName){
boolean boo = userName.matches(“[A-Za-z][A-Za-z0-9]{7}”);
return boo;
}
}
正規表現にはテキストに書いてあるもの以外にも色々な表現方法があるので、必要に応じて覚えていきたいですね。試しに、”Java and C# are similar.C# and C++ aren’t similar!”という文字列にマッチする正規表現を見てみます。
簡単に、次の条件でマッチすることを確認します。
・先頭の文字が大文字のJ
・その後次に該当する文字がいくつか続く(a-z、A-Z、0-9、#、+、’、スペース、.)
・最後の文字が!
半角スペースを文字クラス[]の中で表現するときは、そのままスペースを入力します。
public class test{
public static void main(String[] args){
String str = “Java and C# are similar.C# and C++ aren’t similar!”;
boolean boo = str.matches(“^[J][a-zA-Z0-9#+’ .]+[!]$”);
if(boo){
System.out.println(“マッチしました”);
} else {
System.out.println(“正しく入力してください”);
}
}
}
文字のバイトコードを取得したり文字コードから文字列を生成
Javaに限らず、コンピュータ上に表示される文字は「文字コード」で管理されています。アルファベットや数字、記号、日本語やその他の国の言語など、膨大な数の文字が存在しますが、それらを一意に判別するために個別の数字が割り振られていて、その数字のことを文字コードといいます。
場合によってはUTF-やSHIFT-JISなどのエンコード(エンコーディング)のことを文字コードと呼んでいる場合もありますので注意してください。エンコードとは、特定の文字と数字(文字コード)とを一致させるためのルールのことです。当サイトではUTF-8を使っていますので、UTF-8のルールに則った文字コードが各文字に割り振られていることになります。
以下はgetBytesメソッドを使って文字のバイトコードを取得しています。UTF-8では文字に対して1~4桁の数字(文字コード)が振られています。
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
public class test{
public static void main(String[] args){
String str = “Java”;
byte[] stringByte = str.getBytes(StandardCharsets.UTF_8);
for(byte value : stringByte){
System.out.println(value);
}
String str1 = new String(stringByte);
System.out.println(str1);
}
}
なお、上記のgetByteメソッドを使う方法の他に、char型の文字をint型にキャストすることで文字コードを得ることもできます。
import java.util.ArrayList;
public class test{
public static void main(String[] args){
char c = ‘v’;
int byteCode = (int)c;
System.out.println(byteCode);
//文字列から文字を配列で取得し、それぞれのバイトコードを格納した配列を取得
System.out.println(“———————“);
String str = “Java”;
ArrayList codeArray = new ArrayList();
for(int i = 0; i < str.length(); i++){
int code = (int)str.charAt(i);
codeArray.add(code);
}
for(Integer value : codeArray){
System.out.println(value);
}
}
}