Lesson 6

標準API

Lesson 6 Chapter 1
Java SE

前レッスンでは、オブジェクト指向を中心に扱ってきました。Javaプログラムを整理することでどのようにオブジェクト指向を実現できるかを学んできました。本レッスンでは、Javaを開発、実行する際に私たちが何を使っているのかに目を向けていきます。標準APIと呼ばれるJavaが提供するパッケージ群を主に扱いつつ、開発環境や、実行環境に触れていきます。Javaの全体像を掴むようなレッスンです。

Javaプラットフォームの全体像

まずは、Javaの開発・実行を行う環境を見ていきましょう。Javaにおいて、Java言語を使用してアプリケーションを開発、実行するための環境のことを総じて「プラットフォーム」といいます。Javaプラットフォームは、環境に依存しないことが特徴的です。Windows、Linux、macOSなど、異なるOS上で開発し、実行することが出来ます。この非依存性はアプリケーションのポータビリティ、クロスプラットフォーム性、などと呼ばれます。

Write once, run anywhere

"Write once, run anywhere"は1995年にサン・マイクロシステムズからJavaがリリースされた際のスローガンでした。「一度書けば、どこでも動く」という意味です。このクロスプラットフォーム性が売りであったことが伺えます。

Javaには3つのプラットフォームがあります。

  • Java SE (Java Standard Edition):デスクトップアプリケーションやサーバーサイドアプリケーションを開発するための環境を提供します。

  • Java EE (Java Enterprise Edition):大規模な企業アプリケーションを開発するための環境を提供します。

  • Java ME (Java Micro Edition):携帯電話やスマートフォンなどの小型デバイス向けアプリケーションを開発するための環境を提供します。

本チャプターではJava SEについて詳しく扱っていきます。Java EE、Java MEについてはい後述します。その前に、JDK、JRE、JVMについて説明します。これらは、どれもJavaプラットフォームに含まれるものです。レッスン1でも扱いましたが、復習していただければと思います。

JDK

JDK (Java Development Kit) は、Javaで開発されたアプリケーションを作成するための開発環境です。 JDKには、Javaコンパイラ、Javaデバッガ、その他の開発ツールが含まれており、Javaアプリケーションを作成するために必要な環境を提供します。

JRE

JRE (Java Runtime Environment)は、Javaアプリケーションを実行するために必要な実行環境を提供するものです。JREは、Javaアプリケーションを実行するためだけであり、開発環境は提供しません。

JVM

JVM (Java Virtual Machine) は、Javaアプリケーションを実行するための仮想マシンです。JVMは、Javaで書かれたアプリケーションを機械語に変換し、それをコンピューターが理解できる形式で実行します。Javaアプリケーションがオペレーティングシステムに依存しない形で実行されることを可能にします。

JDK、JRE、JVMの関係性

3つの概念を並べて説明しましたが、JDK、JRE、JVMは包含関係にあります。

Java-6_1

JVMはJREに含まれており、JREはJDKに含まれています。JDKは最も包括的で、Javaアプリケーションの開発から実行まですべてをカバーしています。JREはJavaアプリケーションの実行に必要な最低限のコンポーネントが含まれており、JVMやJavaクラスライブラリ、ランタイム環境などが含まれます。JVMはJavaアプリケーションの実行に必要な仮想マシンであり、JREに含まれています。

Java SEとは何か

JDK、JRE、JVMについて説明したので、Java SEについて説明していきます。Java SE (Java Standard Edition)は、Javaアプリケーションの開発における基本的な機能が含まれるクラスライブラリです。そして、Java SEをクラスライブラリとしてJREの中にもっているプラットフォームのことをJava SEプラットフォームと呼びます。つまり、Java SEは、標準クラスライブラリと、それを含んだプラットフォーム両方を指す言葉です。この呼び方は、Java EE、Java MEでも同様です。

Java SEは、Oracle Corporationによって開発・維持されており、定期的にセキュリティアップデートが提供され、脆弱性の修正や機能改善が行われています。また、JDK(Java Development Kit) も提供されており、Javaアプリケーション開発に必要な開発ツール、ライブラリ、ドキュメントなどを提供します。

Java SEは標準的なJavaプラットフォームであることが分かりました。では、次のレッスンに進んでJava EE、Java MEについても理解を深めていきましょう。

Lesson 6 Chapter 2
Java EE(Jakarta EE)

Java EE(Java Enterprise Edition)は、企業向けアプリケーション開発に使用されるJavaのプラットフォームです。Java SEの拡張版と考えることができます。Java SEと同様に、Java EEアプリケーションは、Java仮想マシン(JVM)上で実行されます。Java EEは、多数のAPIや仕様を提供しており、これらを使用してエンタープライズアプリケーションを開発することができます。

Java EEは、以下のようなコンポーネントが含まれています。

  • Enterprise JavaBeans(EJB) - サーバーサイドのコンポーネントを開発するためのAPIです。EJBは、データベースのアクセス、トランザクション管理、セキュリティ、分散アプリケーションなど、多数の機能を提供します。

  • Java Servlet - Webアプリケーションのコンポーネントを開発するためのAPIです。Servletは、HTTPリクエストとレスポンスの処理、セッション管理、Cookieの処理などを行います。

  • JavaServer Pages(JSP) - サーバーサイドで動的なWebページを生成するためのテクノロジーです。JSPは、HTMLコードとJavaコードを組み合わせることができます。

  • Java Message Service(JMS) - 分散アプリケーション間でメッセージを送受信するためのAPIです。

Java EEは、多数のツールやフレームワークとともに使用されることが一般的です。たとえば、Spring FrameworkやHibernateなどのフレームワークは、Java EEでの開発をより簡単にするために使用されます。

Jakarta EEへ

2018年にJava EEは、Jakarta EEへと名称を移行しました。もともと権利を持っていたOracle社からEclipse Foundationに移管されたことによって名称が変わりました。

Lesson 6 Chapter 3
Java ME

Java ME (Micro Edition)は、携帯電話やスマートフォンなどの組み込みデバイスや、小型のデバイス向けのJavaプラットフォームです。Java MEも、Java SEが基礎になっており、さらに、組み込みデバイス向けのアプリケーション開発のためのAPIや機能を提供します。これにより、Java MEアプリケーションは、小型デバイスで動作することができます。

組み込みによる特徴

Java MEにおいて、特定のタイプのデバイスやアプリケーションに適したAPIや機能がまとめられたものを「プロファイル」と言います。機器が異なれば、メモリなどの制約条件も異なるので、Java MEでは異なるタイプのデバイスやアプリケーションに対応するために、様々なプロファイルが用意されています。

例えば、CLDC(Connected Limited Device Configuration)は、低スペックなデバイス向けに設計されており、低スペックなデバイスで使用するために必要なAPIや機能が用意されています。

一方CDC(Connected Device Configuration)は、高スペックなデバイス向けに設計されています。このプロファイルには、高スペックなデバイスで使用するために必要なAPIや機能が用意されています。

このようにJava MEでは、異なるデバイス環境に向けてプロファイルを用意しています。

Java SE、Java EE、Java MEまとめ

ここまで、Javaにおける3つのプラットフォームについて扱ってきました。一口にJavaと言っても異なるプラットフォームがあることが分かったと思います。次のチャプターからは、Javaで標準的に提供されているパッケージや、クラス群について触れていきます。

Lesson 6 Chapter 4
java.langパッケージ

java.langパッケージは、Javaにおいて基本的なクラスやインターフェースを提供するパッケージです。このパッケージには、Javaに必要な基本的なクラスやインターフェースが含まれています。このパッケージは、Javaのすべてのプログラムに対して自動的にインポートされるため、明示的にインポートする必要はありません。本チャプターでは、java.langパッケージにおける代表的なクラスを扱っていきます。

Objectクラス

Objectクラスは、Javaのスーパークラスであり、すべてのJavaクラスのルートとなるクラスです。Javaのクラスは、Objectクラスを直接または間接的に継承しています。

Objectクラスには、オブジェクトに対して基本的な操作を提供するための多くのメソッドがあります。それらの中で最も重要なものは以下の通りです。

  • toString(): オブジェクトの文字列表現を返します。このメソッドは、オブジェクトをデバッグするために使用することができます

  • hashCode(): オブジェクトのハッシュ値を返します。ハッシュ値は、オブジェクトを識別するために使用されます

  • equals(): 2つのオブジェクトが等しいかどうかを比較します

  • clone(): オブジェクトの複製を作成します

equals()クラス

ここではequals()メソッドについて詳しく見てみましょう。このメソッドは、「2つのオブジェクトが等しいかどうかを比較する」と書きましたが、「等しい」とは、何を基準に判断されるのでしょうか。

「同一性」と「同値性」は、オブジェクト指向において重要な概念です。2つのオブジェクトの等しさは、基本的にはどちらかによって判定されます。

同一性は、2つのオブジェクトが同じインスタンスであるかどうかを比較することを指します。2つのオブジェクトが同じインスタンスである場合、同一であるといいます。同一性は、通常、==演算子によって比較されます。Javaの場合、==演算子はオブジェクトの参照値を比較するために使用されます。

同値性は、2つのオブジェクトが同じ値を持っているかどうかを比較することを指します。2つのオブジェクトが同じ値を持っている場合、同値であるといいます。同値性は、通常、equals()メソッドによって比較されます。Javaの場合、equals()メソッドはオブジェクトの同値性を確かめるために使用されます。

以下のコードを見てみましょう。

Main.java
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");

System.out.println(str1 == str2); // 出力: true
System.out.println(str2 == str3); // 出力: false
System.out.println(str1.equals(str2)); // 出力: true
System.out.println(str2.equals(str3)); // 出力: true

まず、str1 == str2の実行結果は、trueになります。これは、Stringオブジェクトがnewキーワードなしにインスタンスを生成すると、同じ値の文字列のStringオブジェクトが既にある場合、そのオブジェクトを参照するという特徴があるためです。==演算子は、同一性をもとに比較を行うので、同じ参照先を持っているstr1str2は同じとみなされます。

str2 == str3の実行結果は、falseになります。str3newキーワードを使って新しく生成されたインスタンスなので、2つのインスタンスが異なる参照先を持つからです。

str1.equals(str2)str2.equals(str3)はどちらも、trueを返します。何故ならどちらの場合も、比較するふたつの変数に格納されている文字列の値が、"Hello"になっていて同値だからです。

equals()メソッドは、同値性を確かめると学んできました。しかしそれは、常にそうという訳ではありません。全てのスーパークラスにあたるObjectクラスにおいて、equals()メソッドは、同一性を確かめるメソッドとして定義されています。つまり、Stringなどの特定のクラスにおいては、同値性を確かめるようにオーバーライドされているというのが正しい理解です。

Systemクラス

Systemクラスは、Javaにおいてシステムに関する情報を取得するためのクラスです。Systemクラスには、以下のような重要なメソッドが含まれています。

  • currentTimeMillis(): 現在時刻をミリ秒単位で取得します

  • arraycopy(Object src, int srcPos, Object dest, int destPos, int length): 配列の一部を別の配列にコピーします

  • exit(int status): アプリケーションを終了します

  • getProperties(): システムプロパティを取得します

Systemクラスには、標準入出力に関するstaticフィールドも定義されています。

  • in: 標準入力を受け取るためのInputStreamクラスのフィールド

  • out: 標準出力を出力するためのPrintStreamクラスのフィールド

  • err: 標準エラー出力を出力するためのPrintStreamクラスのフィールド

例えば、System.out.println("Hello World")は、"Hello World"とコンソールに出力しますね。

このようにSystemクラスは、Javaにおいて主にシステムに関する情報を取得するために使用されます。

Mathクラス

Mathクラスは、JavaのAPIに含まれる数学関数を提供するクラスです。このクラスは、数学的な演算や数学関数を使用するために使用されます。 Mathクラスは全てのメソッドがstaticメソッドなので、インスタンスを生成することなく利用することができます。

Mathクラスには、以下のようなメソッドが含まれます。

  • abs(double a): 絶対値を返す

  • max(double a, double b): aとbのうち大きい方の値を返す

  • min(double a, double b): aとbのうち小さい方の値を返す

  • sqrt(double a): aの平方根を返す

  • random(): 0から1未満の乱数を返す

  • round(double a): 四捨五入した結果を返す

  • pow(double a, double b): aのb乗を返す

  • sin(double a): aの度のサイン値を返す

  • cos(double a): aの度のコサイン値を返す

  • tan(double a): aの度のタンジェント値を返す

round()メソッド

ここでは、round()メソッドについて詳しく見ていきます。このメソッドは、引数として与えられた数値を最も近い整数に丸めます。

以下に、round()メソッドを用いた例を示します。

Main.java
double number1 = 2.345;
double number2 = 2.5;

// 丸めて整数にする
int rounded1 = (int) Math.round(number1);
int rounded2 = (int) Math.round(number2);

System.out.println(rounded1); // 出力: 2
System.out.println(rounded2); // 出力: 3

以上のようにround()メソッドは、小数第一位の位を四捨五入した結果を返すメソッドです。

Mathクラスは、数学的な演算や数学関数を使用するうえで非常に便利なクラスで、ゲーム開発や科学技術計算など、様々なアプリケーションで使用されます。

また、Mathクラスには以下のような定数も定義されています。

  • E: 自然対数の底にもっとも近いdouble値

  • PI: 円周率にもっとも近いdouble値

Integerクラス

Integerクラスは、Javaにおいて整数値を扱うためのクラスです。このクラスは、int型をラップするために使用され、int型の整数値をオブジェクトとして扱うことができます。

Integerクラスには、以下のようなメソッドが含まれています。

  • intValue(): Integerオブジェクトをint型に変換して返す

  • parseInt(String s): 文字列をint型に変換して返す

  • toString(int i): int型を文字列に変換して返す

  • valueOf(int i): int型をIntegerオブジェクトに変換して返す

Integerクラスには、以下のような定数も定義されています。

  • MIN_VALUE: int型の最小値

  • MAX_VALUE: int型の最大値

Integerクラスは、int型をオブジェクトとして扱うことができるため、コレクションフレームワークなどで使用することができます。コレクションフレームワークとは、複数の要素を格納するためのデータ構造を提供するライブラリです。コレクションに関しては、java.utilパッケージで後述します。コレクションには、int型などのプリミティブ型は直接的に使用することができませんので、Integerクラスのような、プリミティブ型をラップするクラスが用意されています。また、Integerクラスは、基本データ型を文字列に変換するためにも使用されます。

オーバーフロー

int型は、32ビット符号付き整数を表します。つまり、-2,147,483,648から2,147,483,647までの整数値を表すことができます。しかし、int型の変数に演算子を使用することによって、この範囲を超えた値を表すことができます。この現象をオーバーフローと呼びます。 オーバーフローは、int型が表現できる最大値(2,147,483,647)を超えた場合に発生します。この場合、値が最小値(-2,147,483,648)に戻ります。

Stringクラス

Stringクラスは、Javaにおいて文字列を表すクラスです。このクラスは、文字列の基本的な操作(連結、検索、抽出など)をサポートしています。

Stringクラスは、文字列リテラル""を使ってインスタンスを作成することができます。Stringクラスは、以下のようなメソッドを持っています。

  • concat(): 文字列を連結し、新しい文字列を返す

  • substring(): 文字列から一部を抽出して返す

  • replace(): 文字列中の指定した文字列を置き換えて返す

  • split(): 文字列を指定した区切り文字で分割し、配列として返す

  • trim(): 文字列の前後の空白を削除し返す

  • toLowerCase(): 文字列を小文字に変換して返す

  • toUpperCase(): 文字列を大文字に変換して返す

  • length(): 文字列の文字数を返す

  • charAt(): 文字列の中の指定した位置の文字列を返す

Stringクラスは、不変クラスであるため、文字列を変更する操作を行った場合は、新しいインスタンスが生成されます。

Characterクラス

Characterクラスは、Javaにおいて文字を表すクラスです。このクラスは、文字に対する基本的な操作をサポートします。

Characterクラスは、文字リテラル''を使ってインスタンスを作成することが出来ます。Characterクラスは、以下のようなメソッドを持っています。

  • isLetter(): 文字がアルファベットかどうかを判定し、結果を返す

  • isDigit(): 文字が数字かどうかを判定し、結果を返す

  • isLowerCase() / isUpperCase(): 文字が小文字か大文字かどうかを判定し、結果を返す

  • toLowerCase() / toUpperCase(): 文字を小文字または大文字に変換し、結果を返す

  • getNumericValue(): 文字が表す数字の値を返す

  • codePointAt(): 文字のUnicode値を返す

以上のメソッドを用いて文字が数字かどうかを判定し、数字ならその数値を取得したり、文字が記号かどうかを判定し、記号ならその記号のUnicode値を取得するなどができます。

このようにCharacterクラスでは、文字に対する操作をするための強力な機能を持っています。

まとめ

ここまで、java.langパッケージにおける主要なクラスを見てきました。ここで紹介した以外でも、Exceptionクラス、Errorクラスなど、Javaプログラムを実行する上で基礎的な機能を提供しています(Exception、Errorに関しては、次のレッスンで詳しく扱います)。提供されるクラス、インターフェイスを使用することで、Javaプログラムを効率よく開発することができます。

Lesson 6 Chapter 5
java.ioパッケージ

前チャプターでは、java.langパッケージについて扱いました。java.langパッケージは、Javaにおいて基本的なクラスやインターフェースを提供していました。本チャプターで扱うjava.ioパッケージは、入出力(I/O)を扱うためのクラスやインターフェースを提供しています。このパッケージを使用することで、ファイルの入力や標準入力、昇順出力などを実現することができます。

本チャプターでは、そんなjava.ioパッケージの代表的なFileクラスに焦点をあてて学んでいきます。

Fileクラス

JavaのFileクラスは、ファイルやディレクトリを操作するためのクラスです。

Fileクラスのインスタンスを作成するには、以下のようにします。

Main.java
File file = new File("file_path");
                    

ここで、"file_path"には、操作対象のファイル・ディレクトリの絶対パスまたは相対パスを指定します。

Fileクラスは、以下のようなメソッドを持っています。

  • exists(): 指定されたファイルやディレクトリが存在するかどうかを返します。

  • isFile(): 指定されたパスがファイルであるかどうかを返す

  • isDirectory(): 指定されたパスがディレクトリであるかどうかを返す

  • createNewFile(): 指定されたパスに新しい空のファイルを作成する

  • mkdir(): 指定されたパスに新しいディレクトリを作成する。

  • delete(): 指定されたファイルやディレクトリを削除する

この他にも、Fileクラスには、ファイルやディレクトリの情報取得や操作に関する多くのメソッドがあります。詳細については、JavaのAPIドキュメントを参照してみましょう。

Lesson 6 Chapter 6
java.util.パッケージ

本チャプターでは、java.utilパッケージを扱っていきます。このパッケージでは、日付や時間、コレクション、正規表現などに関するクラスやインターフェースを提供しています。

主要なクラス、インターフェースは以下です。

  • ArrayListクラス

  • HashMapクラス

  • Dateクラス

  • Comparatorインターフェース

  • Iteratorインターフェース

  • Scannerクラス

それぞれ詳しく見ていきましょう。

ArrayListクラス

ArrayListクラスは、サイズ変更可能な配列を表すデータ構造を提供します。通常の配列のように添え字を使用して指定した要素に直接アクセスすることが可能ですが、挿入と削除に関しては低速になるという特徴があります。

ArrayListクラスでは、次のようなメソッドが提供されています。

  • add(E element): 指定された要素をリストに追加する

  • get(int index): 指定されたインデックスに対応する要素を返す

  • remove(int index): 指定されたインデックスに対応する要素を削除する

  • size(): リストに含まれる要素の数を返す

  • isEmpty(): リストが空かどうかを返す

  • clear(): リストからすべての要素を削除する

ArrayListを使用するためには、新しいArrayListオブジェクトを生成し、add()メソッドを使用して要素を追加します。

Main.java
ArrayList list = new ArrayList();
list.add("Apple");
list.add("Banana"); 

この例では、新しいArrayListオブジェクトを生成し、add()メソッドを使用して、"Apple""Banana"という文字列を追加しています。

要素を取得するには、get()メソッドを使用します。

Main.java
String fruit = list.get(0);
System.out.println(fruit); 
//実行結果:Apple

この例では、get()メソッドを使用して、インデックス0に対応する要素を取得し、変数fruitに代入して、出力しています。先ほどのコードで"Apple"を挿入したので、それが出力されます。

ArrayListクラスは、配列のような挙動を持ち、要素を追加したり削除したりすることができ、インデックスによって要素を取得することができます。ArrayListクラスは、配列と似たデータ構造を持ちながら、要素数を後から変更することができるのが特徴です。

HashMapクラス

HashMapクラスは、キーと値を関連付けて格納できる構造を提供しており、順不同で格納される特徴があります。値に対して操作をする時はキーを使って呼び出します。

HashMapクラスでは、次のようなメソッドが提供されています。

  • put(K key, V value): 指定されたキーと値をマップに追加する

  • get(Object key): 指定されたキーに対応する値を返す

  • remove(Object key): 指定されたキーに対応する値を削除する

  • size(): マップに含まれる要素の数を返す

  • isEmpty(): マップが空かどうかを返す

  • clear(): マップからすべての要素を削除する

HashMapを使用するには、まず新しいHashMapオブジェクトを生成し、put()メソッドを使用してキーと値を追加します。

Main.java
HashMap map = new HashMap();
map.put("Apple", 150);
map.put("Banana", 120);

この例では、新しいHashMapオブジェクトを生成し、put()メソッドを使用して、"Apple"という文字列をキーとし、150を値として追加しています。また、"Banana"という文字列をキーとし、120を値として追加しています。

Main.java
int price = map.get("Apple");
System.out.println(price); 
// 実行結果:150

この例では、get()メソッドを使用して、"Apple"という文字列に対応する値を取得し、変数priceに代入しています。

HashMapクラスは、柔軟なデータ構造であり、高速な検索が可能です。しかし、HashMapクラスは、キーが重複してしまうと上書きされてしまうため注意が必要です。加えて冒頭でも述べたように、順不同で要素が格納されるので、順序に依存する処理をする場合は、ここでは扱いませんが、LinkedHashedMapやTreeMapを使用する方がいいかもしれません。

Dateクラス

Javaにおいて、日付や時刻を扱うために使用するのがDateクラスです。このクラスは、日時をUTCという世界共通の時間単位で表します。

UTCとは

UTCは、Coordinated Universal Timeの略で、1970年1月1日 00:00:00からの経過秒数を基準にしています。

Dateクラスには、次のようなメソッドが用意されています。

  • toString(): 日付エスケープ形式yyyy-mm-ddに整形する

  • setTime(long time): 指定されたミリ秒から日時を設定する

  • Date(): 現在の日時を表すDateオブジェクトを返す

  • Date(long date): 指定されたミリ秒から日時を表すDateオブジェクトを返す

使用するためには、新しいDateオブジェクトを生成し、getTime()メソッドを使用して現在時刻を取得します。

Main.java
Date date = new Date(); //現在時刻の取得
long time = date.toString(); //dateをyyyy-mm-ddに整形

ただし、Dateクラスは現在では推奨されていないため、代替としてCalendarクラスやjava.timeパッケージのクラスを使うことが推奨されています。

Calendarクラスは、日付や時刻を扱うためのクラスで、Dateクラスと同じように時刻を扱うことができます。また、java.timeパッケージには、LocalDateやLocalTimeなど、より高機能な日付や時刻を扱うためのクラスが用意されています。

Dateクラスを使っていると、日付エスケープ形式yyyy-mm-dd以外の形で日時を出力したい場合があります。その場合は、SimpleDateFormatクラスを使うと便利です。SimpleDateFormatクラスは、java.textパッケージに含まれており、日付や時刻を文字列に変換するためのクラスです。以下のように指定します。

Main.java
Date date = new Date(); //現在時刻の取得
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
System.out.println(sdf.format(date)); 

SimpleDateFormatクラスのインスタンス生成時に任意のフォーマットを指定することができます。そしてformat()メソッドで、フォーマットを用いて文字列へ変換します。

以上のクラスを用いることで、日付や時刻を扱うことができます。

Comparatorインターフェース

Comparatorインターフェースは、Javaでコレクション内の要素を比較しソートするためのインターフェースです。このインターフェースを実装することで、独自の比較方法を指定して要素をソートすることができます。

Comparatorインターフェースには主に、次の2つの抽象メソッドがあります。

  • compare(T o1, T o2): 2つのオブジェクトを比較し、結果を整数値で返します。このメソッドは、2つのオブジェクトが等しい場合は0、1つ目のオブジェクトが2つ目のオブジェクトより大きい場合は正の値、小さい場合は負の値を返します。

  • equals(Object obj): 2つのオブジェクトが等しいかどうかを判定します。

独自に定義したクラスにComparatorインターフェースを継承し、メソッドをオーバーライドすることで、クラス独自の比較方法を指定することが出来ます。実際にコードを見ながら理解していきましょう。

Main.java
Listclass Person {
  String name;
    int age;
    // コンストラクタやgetter/setter省略
}
                  
class AgeComparator implements Comparator {
    public int compare(Person p1, Person p2) {
        return p1.getAge().compareTo(p2.getAge()); //
    }
}
                  
List people = // 要素を格納したリストを作成
Collections.sort(people, new NameComparator());

以上のプログラムでは、Personクラスをソートするための独自の比較方法をAgeComparatorクラスで定義しています。AgeCpmparatorクラスは、Comparatorを継承しています。compare()メソッドのオーバーライドについては、IntegerクラスのcompareTo()メソッドを用いています。このオーバーライドにより、AgeComparatorを使うと、ageフィールドの値でPersonクラスのコレクションをソート出来るようになります。

このようにComparatorインターフェースは、独自の比較方法を定義する際に使われます。

Iteratorインターフェース

Iteratorインターフェースはコレクション内の要素に順番にアクセスするためのインターフェースです。

Iteratorインターフェースを実装したIteratorオブジェクトをイテレータと呼びます。

あるコレクションに対して、そのコレクションの要素にアクセスするためのイテレータを取得するには、iterator()メソッドを使用します。

Main.java
List list = List.of(1, 2, 3, 4, 5);//リストの生成
Iterator iterator = list.iterator();//イテレータの取得

Iteratorインターフェースには、以下のメソッドが定義されています。

  • hasNext(): 次の要素が存在するかどうかを返す

  • next(): 次の要素を返す。最後の要素を超えた場合は"NoSuchElementException"を発生させる

  • remove(): イテレータによって最後に返された要素を削除する

  • forEachRemaining(): 各要素を順番に処理する

以下のように、メソッドを使うことが出来ます。

Main.java
List list = List.of(1, 2, 3, 4, 5);//リストの生成
Iterator iterator = list.iterator();//イテレータの取得

while(iter.hasNext()){
  System.out.print(iter.next() + " ");
}

//実行結果: 1 2 3 4 5

hasNext()メソッドを条件式として使うことで、listの要素数分、処理を回すことができます。繰り返し処理の中では、next()メソッドを使ってlistから要素を取り出しています。

このようにIteratorインターフェースでは、コレクションに対して、繰り返し処理を行うためのメソッドが用意されています。

Scannerクラス

Scannerクラスは、Javaで入力を受け取るためのクラスです。このクラスを使用することで、標準入力、ファイル、文字列などからデータを読み取ることができます。

Scannerクラスを生成する際には、コンストラクターの引数に、入力ストリームを指定します。

入力ストリームとは、プログラムに外部からデータを読み込むための「データの流れ」のことを指します。詳しくは立ち入りません。ここでは、基本出来な[System.in]について触れます。以下のコードを見てみましょう。

Main.java
Scanner scanner = new Scanner(System.in);
                    

System.inは、標準入力を受け取るScannerオブジェクトを生成するときに使います。また、ファイルからの読み取りを行う場合、前チャプターで扱ったFileクラスを使います。

Main.java
Scanner scanner = new Scanner(new File("example.txt"));
                    

入力を受け取るには、以下のメソッドを使います。

  • next(): 次のトークンを取得します。トークンは、空白や改行などで区切られています。

  • nextLine(): 次の行を取得

  • nextInt(): 次の整数を取得

  • nextDouble(): 次のdouble型の数値を取得

また、hasNext()メソッドを使うことで、次のトークンが存在するかどうかを知ることができます。

Scannerクラスは、Javaでの入力処理において非常に便利なクラスになっています。

ここまで、本レッスンでは、Javaプラットフォームと標準APIについて扱ってきました。Javaプラットフォームには、開発環境を提供するJDK、その中に実効環境を提供するJRE、そしてその中にクラスライブラリと仮想マシンであるJVMがありました。次にJavaSE、JavaEE、JavaMEそれぞれの特徴を学びました。そして、標準APIに含まれる様々なパッケージとそのクラスを見てきました。このレッスンを通して、Javaの全体像が見えてきたのではないでしょうか。。