検索

キーワード

【Java】MessageFormatクラスでの文字列置換

こんちには。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!【java.textパッケージ】MessageFormatクラスMessageFormatは、連結されたメッセージを、言語に依存しない方法で構築するためのクラスです。文字列の一部を外部から渡される値(パラメータ)で置き換える時に使用できます。Javaではreplaceメソッドや正規表現で置換の操作を行うこともできますが、エラーメッセージや日付時刻など、定形文字列の一部を置き換えたい場合は、MessageFormatクラスを使うと便利です。Stringクラスのreplaceメソッドに関しては以下のリンク先記事で紹介しています。リンク:【Java】Stringを理解しよう/置換このクラスでは引数に Object型を使用することができます。Object型は全てのデータ型に対する基底のデータ型(クラス型変数)でObjectクラスのオブジェクトです。今回は以下のMessegeFormatクラスを利用した文字列置換を紹介します。▼staticメソッドを使ってフォーマットする方法▼インスタンスを生成してからフォーマットする方法▼数値または日時のフォーマットを指定する方法MessageFormatクラスはjava.textパッケージの中に存在しているため、使う時はjava.text.MessageFormatをインポートする必要があります。▼staticメソッドを使ってフォーマットする方法staticメソッドを使うやり方では、formatメソッドが呼ばれたときに内部的には一回限りの目的でMessageFormat インスタンスを生成します。 後でパラメータを操作できないので注意しましょう。MessageFormatクラスのformatメソッドは第一引数にフォーマットの文字列を指定します。このフォーマット文字列には、【{0},{1},{2}...】のArgumentIndex(引数インデックス)を含めます。ArgumentIndex(引数インデックス)は文字列の一部を外部から渡される値(パラメータ)の置換対象です。文字列の例:"エラーメッセージ:{0} 個数は{1}個以上にしてください。""{0}件のエラーを確認しました。{1}を書き直してください。{2}を半角英数字で入力してください。""Aグループは{0}人、Bグループは{1}人、Cグループは{2}人です。"ここでは基本的な操作方法として下記の2つを紹介します。第二引数にObject配列を指定するやり方(formatメソッド)第二引数以降にArgumentIndex(引数インデックス)分のオブジェクトを指定するやり方(formatメソッド)Stringクラスのformatメソッドについては下記のリンク先記事で紹介しています。リンク:後日掲載予定第二引数にObject配列を指定するやり方(formatメソッド)String format(String ,Object配列)Object配列の要素には、型にとらわれず要素を指定することができます。import java.text.MessageFormat; public class Test { public static void main(String[] args) { Object[] o = { "数十", 127,12345}; String s = MessageFormat.format( "Aグループは{0}人、Bグループは{1}人、Cグループは{2}人です。", o); System.out.println(s); } }出力すると以下のようになります。Aグループは数十人、Bグループは127人、Cグループは12,345人です。第二引数以降にArgumentIndex(引数インデックス)分のオブジェクトを指定するやり方(formatメソッド)String format(String ,ArgumentIndex(引数インデックス)分のオブジェクト...)第二引数以降にArgumentIndex(引数インデックス)分のオブジェクトを指定します。どんな指定することができます。第二引数に指定されたオブジェクトが、ArgumentIndexの{0}に割り当たります。以降追加されるごとに、インデックスのように値が+1され、そのオブジェクトへ割り振られていきます。ArgumentIndex(引数インデックス)分以上を指定すると例外が発生します。import java.text.MessageFormat; public class Test { public static void main(String[] args) { String x ="数十"; byte y =127; int z =12345; String s = MessageFormat.format( "Aグループは{0}人、Bグループは{1}人、Cグループは{2}人です。", x,y,z); System.out.println(s); } }出力すると以下のようになります。Aグループは数十人、Bグループは127人、Cグループは12,345人です。▼インスタンスを生成してからフォーマットする方法インスタンスの生成時にフォーマットの文字列を引数に取ります。同じフォーマット(テンプレート)に対して様々なパラメータで置換をすることができます。ループ処理などで、同じフォーマットに対して複数回処理する場合に、毎回パターンを定義する必要がないため、staticメソッドのformat()を使った場合より高速になります。 初期化(インスタンス化)とString値への変換(toPatternメソッド)MessageFormat messageformat = new MessageFormat(文字列);【{0},{1},{2}...】のArgumentIndex(引数インデックス)を含むフォーマットの文字列を指定します。MessageFormatに現在設定されているパターン文字列を取得するには、MassegeFormatクラスのtoPatternメソッドを使用します。String toPattern() 以下の例で実際に初期化を行っているところを確認しましょう。import java.text.MessageFormat; public class Test { public static void main(String[] args) { //初期化 MessageFormat mf = new MessageFormat( "Aグループは{0}人、Bグループは{1}人、Cグループは{2}人です。"); //String値へ変換 String s= mf.toPattern(); System.out.println(s); }出力すると以下の様になります。Aグループは{0}人、Bグループは{1}人、Cグループは{2}人です。これで初期化は完了です。要素の置き換え(formatメソッド) 初期化した文字列の一部をパラメータへ置き換えましょう。 String format(クラス型の配列)引数には、String[]やObject[]などのクラス型配列を使います。インスタンス化して使う方法のformatメソッドはjava.text.Formatクラスから継承したメソッドです。intやlongなどの基本データ型を代入したい際は、ラッパーしたクラス型を使います。下の表を見てください。ラップしたクラス型とは「型」に加工処理機能(メソッドなど)を持たせるためにクラス化させた型を指します。クラス化のルールに従って型の先頭文字は大文字で表記されます。また本来の名前で表記されます。以下の例で実際に要素の置き換えをしてみましょう。import java.text.MessageFormat; public class Test { public static void main(String[] args) { MessageFormat mf = new MessageFormat( "Aグループは{0}人、Bグループは{1}人、Cグループは{2}人です。"); Integer[] i = { 50, 20, 40 }; String[] s = { "日本", "イギリス", "オーストラリア" }; Object[] o = { "数十",127, 12345 }; System.out.println(mf.format(i)); System.out.println(mf.format(s)); System.out.println(mf.format(o)); } } 出力すると以下のようになります。Aグループは50人、Bグループは20人、Cグループは40人です。 Aグループは日本人、Bグループはイギリス人、Cグループはオーストラリア人です。 Aグループは数十人、Bグループは127人、Cグループは12,345人です。▼数値または日時のフォーマットを指定する方法数値フォーマットの操作MessegeFormatクラスは、数字にフォーマットの指定をして表示することができます。【{0},{1},{2}...】のArgumentIndex(引数インデックス)に フォーマットのスタイルを追加することで表示可能です。デフォルトの数値フォーマットは、千桁ごとにカンマが入るようになっています。以下のような書き方でフォーマットを変更できます。カンマなしの表示:{ArgumentIndex,number,#}ゼロ埋め(パディング)の表示:{ArgumentIndex,number,00000}使用例を見てみましょう。import java.text.MessageFormat; public class Test { public static void main(String[] args) { //Object配列 Object[] o = { 1234,1234,1234}; String s = MessageFormat.format( "Aグループは{0}人、" + "Bグループは{1,number,#}人、" + "Cグループは{2,number,00000000}人です。",o); System.out.println(s); } }出力すると以下のようになります。Aグループは1,234人、Bグループは1234人、Cグループは00001234人です。日付時刻フォーマットの操作MessegeFormatクラスではフォーマットへ日付時刻を置換することが可能です。Dateクラス・Calendarクラスを使った日付時刻取得(旧API)での置換java.timeパッケージを利用した日付時刻取得 (Date And Time API-Java8)での置換をみていきましょう。日付時刻の取得について詳しくは以下の記事で紹介しています。APIについて理解が不十分の方はこちらで理解を深めましょう。リンク:【Java】日付取得(新API-Java8)    【Java】日時取得(従来API)-java.util.Date, java.util.Calendar ※後日掲載記事追加予定Dateクラス・Calendarクラスを使った日付時刻取得(旧API)での置換Dateクラスのインスタンスを生成して日付時刻を表示させます。【{0},{1},{2}...】のArgumentIndex(引数インデックス)に【date/time】を追加することで日時を個々に表示可能です。また、フォーマットのスタイルを追加することで以下のように任意のフォーマットが指定できます。date/フォーマットの表示:{ArgumentIndex,date,yyyy年MM月dd日}time/フォーマットの表示:{ArgumentIndex,time,HH時mm分ss秒}詳しいフォーマットの指定記述は、【Java】日付時刻(従来のAPI) - 操作(計算、比較、フォーマット)の記事を参考にしてください。※後日掲載予定①【staticメソッドを使ってフォーマットする方法】での表示import java.text.MessageFormat; import java.util.Date; public class Test { public static void main(String[] args) { Date d = new Date(); String s = MessageFormat.format( "本日は{0}です。" + "日付:{0,date}と" + "時刻:{0,time}を分けて表示も可能です。",d); String t =MessageFormat.format( "日付:{0,date,yyyy年MM月dd日}と" + "時刻:{0,time,HH時mm分ss秒}でフォーマット表示も可能です。",d); System.out.println(s); System.out.println(t); } }出力すると以下のようになります。本日は2020/08/06 18:52です。日付:2020/08/06と時刻:18:52:11を分けて表示も可能です。 日付:2020年08月06日と時刻:18時52分11秒でフォーマット表示も可能です。 ②【インスタンスを生成してからフォーマットする方法】での表示import java.text.MessageFormat; import java.util.Date; public class Test { public static void main(String[] args) { MessageFormat mf = new MessageFormat("本日は{0}です。"); MessageFormat mf2= new MessageFormat("日付は{0,date}です。"); MessageFormat mf3= new MessageFormat("時刻は{0,time}です。"); Object[] d = {new Date()}; System.out.println(mf.format(d)); System.out.println(mf2.format(d)); System.out.println(mf3.format(d)); } }出力すると以下のようになります。本日は2020/08/06 12:04です。 日付は2020/08/06です。 時刻は12:04:51です。ここでの表示においても【{0},{1},{2}...】のArgumentIndex(引数インデックス)にフォーマットのスタイルを追加することで①と同じように任意のフォーマットが指定できます。java.timeパッケージを利用した日付時刻取得 (Date And Time API-Java8)での置換①【staticメソッドを使ってフォーマットする方法】での表示import java.text.MessageFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; public class Test { public static void main(String[] args) { String s = MessageFormat.format( "本日は{0}です。" + "日付:{1}は時刻:{2}を分けて表示も可能です。", LocalDateTime.now(), LocalDate.now(), LocalTime.now() ); System.out.println(s); } }出力すると以下のようになります。本日は2020-08-06T12:58:59.041935100です。日付:2020-08-06は時刻:12:58:59.042934300を分けて表示も可能です。※java.timeパッケージを利用した日付時刻取得では日時のフォーマットを操作してから置換することもできます。詳しいフォーマットの指定記述は、【Java】日付時刻(新API) - 操作(計算、比較、フォーマット)を参考にしてください。※後日掲載予定import java.text.MessageFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; public class Test { public static void main(String[] args) { //インスタンス生成 LocalDateTime localDateTime = LocalDateTime.now(); LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); //フォーマット操作 DateTimeFormatter datetime = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH時mm分ss秒"); DateTimeFormatter date = DateTimeFormatter.ofPattern("yyyy-MM-dd"); DateTimeFormatter time = DateTimeFormatter.ofPattern("HH:mm:ss:SS"); //置換 String s = MessageFormat.format( "本日は{0}です。" + "日付:{1}は時刻:{2}を分けて表示も可能です。", localDateTime.format(datetime), localDate.format(date), localTime.format(time) ); System.out.println(s); } }出力すると以下のようになります。本日は2020年08月06日 13時12分20秒です。日付:2020-08-06は時刻:13:12:20:71を分けて表示も可能です。②【インスタンスを生成してからフォーマットする方法】での表示import java.text.MessageFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; public class Test { public static void main(String[] args) { MessageFormat mf = new MessageFormat("本日は{0}です。"); MessageFormat mf2= new MessageFormat("日付は{0}です。"); MessageFormat mf3= new MessageFormat("時刻は{0}です。"); Object[] dt= {LocalDateTime.now()}; Object[] d = {LocalDate.now()}; Object[] t = {LocalTime.now()}; System.out.println(mf.format(dt)); System.out.println(mf2.format(d)); System.out.println(mf3.format(t)); } }出力すると以下のようになります。本日は2020-08-06T13:17:03.757747400です。 日付は2020-08-06です。 時刻は13:17:03.757747400です。※①と同様に日時のフォーマットを操作してから置換することもできます。あとがき私が働いているフォワードソフト株式会社では成長意欲旺盛なエンジニアが多く在籍しております。また東京ITカレッジでは他にも多様なプログラミング情報を掲載しています。 まずは一度サイトを覗いてみてください!お待ちしています!

【Java】 import宣言について紹介

こんにちは、駆け出しプログラマーの若江です!ここでは初学者として学習を終えた私が、アウトプットの意味も込めて import について紹介させていただきます。できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!関連記事リンク:パッケージの紹介 / Mathメソッドの紹介import1つのプロジェクト開発の中で、多くのクラスやインターフェースを作成することになりますが、それらは機能ごとにパッケージでまとめられて、アクセスの管理がされています。ここでは他(外部)のパッケージに保持されているクラス・インターフェースの中で、アクセスが許可されているクラスやインターフェースを import する方法について紹介させていただきます。 ※import はパッケージの機能と深く関わりがあるためパッケージがわからない方は、  関連記事よりパッケージの紹介をご一読いただくことをおすすめします。import の役割クラスを作成すると通常は、同じパッケージ内のクラスへアクセスすることができますが、その他の外部パッケージにあるクラスやインターフェースへはアクセスできません。このような外部パッケージのクラスやインターフェースへアクセス可能にするためには、その度「xxxパッケージの Oooクラスにあるこのメソッド!」といったように正確に指定しなければなりません。◆ java の lang の中の Mathクラス にある定数 PI を使う場合// 2 x 2 x PI(円周率) を出力 System.out.println(2*2*java.lang.Math.PI); // 結果:12.5663...何度も同じクラスやメソッドを使う場合、上記のように「java.lang.Math.PI」と呼ぶ方法ではプログラミングに対してかなりの負担となってきます。このような負担を1回の記述のみへ軽減するために import 機能が存在します。import の種類と宣言import の方法には、クラスやインターフェースへアクセスするタイプと、static 領域のメソッドや変数へアクセスするタイプの2種類が存在します。import の宣言方法と2種類の import の違いについて見ていきましょう。◆ import は「package」宣言直下で import 宣言を行います。 import 宣言位置は2種類とも同じです。package com.xxx.Ooo; import com.xxx.Test; // ここで import 宣言 public class Sample{ }import の宣言方法import の宣言方法はそれぞれ「import」「import static」と宣言します。また宣言に続くアクセスするクラスの指定は、全ての階層を記述して明確に指定します。このような「明確な名前」のことを「完全修飾名」と呼びます。・     import     :クラスやインターフェースへアクセスして、インスタンス生成やメソッドの利用を可能にします。         import 宣言はクラスまで指定をします。// com の中の xxx パッケージにある Test クラスへアクセス import com.xxx.Test;・import static:static 領域のメソッドや変数へアクセスして、メソッドや変数の利用を可能にします。         import static 宣言はメソッドまで指定します。// com の中の xxx パッケージにある Ooo クラスの static な method メソッドへアクセス import static com.xxx.Ooo.method;※static については別記事にて紹介させていただきますが簡単に紹介すると、 static 宣言された変数やメソッドは、クラスのインスタンス化なしでアクセスが可能となります。以上を参考に「import しない場合」「import した場合」「import static した場合」のメソッドの利用を比較してみましょう。冒頭で例に出した Mathクラスを使って比較してみます。System.out.println(2*2*java.lang.Math.PI); // import しない場合 System.out.println(2*2*Math.PI); // import した場合 System.out.println(2*2*PI); // import static した場合 かなり簡略化できましたね。また import は「パッケージに含まれるすべてのクラス」や「クラスにある全てのメソッド」といった指定を「アスタリスク( * )」を使うことで指定することが可能です。// com の中の xxx パッケージにある全てのクラスへアクセス import com.xxx.*; // com の中の xxx パッケージにある Test クラスの全ての static なメソッドへアクセス import static com.xxx.Test.*;このように全てを import することを「オンデマンドインポート」と呼びます。上記のようにクラスで1度 import 宣言をしておけば、以降は完全修飾名の記述を気にすることなく、インスタンスの生成やメソッドの呼び出しができるようになります。import する際に気を付けることパッケージの仕組み上、クラス名またはインターフェース名が重複することも考えられます。重複した名前のクラスなどを両方 import すると、どちらを使うのかが判断できずコンパイルエラーとなります。// com の中の xxxパッケージにある Oooクラス import com.xxx.Ooo; // com の中の testパッケージにある Oooクラス import com.test.Ooo; //クラス名が同名のためインスタンス生成などができないまたアクセス修飾子が public 以外のメソッドや変数は、import を宣言してもアクセス制御のルールに基づいてアクセスが拒否される可能性もあるため注意しましょう。◆ sampleパッケージの Sampleクラスに「public の method1」と「private の method2」メソッドを作成package sample; public class Sample { public String method1(String test1) { return test1; } private String method2(String test2) { return test2; } }◆ testパッケージの Testクラスを作成、上記 Sampleクラスを import、インスタンス生成して method1 と method2 を呼ぶpackage test; import sample.Sample; public class Test{ public static void main(String[] arg) { Sample sample = new Sample(); sample.method1("a"); // public のためアクセス可能 sample.method2("a"); // private のためコンパイルエラー } }method2 はアクセス修飾子が pritvate のためコンパイルエラーとなります。また、import 宣言なしで利用できるパッケージも存在します。Java でプログラミングを行う際に必ず使う String などを含んだ「java.lang」パッケージは、頻繁に利用されるためあらかじめ import されており宣言の必要がありません。※import について理解しやすいため今回は「Math」を import の例としましたが、 「Math」も「java.lang」に属するため実は「Math.PI」のように宣言なしで使うことができます。まとめJava のパッケージにはデータやファイルの入出力を主要な機能とした「java.io」パッケージやコレクションや日時機能を主要とした「java.util」といったパッケージをはじめ、たくさんの便利なパッケージが用意されています。必要に応じて import を活用していきましょう。関連記事リンクパッケージの紹介 / Mathメソッドの紹介おまけプログラミングの学習やエンジニアへのキャリアチェンジをお考えの方へ独学からスピードアップして効率よく学習を進めたい方は、『東京ITカレッジ』を、ご自身のスキルを活かしたい方は、『フォワードソフト株式会社』をぜひチェックしてみてください!

【Java】浮動小数点の誤差の原因と対処法

こんにちは。駆け出しプログラマーの松倉です!ここでは、浮動小数点の誤差の原因とその対処法について紹介・解説します。プログラミング未経験の方、Javaについて勉強している方、これから勉強したいと思っている方の参考になれば幸いです!浮動小数点の誤差の原因と対処法javaではすべての計算処理は内部的に 2進数で表現されています。2進数で表現した場合に無限小数となる数の演算は全て、浮動小数点に誤差が発生する可能性があります。基本データ型は桁数が有限であるため、収まらない部分は四捨五入して近似値で表現されます。厳密な計算が求められる場合、この誤差は積み重なるほど大きな相違が起こり問題となります。この記事では浮動小数点の誤差とその対策法など以下について解説します。・基本データ型の有効範囲・浮動小数点の誤差・BigDecimalクラス・BigDecimalによる演算・BigIntegerクラス関連記事リンク:【Java】Mathクラスの使い方(基本的な数値処理)基本データ型の有効範囲整数を扱うデータ型はいくつかありますが、型毎に扱えるデータの種類や範囲が決められています。基本データ型には整数や浮動小数点数、文字、論理型が用意されています。javaでは計算を効率よく行えるようにするため、扱える値を一定の範囲までにしか使えないようになっています。Javaで用意されている基本データ型とその有効範囲は以下になります。                 浮動小数点の誤差丸め誤差とは、コンピュータが数値を 2進法を用いて限られた桁数で表現することにより発生する誤差です。2進数で表現しようとすると循環小数になり近似値を使わざるを得ない場合に生じます。浮動小数点型( float型や double型)の変数を使用する際に、型の桁数は有限であるため、無限小数は必ず丸め込みがされることがあります。例えば 10進数の 0.1を 2進数で表すと 0.00011001100110011…となり循環小数になります。0.8 + 0.9の計算を行ったサンプルコードを確認しましょう。public class Sample1 { public static void main(String[] args) { double i1 = 0.8; double i2 = 0.9; System.out.println(i1 + i2); } } 実行結果:1.7000000000000002 計算すると「 0.8 + 0.9 = 1.7」と算出されるはずですが、double型で算術演算子を使った場合誤差が生じて正確な値が算出できていません。小数点以下の誤差が許されない場合には浮動小数点型を使用しないように気をつけましょう。 BigDecimalクラスBigDecimalクラスは Javaで少数を扱う場合、丸め誤差が発生したときの小数点以下を正確に扱う為、または誤差についての処理方法を厳密にするために用意されています。引数には浮動小数点数型と文字列型どちらも指定することができますが、浮動小数点数型を指定した場合、誤差が発生するので注意が必要になります。正確な値を扱う場合、BigDecimalのコンストラクタの引数は文字列型で指定しましょう。BigDecimalクラスは java.mathパッケージに属しており、java.lang.Mathクラスが提供するメソッドと同等のものを提供しています。BigDecimalクラスを使用するには、「 java.math.BigDecimal; 」をインポートします。BigDecimal型の使い方BigDecimal 変数名 = new BigDecimal("数値"); ※数値の部分はダブルクオーテーション(" ")で閉じる必要があります。(" ")で閉じていない場合、引数の数値が int型や double型などに認識され誤差が生じます。 BigDecimalクラスのコンストラクタの引数を double型と String型で指定した場合のサンプルコードを確認しましょう。import java.math.BigDecimal; public class Sample2 { public static void main(String[] args) { BigDecimal i1 = new BigDecimal(0.6); //double型で指定 BigDecimal i2 = new BigDecimal("0.6"); //String型で指定 System.out.println(i1); System.out.println(i2); } } 実行結果:0.59999999999999997779553950749686919152736663818359375 0.6 BigDecimalクラスで double型を指定した場合、実行結果をみると誤差が発生しているのがわかります。一方で String型を指定した場合、指定した通りの値が出力されています。※BigDecimalクラスで正確な計算ができるのであれば、全てBigDecimalを使えば良いと思いがちですが、これは仕様によって判断しなければなりません。個数や身長の平均値のような小数何十桁の精度がいらない表面上人間が感知できない場合、この誤差は本質的に無視できます。そのため演算すべてに BigDecimalクラスの丸めを指定することでコードが複雑になったり、演算処理速度が遅くなるデメリットも発生することを認識しておきましょう。BigDecimalによる演算BigDecimalクラスには、四則演算等の計算用のメソッドが用意されています。BigDecimalを使った四則演算については以下のようになります。・足し算 add()・引き算 subtract()・掛け算 multiply()・割り算 divide() 各メソッドを使った演算のサンプルコードを確認しましょう。import java.math.BigDecimal; public class Sample3 { public static void main(String[] args) { BigDecimal i1 = new BigDecimal("5.0"); BigDecimal i2 = new BigDecimal("10.0"); BigDecimal i3 = new BigDecimal("3.0"); BigDecimal add = i1.add(i2); //足し算 BigDecimal sub = i1.subtract(i2); //引き算 BigDecimal mul = i1.multiply(i3); // 掛け算 BigDecimal div = i2.divide(i3, 2, BigDecimal.ROUND_HALF_UP); //割り算(少数第3位で四捨五入) System.out.println("足し算: " + add); System.out.println("引き算: " + sub); System.out.println("掛け算: " + mul); System.out.println("割り算: " + div); } }実行結果:足し算: 15.0 引き算: -5.0 掛け算: 15.00 割り算: 3.33 ※割り算の場合、下記のように丸め処理を記述せずに割り切れない計算をすると無限小数となり、ArithmeticExceptionの例外が発生します。そのため実行結果の値を少数第 3位で四捨五入を行っています。BigIntegerクラスBigIntegerクラスは Javaで数学的な処理をする際に、扱う数値が基本データ型では扱えない程大きい場合に利用します。long型の最大値は 9223372036854775807ですが、例えば 20桁(一垓)のような値は大きすぎて格納できる型がありません。BigIntegerクラスに情報を格納するためのメモリは動的に割り当てられるため、論理的には BigIntegerクラスに格納できる値に上限はありません。BigIntegerクラスは java.mathパッケージに属しており、java.lang.Mathクラスが提供するメソッドと同等のものを提供しています。BigIntegerクラスを使用するには、「 java.math.BigInteger;」をインポートします。BigIntegerクラスを使った四則演算については以下のようになります。・足し算 add()・引き算 subtract()・掛け算 multiply()・割り算 divide()また、基本データ型への変換メソッドも提供されています。intValue()メソッドはBigIntegerクラスの値をint型へした変換値を返却することもできます。intに変換する際に桁落ちなどで失われた情報がないかどうかを確認する場合、intValueExact()メソッドを使用します。int型の範囲から外れている場合は、ArithmeticExceptionを返却します。 有効範囲外の値同士の掛け算をサンプルコードで確認しましょう。import java.math.BigInteger; public class Sample4 { public static void main(String[] args) { BigInteger i1 = new BigInteger("214748364744444444444444444444444444"); BigInteger i2 = new BigInteger("-214748364744444444444444444444444444"); System.out.println(i1.multiply(i2)); } } 実行結果:-46116860160412949620864197530864197339976762202469135802469135802469136BigIntegerクラスを用いることで int型、long型の有効範囲外の値が出力されています。まとめ浮動小数点の誤差と BigDecimalクラス、BigIntegerクラスについて解説しました。数値の小数点以下を正確に扱う上でぜひ理解しておきましょう。float型や double型では、演算処理の過程で誤差が積み重なり、正確な値が出力されない場合もあります。金額など厳密な計算が必要な場合などは BigDecimalクラスを使って計算するようにしましょう。また基本データ型の有効範囲外の値を用いる場合、BigIntegerクラスを使いましょう。普通の計算方法とは違うので慣れが必要かもしれませんが、覚えておいて損はありません!しっかりと学習しましょう!  おまけプログラミングの学習やエンジニアへのキャリアチェンジをお考えの方へ『東京ITカレッジ』、『フォワードソフト株式会社』ぜひチェックしてみてください!関連記事リンク:【Java】Mathクラスの使い方(基本的な数値処理)

【Java】 パッケージについて紹介

こんにちは、駆け出しプログラマーの若江です!ここでは初学者として学習を終えた私が、アウトプットの意味も込めてパッケージについて紹介させていただきます。できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!関連記事リンク:命名規則の紹介パッケージパッケージは複数の設計図(クラスやインターフェースなど)を1つのファイルにまとめておく役割をします。開発するプロジェクトの中身をきれいに整理整頓する他にも、設計図の置き場所を詳しく示す目印にもなったりと、プロジェクト開発に欠かせない基礎知識です。ここではパッケージの役割やルールについて紹介させていただきます。パッケージの役割先ほど紹介した通りパッケージにはプロジェクトの部品設計図となる「クラス」や「インターフェース」というものをまとめ置く役割があります。Javaでは通常、クラスやインターフェースに同じ名前を付けて保存しておくことができないですが、新たに別のパッケージを作ることによって、同名のクラスやインターフェースを別パッケージ内に用意することも可能となります。 例) パッケージA{ クラス1、クラス2、クラス3 }    パッケージB{ クラス1、クラス2、クラス3 }    パッケージAとパッケージBのクラスは同名ですが別物の扱いになりますこのようにパッケージによってクラスを分類することができるため、「パッケージAにあるクラス1」 といったようにクラスの置き場所を正確に特定することができます。またパッケージはプロジェクトの「動作指示機能」や「データ保持機能」「データ登録機能」など機能ごとでわけられます。 例) パッケージA は動作指示機能:クラス1(エンジン動作)、クラス2(車輪動作)    パッケージB はデータ保持機能:クラス1(スピードデータの保持)、クラス2(車輪の回転数データ保持)    パッケージC はデータ登録機能:クラス1(今日の平均速度を登録)、クラス2(今日の走行距離を登録)パッケージの管理機能が書かれたクラスやインターフェースの一番上には、そのクラス・インターフェースがどのパッケージに入っているかが記され管理されます。記述の方法は、「package」の宣言と「クラス・インターフェースを除く全ての階層名」で書かれ、階層名はインターネットのドメイン名を逆順にした名前を使います。・階層とは、入れ子構造のファイルです。 ロシアのマトリョーシカをイメージするとわかりやすいかもしれませんね。・ドメインとは、インターネット上でそのプロジェクトへアクセスする「住所」のような役割をしています。 「xxx.com」や「ooo.co.jp」などを見ると馴染みがあるかと思います。 ドメイン名でパッケージ宣言をしておくことでそのパッケージを一般に公開、配布できるようになります。・パッケージの宣言: package com.xxx.ooo; 「com」から順番に階層1、「xxx」が階層2、「ooo」が階層3となっていきます。 この場合「com」ファイルの中の「xxx」ファイルの中の「ooo」に入っているクラス・インターフェースとなります。 また階層の区切りは「ピリオド( . )」で区切ります。◆パッケージ宣言例// com 階層にある test の階層にある controller の中のクラス・インターフェース package com.test.controller;ちなみにパッケージ名はプログラマー自身で名付けます。名付け方にはルールがあるため、名付け方がわからないという方は、関連記事リンクよりルールの確認をしてみてください。パッケージのアクセス制約パッケージは基本的に同パッケージ内にあるクラスやインターフェース同士のみアクセスすることが許可されています。 例) パッケージA { クラス1, クラス2, クラス3 }     ➡クラス1の一部機能をクラス2で使用可能◎    パッケージB { クラス1, クラス2, クラス3 }     ➡パッケージBのクラス1でパッケージAのクラス2は使用できない×ただし実際の開発となると、他(外部)パッケージに入っているクラスやインターフェースの機能を使いたい状況が生まれます。その際は他パッケージの公開が許可されているクラス・インターフェースを「import」宣言することでアクセス可能となります。反対にパッケージ内の特定のクラス・インターフェースを非公開にしてアクセス不可にすることもできます。このアクセス可能/不可を制御する機能を「アクセス修飾子」と呼びます。※「import」するクラスの名前が重複する場合はコンパイルエラーとなるので注意してください。※「import」「アクセス修飾子」に関してはそれぞれ別記事で紹介させていただきます。このようにパッケージの仕組みを使うことでクラスやインターフェースのアクセスを管理することができるようになります。まとめパッケージはクラスやインターフェースを1つのグループとしてまとめることができます。パッケージの宣言をドメイン名で命名することで、誰でも公開されたクラスやインターフェースへアクセスすることができるようになります。import宣言をすることで外部パッケージへアクセスすることが可能となります。関連記事リンク命名規則の紹介おまけプログラミングの学習やエンジニアへのキャリアチェンジをお考えの方へ独学からスピードアップして効率よく学習を進めたい方は、『東京ITカレッジ』を、ご自身のスキルを活かしたい方は、『フォワードソフト株式会社』をぜひチェックしてみてください!

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ/【Java】JSPのディレクティブ/【Java】JSPのEL式JSTLとは?JSTLは「JSP Standard Tag Library」の略で、JSP内でよく使われる機能をタグライブラリとしてまとめたものです。JSTLとEL式を組み合わせることで、スクリプトレットレスなJSPを記述することが可能となり、可読性・保守性が向上します。また、実装が既に提供されており、開発者がタグの実装をしなくて済むため、開発時間の短縮につながる事や、ノウハウが蓄積され標準化された仕様であるため、高い安定性がある事がメリットといえます。JSPのアクションタグを独自に作成して利用できるようにしたものをカスタムタグと呼び、このカスタムタグをまとめてライブラリ化したものをタグライブラリと呼びます。JSTLに含まれているタグライブラリJSTLは提供される機能により、5つのタグライブラリ(Core, i18n, Database, XML, Functions)に分類されています。※この記事ではよく使われるものとして、Core, i18nの一部のタグについて紹介します。JSTLを使う準備JSTLのタグライブラリは、JARファイル形式で提供されており、JSPの動作環境にそのまま追加して使用することが可能です。※Eclipseの動的Webプロジェクトでの構成を前提に説明します。jarファイルの入手方法以下のサイトからJSTLのjarファイルをダウンロードします。Apache Tomcatのサイトhttps://tomcat.apache.org/download-taglibs.cgiダウンロードするファイル・taglibs-standard-impl-1.2.5.jar・taglibs-standard-jstlel-1.2.5.jar・taglibs-standard-spec-1.2.5.jarjarファイルの配置方法ダウンロードしたjarファイルを対象プロジェクトの「WEB-INF\lib」配下に配置します。eclipseのプロジェクトエクスプローラーで見たときに以下のような構成になります。タグライブラリの使用方法JSPでタグライブラリを使用する場合は、「taglib」ディレクティブを使用して、利用したいタグライブラリを宣言します。prefix名、TLDファイルのURIには以下の値を使用します。(prefix(接頭辞)には任意の文字列を指定可能ですが、可読性の観点から規定されている接頭辞を用いるのが望ましい。)Coreprefix="c" uri="http://java.sun.com/jsp/jstl/core"i18nprefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"Functionprefix="fn" uri="http://java.sun.com/jsp/jstl/functions"XMLprefix="x" uri="http://java.sun.com/jsp/jstl/xml"Databaseprefix="sql" uri="http://java.sun.com/jsp/jstl/sql"Core タグライブラリCoreタグライブラリの主なタグ一覧です。この記事では、よく使われる一部のタグについて、使用方法を紹介します。c:set、c:remove、c:outc:set (変数を設定)c:remove (変数を削除)c:out (変数を出力) サンプルコード 「c:set」で変数messageに値を設定、「c:out」で出力  ⇒ message=  「c:remove」で変数messageを削除、「c:out」で出力  ⇒ message=  実行結果c:if、c:choosec:if (単一の条件分岐) 条件式がtrueの場合の処理 c:choose (複数の条件分岐) 条件に一致した場合の処理 条件に一致した場合の処理 全ての条件に一致しなかった場合の処理 ※c:chooseタグは、c:whenタグ、c:otherwiseタグを入れ子にして使用します。サンプルコード 「c:set」で変数numに値「9」を設定 「c:if」で10以下の値か判定  ⇒変数numは、10以下です 「c:set」で変数num2に値「4」を設定 「c:choose」で10以上または5~9の値か判定、条件に当てはまらない場合は4以下と判定  ⇒変数numは、10以上です  ⇒変数numは、5~9です  ⇒変数numは、4以下です 実行結果c:forEachc:forEach (繰り返し)回数指定による繰り返しコレクション・配列の要素を参照しながら繰り返しサンプルコード 「c:forEach」1~5まで増分2で繰り返し 「c:out」で現在のindex値を出力  index: 「c:set」で変数strにカンマ区切りの文字列を設定 「c:forEach」でカンマで区切られた文字列を1つずつ取得してループ 「c:out」で現在のindexと取得した文字列を出力 : ※「c:forEach」の「items」にカンマ区切りの文字列を指定する事で、カンマ部分で区切られた文字列の配列として処理されます実行結果I18NライブラリI18Nタグライブラリの主なタグ一覧です。この記事では、よく使われる一部のタグについて、使用方法を紹介します。fmt:formatNumberfmt:formatNumber (数値データを指定した書式でフォーマットする)サンプルコード フォーマット未指定(デフォルト) カンマ区切り(0埋めしない) 桁数指定(patternで指定、ゼロ埋めする) パーセント表示 カンマ区切りで表示させない 桁数指定(属性値で指定) 通貨記号を付与 実行結果fmt:formatDateformatDate(日付データを指定した書式でフォーマットする)サンプルコード フォーマット未指定(デフォルト) 表示タイプの指定 [type="DATE"]   [type="TIME"]   [type="BOTH"]   日付表示のスタイル指定 [dateStyle="FULL"]   [dateStyle="LONG"]   [dateStyle="MEDIUM"]   [dateStyle="SHORT"]   時刻表示のスタイル指定 [timeStyle="FULL"]   [timeStyle="LONG"]   [timeStyle="MEDIUM"]   [timeStyle="SHORT"]   パターン指定 [pattern="yyyy/MM/dd HH:mm:ss"]   [pattern="yyyy年MM月dd日(E) a KK時mm分ss秒"]   [pattern="y年M月d日 H時m分s秒"]   実行結果関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ/【Java】JSPのディレクティブ/【Java】JSPのEL式おまけプログラミングの学習やエンジニアへのキャリアチェンジをお考えの方へ『東京ITカレッジ』、『フォワードソフト株式会社』ぜひチェックしてみてください!

【Java】 命名規約

こんにちは、駆け出しプログラマーの若江です!ここでは初学者として学習を終えた私が、アウトプットの意味も込めて命名規約についてご紹介させていただきます。できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!関連記事リンク:変数とは / パッケージの紹介命名規約プログラミングでは変数名やメソッド名、クラス名など、たくさんのものに対して自由度高くプログラマー自身で名前を付けることができます。そのような中で根本的に「許可されていない名前やパターン」から、「一般的な名前の付け方、パターン」など、命名規約について幅広く紹介させていただきます。コーディング規約コードを書く際に、個人・開発チーム・大規模開発グループなどで取り決められるコーディングに関するルールです。設定されるルールには、変数名やメソッド名・クラス名などの名づけ方や、利用する機能の制限・禁止事項、プログラムの管理方法など様々なものが含まれます。コーディング規約はチーム間での連携が取りやすくなったり、他者の書いたコードが読みやすくなったり、不具合を未然に防いだりなどの点で有用となります。プログラマー間での「命名規約」「命名規則」「ネーミング規約」「ネーミング規則」とも呼ばれています。プログラムを開発する際には、プログラマー自身が様々なものに名前を付けます。パッケージ名や、パッケージの中にあるクラスの名前、クラスの中に書く定数名・メソッド名・変数名など、開発の規模が大きくなるほどその量は増えていきます。それらパッケージ・クラス・メソッドなどに適切な名前を付けておくことで、どのような役割をまとめたパッケージなのかや、どのような機能を果たすクラスなのか、どのような動作をするメソッドなのか、などといったことが理解しやすくなります。チーム開発など複数人で開発する際は、この命名規約をコーディング規約に含むことで、それぞれの名前をチーム全体の共通認識にすることができ、スムーズな開発を実現させることができます。例えば「手をたたく」ひとつでも、「拍手」もあれば「ハイタッチ」もありますし「注意をひく」場合や「盗み食いを阻止する」ことも考えられます。規約として「手をたたくとは命名せずに拍手と命名しましょう」と決めておけば、機能の誤認や混乱を防げますね。Java での「命名規約」名前の付け方についてルールを取り決めることを命名規約を言いますが、Java で既に取り決められたルールも命名規約と言います。ここでは Java においての命名規約の紹介をさせていただきます。取り決められたルールJava で名前を付ける際は以下のルールが存在します。・Unicode文字を含む英数字、記号(アンダーバー( _ )、ドルマーク($))を使うことができます。・名前の長さは1文字から無制限です。・数字も使えますが、先頭は使用不可です。・あらかじめ命名に使用NGのワードが設定されています。(予約語) ※アンダーバーは Java8 まで使用可能。( _ と英数字等の組み合わせは可能) ※ Unicode文字 とは世界の様々な文字に番号を振り当てたもので、日本語も対象となっています。  ただし命名には基本的に英字を使うことが一般的とされています。◆以下全て命名可能String a = "a"; // 1文字の英語 String あ = "a"; // 日本語 (非推奨) String _ = "a"; // アンダーバー (Java8 までは使用可能) String $ = "a"; // ドルマーク (非推奨) String a1 = "a"; // 英語 + 数字 → 「1a」にするとエラーになる String abcdefghijklmnopqrstuvwxyz = "a"; // 文字制限なし※文字の長さも必要以上の長さは推奨されていません。予約語一覧先ほどのルールで触れた命名NGワードのことを「予約語 (Keywords)」といいます。Java プログラミングで頻繁に使われるワードの一部は予約語に設定されています。以下予約語は命名に使用できません。◆予約語一覧51ワードが予約語に登録されています。(2020年8月現在)※アンダーバー( _ )は Java9 から予約語として新たに登録されました。また、予約語ではありませんが上記に加えて「null」「true」「false」も命名に使うことができません。(これら3つは「リテラル」という分類に属し、命名として判断されません)パッケージ・クラス・変数・定数・メソッドの命名規則Java ではパッケージ・クラス・変数・定数・メソッドなどそれぞれにも命名規則があります。基本的に先ほど「取り決められたルール」で紹介したルールに反しなければどのような名前も許容されますが、推奨される書き方がパッケージ・クラス・変数・定数・メソッドなどには存在します。それぞれの書き方は英字の小文字と大文字を区別して使い分けします。また命名する際に単語を2つ以上組み合わせて名前付けをする場合は以下2つの方法を使います。・スネークケース:単語と単語の間をアンダーバー( _ )で区切ります。 例) first_step, hop_step_jump など・キャメルケース:単語と先頭大文字の単語を組み合わせます。 例) firstStep, hopStepJump などパッケージの命名クラスなどをまとめるファイルのようなものです。パッケージの命名には小文字の英字を使います。命名したパッケージ内に保持しているクラスには、明示的にパッケージの在りかを記述します。どの階層にあるどのパッケージに含まれるクラスか?などが書かれます。記述のルールはインターネットでアクセスする際のドメイン(〇〇.XX.com など)の逆順です。また、クラスの先頭に記述しなくてはいけません。◆パッケージ記述例package com.xxx.OO;パッケージでは数字始まり、予約語、記号(ドット( . ))を使用することも可能です。その際は先頭にアンダーバーを付けます。package com._1._true._for;※アンダーバー以外に、ドルマーク( $ )でもエラーは出ませんが、アンダーバーを使うことがルールです。クラス・インターフェースの命名クラスやインターフェースには機能や動作などの指示が書かれています。クラス・インターフェースの命名は先頭大文字の英字で書きます。またクラス・インターフェースは機能や動作がまとめられた「もの」として位置づけられることから、クラス・インターフェースの命名には基本的に「名詞」が使われます。 例) Car, Book など単語を2つ以上組み合わせる際はキャメルケースを使います。 例) WorldWide, FastRunCar などまたインターフェースの命名には時折「xxable」といったように「形容詞」が使われることもあります。メソッドの命名クラスなどに書かれる、処理や動作のコードです。メソッドの命名は小文字の英字で書きます。処理や動作を実行する機能のため、メソッドの命名には基本的に「動詞」もしくは「動詞 + 名詞」が使われます。 例) walk, talk など2つ以上の単語を組み合わせる際はキャメルケースを使います。 例) watchEvrywhere, listenToMusic など<メソッド名 【set, get, is, has, can】>プログラマー全体で認知されている、メソッドの命名規約があるため紹介しておきます。プログラマー間で共通の認識がある名前のため、誰が見てもわかりやすい命名の手助けとなります。メソッド名 【set, get】アクセスが制限されたフィールドへアクセスするメソッドを「セッター」「ゲッター」と呼び、メソッド名に「setXxxx」もしくは「getXxxx」と命名します。 例) setCode, getCode などXxxx 部分は通常のメソッド命名ルール、2つ以上の単語組み合わせに従い大文字から始まります。メソッド名 【is】戻り値がboolean(真偽値)型のメソッドの中でも、状態の判断を行うメソッドは「isXxxx」と命名します。英文法 is と同様の使い方をメソッドで行います。 例) isEmpty, isReady などメソッド名 【has】戻り値がboolean(真偽値)型のメソッドの中でも、指定したデータを持っているかの判断を行うメソッドは「hasXxxx」と命名します。 例) hasNext, hasPrevious などメソッド名 【can】戻り値がboolean(真偽値)型のメソッドの中でも、指定した動作が可能かの判断を行うメソッドは「canXxxx」と命名します。 例) canSave, canRemove など変数の命名処理の流れ方などにより中身が変化する値です。変数の命名は基本的にメソッドと同じく小文字の英字で書きます。変数は値を持つ「もの」に位置づけられるので、基本的に「名詞」が使われます。 例) num, price, name など単語2組以上を組合す場合はキャメルケースを使います。 例) idNumber, firstName など定数の命名変数と対比して固定の値です。定数の命名は大文字の英字で書きます。定数も変数と同じく値を持つため、基本的に「名詞」が使われます。 例) RIGHT, LEFT など単語を2つ以上組合す場合はスネークケースを使います。 例) NEXT_MONTH, TWO_WEEKS など命名規約にはたくさんのルールがありますが、自身で命名を行う際に、比較的簡単に他者が見てもわかりやすい命名ができる手助けとなります。まとめコーディング規約があるおかげで、複数人数での開発もスムーズに連携をとることができます。多くの場面で命名を行うことになりますが命名規約のおかげで、見やすくわかりやすい命名が簡単にできるようになっています。チーム間での混乱を避けるためにもしっかりと覚えておきましょう。関連記事リンク変数とは / パッケージの紹介おまけプログラミングの学習やエンジニアへのキャリアチェンジをお考えの方へ独学からスピードアップして効率よく学習を進めたい方は、『東京ITカレッジ』を、ご自身のスキルを活かしたい方は、『フォワードソフト株式会社』をぜひチェックしてみてください!

【Java】コレクション(Map)

こんにちは、駆け出しプログラマーの若江です!ここでは初学者として学習を終えた私が、アウトプットの意味も込めてコレクションのMapについてご紹介させていただきます。できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです! 関連記事リンク:コレクションの概要 / 拡張for文の紹介 / コレクション (Set) の紹介コレクション( Map )複数のデータを持つことができるコレクションの中で、「キー」と「バリュー」で格納したデータを管理する特徴を持つのが Mapインターフェースです。ここではMapインターフェースの特徴や、Mapインターフェースを実装したクラスの紹介をさせていただきます。MapインターフェースMapインターフェースを実装したクラスを利用するためにまずはその特徴を確認しておきましょう。Mapインターフェースには以下の特徴があります。・「キー」と「バリュー」で格納データを管理する。 「キー」とはオリジナルの名前みたいなもので、同じ名前のキーを重複して設定することができません。 「バリュー」は和訳の通り値です。重複などの管理がされないため、キーと違って重複データを許可します。 キーとバリューの関係はペアで、1つのキーに対して1つのバリューが紐づけられます。 格納したい値(バリュー)に独自の名前(キー)を付けてあげるようなイメージです。 また、名前(キー)で呼んであげれば値(バリュー)が返事をするような動作をするイメージでもあります。・格納するデータは順序管理されない。 Mapインターフェース自体には「1番目のデータ」などの管理方法が設計されていません。 そのため、格納するデータはマップの配列内でバラバラに点在しているイメージです。 これら点在しているデータをオリジナルの名前(キー)で管理しています。Mapインターフェースを実装したクラスここではMapインターフェースを実装した代表的なクラスを3つ紹介します。Mapインターフェースを実装したクラスの基本的な書き方は以下の構文です。・Mapインターフェースを実装したクラスの基本的な書き方: Map< キーの型, バリューの型 > 変数名 = new Mapインターフェースを実装したクラス < キーの型, バリューの型 >();※「キーの型」と「バリューの型」はそれぞれ別の型を設定することができます。それぞれ格納データの管理方法に差がありますので違いを確認しましょう。HashMapクラスMapインターフェースの機能をそのまま実装した最も基本的なクラスです。「キー」「バリュー」でデータを管理するほか、null も許容します。実際のサンプルコードで書き方や結果も含めて確認しましょう。import java.util.Map; import java.util.HashMap;// Integer型のキーとString型のバリューを持つHashMapのインスタンスを生成 Map map = new HashMap(); // ()内の左側がキー、右側がバリュー map.put(1, "a"); // キー 1 に バリュー a を紐づけ map.put(1, "a"); // キー重複 map.put(2, "a"); // キーがオリジナルであれば、バリューは重複データでも許容される map.put(null, null); // null は許容される System.out.println(map); // 結果:1=a, 2=a, null=null を表示※結果の順序は格納するデータにより異なります。TreeMapクラスキーの名前を昇順に並べ替えるクラスです。基本的にHashMapと同じくキーバリュー管理を行いますが、TreeMapクラスは null を許容しません。サンプルコードで実際の書き方と結果を確認しましょう。import java.util.Map; import java.util.TreeMap;// Integer型のキーとString型のバリューを持つTreeMapのインスタンスを生成 Map map = new TreeMap(); map.put(1, "a"); // キー 1 とバリュー a を紐づけ map.put(1, "a"); // キー重複 map.put(6, "a"); // キー 6 とバリュー a を紐づけ map.put(3, "c"); // キー 3 とバリュー c を紐づけ map.put(2, "b"); // キー 2 とバリュー b を紐づけ map.put(null, null); // null は許容されないため例外を返す // null の例外を発生させない場合の結果 System.out.println(map); // 結果:1=a, 2=b, 3=c, 6=a を表示  ※順序管理ではないのでキー「3」の次が「4」でなくても正常に昇順で並び替えできます。HashMapと同じくバリューは重複が可能です。LinkedHashMapクラス先ほど紹介したHashMapクラスを継承して機能拡張したクラスがLinkedHashMapです。HashMapの機能に加えてデータを格納した順序で管理する特徴があります。こちらもサンプルコードで書き方と結果を確認しましょう。import java.util.Map; import java.util.LinkedHashMap;// Integer型のキーとString型のバリューを持つLinkedHashMapのインスタンスを生成 Map map = new LinkedHashMap(); map.put(1, "a"); // キー 1 とバリュー a を紐づけ map.put(1, "a"); // キー重複 map.put(6, "d"); // キー 6 とバリュー d を紐づけ map.put(3, "c"); // キー 3 とバリュー c を紐づけ map.put(2, "b"); // キー 2 とバリュー b を紐づけ map.put(null, null); // null も許容する System.out.println(map); // 結果:1=a, 6=d, 3=c, 2=b, null=null を表示入力された順番に結果が表示されました。キーの重複に関してMapではキーの重複が許容されないと紹介させていただきましたが、実際にはキーが重複した場合、キーに紐づくバリューが更新される設計となっています。Map map = new HashMap(); map.put(1, "a"); // 1 と a を紐づけ System.out.println(map); // 結果:1=a を表示 map.put(1, "b"); // 1 に対するバリューを b に更新 System.out.println(map); // 結果:1=b を表示 map.put(1, "c"); // 1 に対するバリューを c に更新 System.out.println(map); // 結果:1=c を表示 Mapで使う代表的なメソッド先ほどの3つのクラスで共通してよく使うメソッドをここで紹介します。メソッドは大きく分けて3つ、データの「追加」「削除」「検索」を行います。「追加」「削除」「検索」の動作を具体的にしたメソッドが以下8つとなります。※以下サンプルコードでは import を省略しています。・         put        :指定したキーと指定したバリューを紐づけてデータを格納します。         重複キーを指定した場合はバリューの紐づけを更新します。Map map = new HashMap(); map.put(1, "a"); // キー 1 とバリュー a を紐づけ System.out.println(map); // 結果:1=a を表示 map.put(1, "b"); // キー 1 が重複したためバリューを b に更新 System.out.println(map); // 結果:1=b を表示 map.put(2, "b"); // 新たなキー 2 とバリュー b を紐づけ System.out.println(map); // 結果:1=b, 2=b を表示・       clear       :マップ内からデータを全て削除します。Map map = new HashMap(); map.put(1, "a"); map.put(2, "b"); map.put(3, "c"); System.out.println(map); // マップ内に 1=a, 2=b, 3=c があることを確認 map.clear(); // マップ内のデータを全て削除 System.out.println(map); // 結果:空のマップを表示 ・ containsKey :マップが保持しているキーに対して、指定したキー名が存在した場合に true を返します。         キーが存在しない場合に false を返します。Map map = new HashMap(); map.put(1, "a"); map.put(2, "b"); map.put(3, "c"); System.out.println(map); // マップ内に 1=a, 2=b, 3=c があることを確認 System.out.println(map.containsKey(1)); // 結果:キー名 1 が存在するため true を返す System.out.println(map.containsKey(4)); // 結果:キー名 4 が存在しないため false を返す・containsValue:マップが保持しているバリューに対して、指定したバリュー名が存在した場合に true を返します。          バリューが存在しない場合に false を返します。Map map = new HashMap(); map.put(1, "a"); map.put(2, "b"); map.put(3, "c"); System.out.println(map); // マップ内に 1=a, 2=b, 3=c があることを確認 System.out.println(map.containsValue("a")); // バリュー a が存在するため true を返す System.out.println(map.containsValue("d")); // バリュー d が存在しないため false を返す・         get         :マップ内のキーに対して指定したキー名が存在する場合は紐づくバリューを返します。          指定したキー名が存在しない場合は null を返します。Map map = new HashMap(); map.put(1, "a"); map.put(2, "b"); map.put(3, "c"); System.out.println(map); // マップ内に 1=a, 2=b, 3=c があることを確認 System.out.println(map.get(1)); // 結果:キー 1 に紐づくバリュー a を表示 System.out.println(map.get(4)); // 結果:4 のキー名がないため null を表示 ・     isEmpty     :マップ内にデータが存在しない場合に true を返します。              データが1つでも存在する場合は false を返します。Map map = new HashMap(); System.out.println(map.isEmpty()); // データを格納する前のマップは空のため true を表示 map.put(1, "a"); // マップにデータを格納 System.out.println(map.isEmpty()); // 1=a のデータが存在するため false を表示  ※ null=null でもマップに存在すると判定されるため false を返します。・     remove      :マップ内のキーに対して指定したキー名が存在する場合は削除します。Map map = new HashMap(); map.put(1, "a"); map.put(2, "b"); map.put(3, "c"); System.out.println(map); // マップ内に 1=a, 2=b, 3=c があることを確認 map.remove(3); // キー名 3 が存在するため削除 System.out.println(map); // 結果:a=1, b=2 を表示 ・        size        :マップ内に存在するキーの個数を表示します。Map map = new HashMap(); map.put(1, "a"); map.put(2, "b"); map.put(3, "c"); map.put(null, null); System.out.println(map.size()); // 結果:4 を表示 (null もカウント対象)以上が代表的なメソッドとなります。これら8つは HashMap, TreeMap, LinkedHashMap 全てのクラスで使うことができます。余談上記サンプルコードの「インスタンス生成と putメソッド」を 1つにまとめて記述することもできます。余裕があれば以下のような書き方ができることも覚えておきましょう。・インスタン生成と putメソッドをまとめた書き方の例: Map< Integer, String> map = new HashMap(){{ put(1, "a") }};Map map = new HashMap(){ { put(1, "a"); put(2, "b"); put(3, "c"); } }; System.out.println(map); // 結果:1=a, 2=b, 3=c を表示※「{{  }}」この書き方はこの場限りのクラスを生成する「匿名クラス」と、 初期値の「イニシャライザブロック」を利用しています。 「匿名クラス」と「イニシャライザブロック」に関する紹介は別記事でさせていただきます。格納したデータの取り出し方Mapでのデータ操作方法を紹介したので、キーやバリューの取り出し方も併せて確認しておきましょう。今回は拡張for文とMapインターフェースのメソッド「keySet」と「values」を使って取り出してみます。・keySet:Setインターフェースの重複を許可しない特徴と連動させて、キーの値を取り出します。・values :Collectionインターフェースと連動させて、バリューの値を取り出します。Map map = new HashMap(); map.put(1, "a"); map.put(2, "b"); map.put(3, "c"); map.put(null, null); // keySet を使ってキーの値を取り出す for(Integer key : map.keySet()) { System.out.println(key); // 結果:1 2 3 を表示 } // values を使ってバリューの値を取り出す for(String value : map.values()) { System.out.println(value); // 結果:a b c を表示 }まとめ「キー」「バリュー」の特徴を持つMapインターフェースと HashMap, TreeMap, LinkedHashMapクラスを紹介しました。それぞれのクラスではデータの管理方法に違いがあります。各クラスの役割を状況に応じて使い分けましょう。関連記事リンクコレクションの概要 / 拡張for文の紹介 / コレクション (Set) の紹介おまけプログラミングの学習やエンジニアへのキャリアチェンジをお考えの方へ独学からスピードアップして効率よく学習を進めたい方は、『東京ITカレッジ』を、ご自身のスキルを活かしたい方は、『フォワードソフト株式会社』をぜひチェックしてみてください!

【Java】日時取得(従来API)-java.util.Date, java.util.Calendar

こんにちは、研修を終えたばかりの駆け出しエンジニアの伊藤です。東京ITカレッジのJava研修で学んだ内容を復習も兼ねて記事にしたいと思います。今回は、「java.util.Date」「java.util.Calendar」を使った日付取得方法について説明します。この記事では、最低限覚えておいてほしいクラスとして、日付と時刻を表すクラスと基本的な操作方法のみを紹介します。日付操作やフォーマットについては別記事「」でご紹介しますので、そちらも参考にしてください。また、Java8から採用された新API(DateAndTimeAPI)についての使い方や基本的な操作方法等は、日付時刻の取得(新API)にて説明しているので、ぜひご覧ください。Javaやプログラムについて勉強し始めた方の参考になれば幸いです!(eclipseを使用して計算を行っています)日付時刻(従来のAPI)DateクラスとCalendarクラスの違い(概要)両クラス共に日付を扱いますが、機能に違いがあります。 Dateクラス  :特定の日付や時間取得 Calendarクラス:日時の演算処理や細かい日時等の取得現在時刻を取得する方法Dateクラス(java.util.Date)Dateクラスでインスタンスを作成し、現在時刻を取得します。 ・現在時刻の取得  Date 変数名 = new Date();new演算子で、インスタンスを生成した時点の日時が反映されます。また反映された日時は、西暦1970年1月1日 午前0時0分0秒 (1970/01/01 00:00:00(GTM))を基点とした生成時の経過ミリ秒が保持されます。//現在時刻の取得サンプル(Date) import java.util.Date; public class DateSample { public static void main(String[] args) { //現在時刻の生成、取得 Date date = new Date(); System.out.println("---取得結果--------------------"); System.out.println("現在時刻:" + date); } }---取得結果-------------------- 現在時刻:Mon Jul 20 12:44:26 GMT+09:00 2020Dateインスタンスを生成し、現在時刻の取得ができました。現在時刻:Mon Jul 20 12:44:26 GMT+09:00 2020 曜日 月 日 時:分:秒 GMT+9:00 西暦で現在時刻を表しています。(GMTは、グリニッジ標準時のことです。日本は、標準時であるイギリスのグリニッジ天文台から約9時間の時差があるため、+9:00と表記されます)2020/07/20 12:44:26というような、スラッシュでの表示にする場合は、フォーマットの設定が必要になります。フォーマットについては、こちら「」に詳しく使い方を載せているので、併せてご覧ください。long型とDate型(経過ミリ秒からDate型変換)上記のDateクラスの説明であった通り、Dateインスタンスが保持するのは経過時間です。しかしプログラム内部では、1970/01/01 00:00:00 から何年何日…と経過時間が計算されているわけではありません。Dateインスタンスは経過時間をlong型の数値で持ち、それを人間が見やすい形式に変換しているのです。実際にプログラム内部ではどのように日時データを保持しているのか、サンプルで見てみましょう。//long型からDate型への変換サンプル import java.util.Date; public class DateSample { public static void main(String[] args) { //基準日時 1970/01/01 00:00:00 System.out.println("---取得結果--------------------"); //基準日時 から 1秒(1,000)後の時間表示 long long1 = 1000L; Date date1 = new Date(long1); System.out.println(" 1秒後:" + date1); //基準日時から 1日後の日時 long long2 = 86400000L; //1000L * 24 * 60 * 60; Date date2 = new Date(long2); System.out.println(" 1日後:" + date2); //基準日時から 1年後の日時 long long3 = 31536000000L; //1000L * 365 * 24 * 60 * 60; Date date3 = new Date(long3); System.out.println(" 1年後:" + date3); //基準日時から2020年1月1日の経過時間 long long4 = 1577836800000L; Date date4 = new Date(long4); System.out.println("指定日:" + date4); } }---取得結果-------------------- 1秒後:Thu Jan 01 09:00:01 GMT+09:00 1970 1日後:Fri Jan 02 09:00:00 GMT+09:00 1970 1年後:Fri Jan 01 09:00:00 GMT+09:00 1971 指定日:Wed Jan 01 09:00:00 GMT+09:00 2020     ※ 1秒 = 1,000ミリ秒long型の整数値をDateインスタンスを生成する際に引数として渡すと、その引数(コンストラクタ)を使ってインスタンスが生成されます。上記のサンプルで、long型から指定日時の取得ができることが分かります。Date型はこのようにlongの整数値として日付を保持します。(このlongは経過時間のミリ秒表現です)また、1970/01/01 よりも前の日時を表示するには、マイナスのlong型整数値を指定すれば取得することができます。経過ミリ秒の取得Date型からlong型変換今度は逆にDateインスタンスからlong型の経過時間のミリ秒数を取得してみます。//経過ミリ秒をDate型に変換(経過ミリ秒から日時を取得) import java.util.Date; public class UnixTimeSample { public static void main(String[] args) { //Date型から経過ミリ秒の取得 System.out.println("---取得結果--------------------"); Date date = new Date(); long unixTime = date.getTime(); System.out.println("経過ミリ秒:" + unixTime); //取得したミリ秒をDate型に戻す Date returnDate = new Date(unixTime); System.out.println("取得日時 :" + returnDate); } }---取得結果-------------------- 経過ミリ秒:1595908376400 取得日時 :Tue Jul 28 12:52:56 GMT+09:00 2020変数名.getTime(); で変数に格納された値を取得することができます。この時の経過ミリ秒は、何度も出てきている通り基準時である1970/01/01 00:00:00からの経過時間です。日時を数値化することによって、簡単に計算することができるようになります。このように日時をlong型で持つことによる利点は、計算や比較などが容易にできる、ということです。また、この経過秒数をUNIX時間(または、UNIX時刻)と言います。currentTimeMillisメソッドcurrentTimeMillisメソッドを使っても経過ミリ秒を取得することができます。//経過ミリ秒をcurrentTimeMillisメソッドで取得 import java.util.Date; public class UnixTimeSample { public static void main(String[] args) { //Date型から経過ミリ秒の取得 System.out.println("---取得結果--------------------"); Date date = new Date(); long unixTime = date.getTime(); System.out.println("経過ミリ秒(long) :" + unixTime); //取得したミリ秒をDate型に戻す Date returnDate = new Date(unixTime); System.out.println("取得日時(long)  :" + returnDate); //System.currentTimeMillisメソッドを使った、経過ミリ秒の取得 long currentTime = System.currentTimeMillis(); System.out.println("経過ミリ秒(currentTime):" + currentTime); //System.currentTimeMillisメソッドを使い取得したミリ秒をDate型に戻す Date currentTimeDate = new Date(currentTime); System.out.println("取得日時(currentTime) :" + currentTimeDate); } }---取得結果-------------------- 経過ミリ秒(long) :1596078810239 取得日時(long)  :Thu Jul 30 12:13:30 GMT+09:00 2020 経過ミリ秒(currentTime):1596078810273 取得日時(currentTime) :Thu Jul 30 12:13:30 GMT+09:00 2020今回のサンプルプログラムは、Date型からlong型変換の「経過ミリ秒をDate型に変換」プログラムと見比べられるように書かれています。プログラムソースは、上から順に処理を行っていきます。その為、取得結果でも経過ミリ秒に差が出ています。しかし、Date型は秒までの表示なので取得日時結果には違いは見られませんね。より正確な時間が欲しい場合は、ナノ秒を使うと良いでしょう。新APIを使用すると、ナノ秒までを簡単に取得することができます。Calendarクラス(java.util.Calendar)getメソッドDateクラスでは、日付から時差まで全てが取得できました。しかし、西暦だけ欲しい、日付だけ使いたい、という細かい日時の取得は難しいです。そこで、細かい日時の取得にはCalendarクラスを用います。Calendarクラスのインスタンスを生成した後、日時を取得します。  ・現在時刻を保持したインスタンスの生成   Calendar 変数名 = Calendar.getInstance();  ・インスタンスで保持した現在時刻から、欲しい日時を指定し取得   int 変数名2 = 変数名.get(Calendar.日時名);Calendarクラスでは、getInstanceメソッドを使用して、生成時点の日付と時刻を保持したインスタンスを生成しています。getメソッドを使用して、引数に取得したい日時の種類を指定します。getInstanceで生成した現在時刻から指定した日時を取得しています。//現在日時の取得サンプル(Calendar.get) import java.util.Calendar; public class CalendarTest { public static void main(String[] args) { //Calendarクラスのオブジェクトを生成 Calendar calendar =Calendar.getInstance(); //欲しい日時の取得 System.out.println("---取得結果--------------------"); System.out.println("西暦 :" + calendar.get(Calendar.YEAR)); System.out.println("月  :" + calendar.get(Calendar.MONTH)); System.out.println("現在月:" + calendar.get(Calendar.MONTH)+1); System.out.println("日にち:" + calendar.get(Calendar.DATE)); System.out.println("時刻 :" + calendar.get(Calendar.HOUR)); System.out.println("分  :" + calendar.get(Calendar.MINUTE)); System.out.println("何日目:" + calendar.get(Calendar.DAY_OF_YEAR)); //繋げて表示する場合 System.out.println(); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH)+1; int date = calendar.get(Calendar.DATE); int hour = calendar.get(Calendar.HOUR); int minute = calendar.get(Calendar.MINUTE); int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR); System.out.println("今日は西暦" + year + "年" + month + "月" + date + "日" + hour + "時" + minute + "分です。"); System.out.println("そして、" + year + "年が始まってから" + dayOfYear + "日目になります。"); } }---取得結果-------------------- 西暦 :2020 月  :6 現在月:7 日にち:20 時刻 :2 分  :58 何日目:202 今日は西暦2020年7月20日2時58分です。 そして、2020年が始まってから202日目になります。Calendarクラスでは、月の取得の際に注意することがあります。例えば、現在月が7月とします。 get(Calendar.MONTH) を使用し現在月を取得しようとすると、取得結果は6月になってしまいます。(上記テストプログラム参照)それは、Calendarインスタンスを生成した際、保持する月は 0から11まで、となっているからです。1月が 0 、2月が 1 、3月が 2 としてインスタンスに保持されているということです。そのため、Calendarクラスで現在月を取得するには、get(Calendar.MONTH)に +1 をすることが必要となるので、気を付けてください。setメソッドgetメソッドを使用すれば、現在日時の取得ができました。今度は、指定した年月日の取得をしてみましょう。//指定日時の取得サンプル(Calendar.set) import java.util.Calendar; public class CalendarSetSample { public static void main(String[] args) { //Calendarクラスのオブジェクトを生成 Calendar calendar = Calendar.getInstance(); System.out.println("---取得結果--------------------"); //現在日時の取得 System.out.println("現在日時:" + calendar.getTime()); //西暦変換(2020 → 2010) calendar.set(Calendar.YEAR, 2010); System.out.println("2010年 :" + calendar.getTime()); //月変換(7月 → 12月) calendar.set(Calendar.MONTH, 12 - 1); System.out.println("12月 :" + calendar.getTime()); //日付変換(29日 → 1日) calendar.set(Calendar.DATE, 01); System.out.println("1日 :" + calendar.getTime()); //午前午後変換(AM → PM) calendar.set(Calendar.AM_PM, 1); System.out.println("午後 :" + calendar.getTime()); //時間変換(22時 → 14時) calendar.set(Calendar.HOUR, 2); System.out.println("14時 :" + calendar.getTime()); //曜日変換(火曜 → 日曜) calendar.set(Calendar.DAY_OF_WEEK, 1); System.out.println("日曜 :" + calendar.getTime()); System.out.println("---指定日時をまとめて取得------"); //年月日を指定 calendar.set(2000, 01, 15); System.out.println("年月日指定 :" + calendar.getTime()); //年月日時分秒で指定 calendar.set(2000, 01, 15, 18, 22, 30); System.out.println("年月日時分秒指定:" + calendar.getTime()); } }---取得結果-------------------- 現在日時:Fri Jul 31 16:52:54 GMT+09:00 2020 2010年 :Sat Jul 31 16:52:54 GMT+09:00 2010 12月 :Fri Dec 31 16:52:54 GMT+09:00 2010 1日 :Wed Dec 01 16:52:54 GMT+09:00 2010 午後 :Wed Dec 01 16:52:54 GMT+09:00 2010 14時 :Wed Dec 01 14:52:54 GMT+09:00 2010 日曜 :Sun Nov 28 14:52:54 GMT+09:00 2010 ---指定日時をまとめて取得------ 年月日指定 :Tue Feb 15 14:52:54 GMT+09:00 2000 年月日時分秒指定:Tue Feb 15 18:22:30 GMT+09:00 2000サンプルでは、変数名.getTime(); で1970/01/01 00:00:00からの経過時間ミリ秒を取得し、Date型に変換し表示しています。取得結果では、指定した要素以外は前の値を保ったままになります。曜日取得に関しては、週の始まりが日曜日となっています。上記サンプル結果では 12月1日(水)の週の日曜日が 11月28日(日)なので、日付と月も変わっています。注意するフィールドCalendarクラスでは、日時を操作するための様々なフィールドが用意されています。全フィールドの詳細についてはJavaDocを参照してください。ここでは、値を設定する際に注意が必要なフィールドについて説明します。MONTH MONTHフィールドの値は 0から11 です。  0    1月 January(Jan)    1    2月 February(Feb)    2    3月 March(Mar)    3    4月 April(Apr)    4    5月 May(May)    5    6月 June(Jun)    6    7月 July(Jul)    7    8月 August(Aug)    8    9月 September(Sep)    9   10月 October(Oct)    10    11月 November(Nov)    11    12月 December(Dec)  MONTHを取得、指定する場合は欲しい指定月(setメソッド)からマイナス1 することを忘れないようにしましょう。 (getメソッドの場合はプラス1 になるので、間違えないようしてください)AM_PM HOUR が正午より前であるかあとであるかを示します AM_PMフィールドの値は 0、1 です。 0  AM   1  PMHOUR 午前または午後の何時かを示します HOURフィールドは 12時間制(0から11)です。 真夜中、正午どちらもHOURフィールドでは、12 ではなく 0 で表されるので注意してください。 11 以上の 12時 13時としてもエラーは出ず、結果は出力されます。 しかし、日付や曜日が指定したところから変わってしまうこともあるので、0 から 11 以内で指定した方が欲しい値を取得できます。    午前、午後の時間は持ちませんので、AM_PMフィールドと共に使うのが良いです。 (HOUR_OF_DAY は 24時間制です)DAY_OF_WEEK DAY_OF_WEEKフィールドの値は 1から7 です。 1  日曜日 Sunday(Sun)   2  月曜日 Monday(Mon)   3  火曜日 Tuesday(Tue)   4  水曜日 Wednesday(Wed)   5  木曜日 Thursday(Thu)   6  金曜日 Friday(Fri)   7  土曜日 Saturday(Sat)setメソッドを使用すると、年、月、日などの単位ごとや、年月日をまとめて取得することができます。また、MONTH、AM_PM、DAY_OF_WEEK、各フィールドにはそれぞれに値が定数として用意されています。(AM_PMフィールドであれば、Calendar.PM と書くことができ、その際の PM が定数で値は 1 になります)使用する場面に応じて、定数で使用した方が良い場合と、数値としてそのまま値を使用し方が良い場合があるので、使い分けができると良いでしょう。曜日は値が 1から始まるので、上記フィールドと違っているので気を付けてください。注意するフィールド値は、getメソッドも同様です。日時の取得方法はわかったでしょうか?新APIの日時取得方法と比べてみると理解度が上がると思いますので、ぜひ読んでみてください。より詳しくプログラミングの学習をしたい、エンジニアへのキャリアチェンジに興味がある方は『東京ITカレッジ』、『フォワードソフト株式会社』ぜひチェックしてみてください。

【Java】Java8 以降に追加された文字列結合(StringクラスjoinメソッドとStringjonerクラス)

こんちには。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Java8 以降に追加された文字列結合Java8 以降の文字列結合の方法として①StringJoiner を使用する方法と②String の join メソッドを使用する方法 が追加されました。今回はそちらを紹介します。joinメソッド以外のStringクラスメソッドについては以下の記事で紹介しています。joinメソッドやStringJoinerクラスの登場により、区切り文字や接頭辞、接尾辞を使った文字列の構築が簡単に実装できるようになりました。CSVフォーマットやJSONフォーマット、URLのパラメータを生成する場面などでも活用できる機能になっており、プログラムの可読性、生産性の向上にもつながります。【java.langパッケージ/ Stringクラス】joinメソッドString String.join(区切り文字, 連結する文字列, ... ,連結する文字列)区切り文字と文字列を連結させて一つの文字列を構築するのがjoinメソッドです。第一引数には区切り文字を指定し、第二引数以降には文字列を指定します。では例をみてみましょう。今回は、第一引数に:(コロン)を指定し、第二引数以降には山手線の駅名の文字列を入れました。public class Test { public static void main(String[ ] args) { String s = String.join(":", "東京","品川","新宿"); System.out.println(s); } }出力すると東京:品川:新宿となります。またはjoinメソッドは区切り文字とString型の配列を連結 させることもできます。String String.join(区切り文字, 配列)第一引数には区切り文字を指定し、第二引数にはString型の 配列を指定します。こちらも例をみてみましょう。public class Test { public static void main(String[ ] args) { String[] str= new String[] {"東京","品川","新宿","池袋","神田"}; String s = String.join(":", str); System.out.println(s); } }出力すると東京:品川:新宿:池袋:神田となります。【java.utilパッケージ】StringJoinerクラスStringJoinerクラスは、区切り文字で区切られ、指定された接頭語から始まり、指定された接尾語で終わる文字列を構築するために使用されます。今回は基本的な操作 を紹介します。①StringJoiner値をStringオブジェクトに変更する操作(toStringメソッド)②初期化と要素の追加する操作(addメソッド)③StringJoiner値同士を結合する操作(mergeメソッド)StringJoinerクラスはjava.utilパッケージの中に存在しているため、使う時はjava.util.StringJoinerをインポートする必要があります。▼StringJoiner値をStringオブジェクトに変更する操作(toStringメソッド)String toString()toStringメソッドは、StringJoiner値をStrig値に変換するメソッドであると覚えておいてください。addメソッドやmergeメソッドの説明例で使用するため今回紹介しています。このメソッドが使用されたStringJoiner値はStringへ変換され、Stringオブジェクトとして使用できるようになります。このメソッドの使用例は この後のメソッドの説明例を見てください。▼初期化と要素の追加する操作(addメソッド)初期化についてStringJoiner sj= new StringJoiner(句切り文字);StringJoiner sj= new StringJoiner(句切り文字, 接頭語, 接尾語);初期化の際に引数を上記のように指定します。初期化しただけの状態で実行するとimport java.util.StringJoiner; public class Test { public static void main(String[ ] args) { //初期化 StringJoiner sj= new StringJoiner(":"); StringJoiner tj= new StringJoiner(":", "[", "]"); String s = sj.toString(); String t = tj.toString(); System.out.println(s); System.out.println(t); } }区切り文字のみが引数の場合は、何も表示されていないですが、これで初期化が出来ています。要素の追加によって、接頭接尾語が無く、「:」(コロン)で句切られた文字列が構築されます。 接頭語、接尾語が引数に含まれる場合は、接頭語、接尾語のみが出力されました。要素の追加によって、接頭接尾語で囲まれ「:」(コロン)で句切られた文字列が構築されます。[]要素の追加についてStringJoiner add(文字列)addメソッドは引数に指定された文字列を、StringJoiner値の要素として順に追加できます。例をみてみましょう。今回は、StringJoinerの初期化で 第一引数に:(コロン)を指定し、接頭語/接尾語に[](大カッコ)を指定しています。import java.util.StringJoiner; public class Test { public static void main(String[ ] args) { StringJoiner sj= new StringJoiner(":", "[", "]"); sj.add("東京").add("品川").add("新宿").add("池袋"); //toStringメソッド String s = sj.toString(); System.out.println(s); } }出力すると[東京:品川:新宿:池袋]となります。以下の書き方は同じ意味です。sj.add("東京").add("品川").add("新宿").add("池袋");sj.add("東京"); sj.add("品川"); sj.add("新宿"); sj.add("池袋");▼StringJoiner値同士を結合する操作(mergeメソッド)StrindJoiner merge(StringJoiner other)mergeメソッドは、StringJoiner値同士を連結させるメソッドです。引数には、別のStringJoiner値を指定します。引数に指定されたStringJoiner値は、接頭語と接尾語を除いて連結されます。注意するのは、指定されたStringJoinerが空の場合、このメソッドは効果を発揮しません。addメソッドで要素を追加した後に、mergeメソッドを使用することになります。addメソッドの例に加え、StringJoiner値(変数tj)を追加し、連結をしています。import java.util.StringJoiner; public class Test { public static void main(String[ ] args) { StringJoiner sj= new StringJoiner(":", "[", "]"); sj.add("東京").add("品川").add("新宿").add("池袋"); //追加 StringJoiner tj= new StringJoiner("、",""); tj.add("神田").add("上野").add("原宿"); String s = sj.toString(); String t = tj.toString(); //mergeメソッド sj.merge(tj); String u = sj.toString(); System.out.println("sjの中身"+s); System.out.println("tjの中身"+t); System.out.println("連結された中身"+u); } }出力するとsjの中身[東京:品川:新宿:池袋] tjの中身 連結された中身[東京:品川:新宿:池袋:神田、上野、原宿]となります。StringJoiner値が連結されたのがわかると思います。mergeメソッドは、接頭接尾語を除いた文字列を連結するので区切り文字は変わりません。連結の中身の区切り文字は「:」(コロン)「、」(読点)が混在しています。どちらかに揃えたい場合は、StringクラスのreplaceAllメソッドで置換するのが便利です。リンク:【Java】Stringについて理解する/置換あとがき私が働いているフォワードソフト株式会社では成長意欲旺盛なエンジニアが多く在籍しております。また東京ITカレッジでは他にも多様なプログラミング情報を掲載しています。まずは一度サイトを覗いてみてください!お待ちしています!

【Java】 文字列・データ型間の変換方法

こんにちは、駆け出しプログラマーの若江です!ここでは初学者として学習を終えた私が、アウトプットの意味も込めて文字列とデータ型間の変換についてご紹介させていただきます。できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!関連記事リンク:Stringについて紹介 / 拡張for文の紹介文字列とデータ型間の変換方法String型(文字列)からデータ型への変換、またはデータ型から String型への変換はメソッドの引数やデータ比較、データベースへの登録などにおいて、お互いの整合性を合わせる場合などに必要となります。ここでは「String型」↔「データ型」の変換方法を紹介させていただきます。String型とデータ型の変換 概要様々なデータ型が Java には存在しますが、多くの変換方法には大きく似ている部分があります。覚えやすくするために、ここではいくつかの型をひとつの分類でまとめて5種類に分けて紹介します。・分類①:文字列と整数値の変換 (int, short, long)・分類②:文字列と小数点を持つ値の変換 (float, double)・分類③:文字列と真偽値 true / false の変換 (boolean)・分類④:文字列と文字単体の変換 (char)・分類⑤:文字列と Byte の変換 (byte)変換方法紹介の前に、「プリミティブ型をラップしたクラス型」について簡単に説明しておきます。プリミティブ型とは、int, short, long, float, double, boolean や char 型などの総称を指します。ラップしたクラス型とは、上記のような「型」に加工処理機能(メソッドなど)を持たせるためにクラス化させた型を指します。クラス化のルールに従って型の先頭文字は大文字で表記されます。また本来の名前で表記されます(int = Integer など)。分類①:文字列と整数値(int ,short, long)の変換文字列と整数値の変換はお互いが整数値であることを条件とします。整数値以外、もしくはその型が保持できる値の上限を超えている場合は、実行時に NumberFormatException という例外を投げます。例外が投げられると、それ以降の処理は中止されるため気を付けましょう。変換で使うメソッド文字列と整数値の変換には3種類のメソッドが用意されています。・  valueOf :文字列からデータ型、データ型から文字列の両方で使うことができます。  型 変数名 = クラスの型.valueOf(値);・ parse○○:文字列からデータ型へ変換する際に使います。○○にはデータ型の名前が入ります。  プリミティブ型 変数 = クラスの型.parse○○(値);・ toString  :データ型から文字列へ変換する際に使います。  String 変数名 = クラスの型.toString(値);上記書き方を参考にサンプルコードを確認しましょう。◆ valueOf のサンプルコード【String ➡ 整数値】// 文字列 100 を String の変数に代入 String str = "100"; // 文字列 100 を整数値の 100 に変換 Integer i = Integer.valueOf(str); // Integer は int とも記述可能です。(オートボクシング機能) Short s = Short.valueOf(str); // Short は short とも記述可能です。(オートボクシング機能) Long l = Long.valueOf(str); // Long は long とも記述可能です。(オートボクシング機能) // 整数値 100 を表示 System.out.println("String から valueOf で Integre へ変換: " + i); System.out.println("String から valueOf で Short へ変換: " + s); System.out.println("String から valueOf で Long へ変換: " + l); 【整数値 ➡ String】// データ型の変数に整数値 100 を代入 int i = 100; short s = 100; long l = 100; // 整数値 100 を文字列の 100 へ変換 String str = String.valueOf(i); String str1 = String.valueOf(s); String str2 = String.valueOf(l); // 文字列 100 を表示 System.out.println("int から valueOf で String へ変換 :" + str); System.out.println("short から valueOf で String へ変換:" + str1); System.out.println("long から valueOf で String へ変換:" + str2); ◆ parse○○ のサンプルコード// 文字列の 100 を String に代入 String str = "100"; // 文字列の 100 を整数の 100 に変換 int i = Integer.parseInt(str); short s = Short.parseShort(str); long l = Long.parseLong(str); // 整数値に変換した 100 を表示 System.out.println("String から perseInt で int へ変換: " + i); System.out.println("String から perseShort で short へ変換: " + s); System.out.println("String から perseLong で long へ変換: " + l);◆ toString のサンプルコード// 整数値 100 をデータ型の変数に代入 int i = 100; short s = 100; long l = 100; // 整数値 100 を文字列へ変換 String str = Integer.toString(i); String str1 = Short.toString(s); String str2 = Long.toString(l); // 文字列 100 を表示 System.out.println("int から toString で String へ変換 :" + str); System.out.println("short から toString で toString へ変換:" + str1); System.out.println("long から toString で toString へ変換:" + str2); 分類②:文字列と小数点を持つ値(float, double)の変換小数点を持つ値の他、整数値も渡すことができます。(整数値を使用しても結果は小数点を含んで返ってきます)値に文字を渡した場合は NumberFormatException という例外が投げらるので注意しましょう。使うメソッドは分類①と同じ3種類のメソッドです。分類①とは小数点を扱う点で違うためサンプルコードを確認しておきましょう。※valueOf のサンプルコードは省略します。◆ parse○○ のサンプルコード// 文字列の変数に 0.1 を代入 String str = "0.1"; // 文字列からデータ型へ変換 float f = Float.parseFloat(str); double d = Double.parseDouble(str); // 0.10 を表示 System.out.println("String から parseFloat で数値へ変換" + f); System.out.println("String から parseDouble で数値へ変換" + d);◆ toString のサンプルコード// データ型に合わせた小数点の数 0.1 を変数へ代入 float f = 0.1f; double d = 0.1; // 0.1 を文字列へ変換 String str = Float.toString(f); String str2 = Double.toString(d); // 文字列 0.1 を表示 System.out.println("float から toString で String へ変換" + str); System.out.println("double から toString で String へ変換" + str2);※ 0.1 は double型のため、サイズが大きすぎてfloat では扱いきれませんので、明示的に 0.1f として float に合わせています。ちなみに float, double から String へ変換する際に、小数点が深いと指数表記で結果を返すことがあります。指数表記とは「1.0E-4」などのような結果が表示されます。上記から期待していた小数点の表記へ正したい場合は、BigDecimal というクラスで解決が望めます。以下参考として確認しておきましょう。double d = 0.0001; // 指数表記で表示される String str = Double.toString(d); System.out.println("指数表記で表示される: " + str); // valueOf に 0.0001 を渡す。BigDecimal を使うと小数点で表示される String str2 = BigDecimal.valueOf(d).toString(); System.out.println("省略されずに表示される: " + str2); 分類③:文字列と真偽値(boolean)の変換文字列から boolean への変換では、文字列が true (大文字、小文字の区別なし) の場合に true の変換を返し、それ以外は false の変換を返します。boolean から文字列への変換は、そのまま文字列へ変換処理されます。使うメソッドは分類①②と同じです。数字の型とは少し違た動きをしますので、サンプルコードで確認しておきましょう。※ valueOf のサンプルコードは省略します。◆ parseBoolean のサンプルコードString str1 = "true"; String str2 = "test"; boolean b1 = Boolean.parseBoolean(str1); // true を true と判定 boolean b2 = Boolean.parseBoolean(str2); // test を false と判定 System.out.println("true を perseBoolean で boolean へ変換: " + b1); // true を表示 System.out.println("false を perseBoolean で boolean へ変換: " + b2); // false を表示 ◆ toString のサンプルコードboolean b1 = true; boolean b2 = false; String str1 = Boolean.toString(b1); // true を文字列へ変換 String str2 = Boolean.toString(b2); // false を文字列へ変換 System.out.println("true を toString で String へ変換: " + str1); // 文字列 true を表示 System.out.println("false を toString で String へ変換: " + str2); // 文字列 false を表示分類④:文字列と文字単体(char)の変換char型を配列にしたものが String型となります。そのため String を1文字単位で扱ったり、char を配列にするといった処理を行います。char のメソッドは分類①②③と少し異なり、ここでは toString の他に以下メソッドを紹介します。・toCharArray :Stringの文字列を1文字ごとの配列に切り分けます。サンプルコードを確認しましょう。◆ toString のサンプルコードchar c = 'a'; String str = Character.toString(c); // 文字単体を文字列へ変換 System.out.println("char から toString で String へ変換: " + str); // a を表示◆文字単体の配列から文字列へ変換// a, r, r, a, y を持った文字の配列 char[] c = new char[]{'a', 'r', 'r', 'a', 'y'}; // char の文字配列を引数にして String を新しく生成 String str = new String(c); System.out.println("char を配列にして String へ変換: " + str); // 文字列の array を表示◆文字列から文字の配列へ変換String str = "array"; // 文字列を char の配列へ変換 char[] c = str.toCharArray(); System.out.println(c); // 文字の配列として array を表示ちなみに上記 c は文字の配列となっているため、for文で取り出すことも可能です。上記サンプルコードに以下を足すことで 「a」「r」「r」「a」「y」を取り出せます。for(char c2 : c) { System.out.println(c2); } 分類⑤:文字列と Byte (byte)の変換文字列の文字を10進数の byte へ変換、または byte から文字列へ変換ができます。文字列から byte への変換には getByteメソッドを使います。◆ getByte のサンプルコードString str = "Word"; byte[] b = str.getBytes(); // W o r d をそれぞれ byte に変換して byte の配列へ代入 // 「Arrays.toString」で配列の中身を文字列として表示 System.out.println(Arrays.toString(b)); // 結果:87, 111, 114, 100 を表示 // 配列のため拡張for文で byte を1つずつ取り出しも可能 for(byte b2 : b) { System.out.println(b2); }◆ byte を文字列へ変換// 先ほど String から byte へ変換した結果を利用 byte[] b = {87, 111, 114, 100}; // byte の配列を使って String を生成 String str = new String(b); System.out.println(str); // 結果:Word を表示まとめ文字列とデータ型の変換には valueOf, parse, toString を基本として、toCharArray, getByte といったメソッドを使うことができます。それぞれの機能を理解して必要になったときに使えるようにしておきましょう。関連記事リンクStringについて紹介 / 拡張for文の紹介おまけプログラミングの学習やエンジニアへのキャリアチェンジをお考えの方へ独学からスピードアップして効率よく学習を進めたい方は、『東京ITカレッジ』を、ご自身のスキルを活かしたい方は、『フォワードソフト株式会社』をぜひチェックしてみてください!