1. Alice と 30 を組にして "Alice:30" を返す
  2. Bob と 25 を組にして "Bob:25" を返す
  3. 空文字と 0 でも ":0" を返す
  4. 日本語の名前と大きい年齢でも組にできる
コース一覧
Java 中級:コレクション・Stream・例外処理
Pair<K,V> を作る

Java 中級:コレクション・Stream・例外処理

コレクション、ジェネリクス、例外処理、Stream API、関数型インターフェース、日付処理、ファイル I/O、継承など Java の中級トピックを実践的に学べるコースです。Java の基礎文法とオブジェクト指向を理解している学習者を対象に、現場の Java コードを読み書きするための知識を補強します。約 16 時間 (1 日 30 分 × 32 日) で 64 レッスンを修了でき、修了後は Spring Boot や業務システム開発に必要な Java 力が身につきます。

1
コレクション基礎
01. ArrayList を使う5分
02. List を走査する5分
03. 要素の削除と検索5分
04. HashMap の基本5分
05. Map を走査する5分
06. Set で重複を排除5分
07. Collections クラスの便利メソッド5分
08. コレクション基礎 まとめクイズ5分
2
ジェネリクス
01. ジェネリッククラスを作る5分
02. ジェネリックメソッド5分
03. 境界型パラメータ5分
04. ワイルドカード ?5分
05. Pair<K,V> を作る5分
06. ジェネリクス まとめクイズ5分
3
例外処理
01. try-catch で例外をつかむ5分
02. 複数の catch ブロック5分
03. throws と例外の伝播5分
04. 独自の例外を作る5分
05. try-with-resources5分
06. finally ブロック5分
07. 例外処理 まとめクイズ5分
4
Stream API
01. Stream を作る5分
02. filter で絞り込む5分
03. map で変換する5分
04. reduce で集約する5分
05. collect で集める5分
06. sorted で並び替え5分
07. distinct で重複排除5分
08. limit と skip5分
09. 並列ストリーム5分
10. Stream API まとめクイズ5分
5
関数型インターフェース
01. ラムダ式の基本5分
02. メソッド参照 ::5分
03. Function インターフェース5分
04. Predicate インターフェース5分
05. Consumer と Supplier5分
06. BiFunction と 2 引数の関数5分
07. 関数型インターフェース まとめクイズ5分
6
文字列操作
01. String.format で書式化5分
02. StringBuilder で連結5分
03. 正規表現の基本5分
04. split と join5分
05. 文字列操作 まとめクイズ5分
7
日付と時刻
01. LocalDate で日付を扱う5分
02. LocalDateTime で時刻も扱う5分
03. Duration で時間差を計算5分
04. 日付の書式化とパース5分
05. 日付の加減算5分
06. 日付と時刻 まとめクイズ5分
8
ファイル I/O
01. Files でファイルに書き込む5分
02. ファイルを行単位で読む5分
03. Path でファイルパスを扱う5分
04. BufferedReader と Stream API5分
05. ファイルの存在確認と削除5分
06. ファイル I/O まとめクイズ5分
9
継承とポリモーフィズム
01. extends で継承する5分
02. super で親を呼ぶ5分
03. メソッドのオーバーライド5分
04. abstract で抽象クラス5分
05. interface で契約を定義5分
06. default メソッド5分
07. instanceof と型パターン5分
08. ポリモーフィズムを活かす5分
09. 継承とポリモーフィズム まとめクイズ5分

Pair<K,V> を作る

2 つの値を返したいのに、return は 1 個しか書けない

「最小値と最大値をまとめて返したい」「商品コードと在庫数を 1 セットで渡したい」。こういうとき、Java の return は 1 個の値しか返せません。仕方なく int[] に詰めて返すと、受け取る側は [0] が最小値で [1] が最大値だと覚えておかないといけません。名前が付いていないので、順番を取り違えても誰も気づけないのです。

2 つの値に名前を付けて 1 つの型にしてしまえば、この問題は消えます。たとえば「範囲」を表す小さなクラスは次のように書けます。

Java

public class Range<T> { private final T min; private final T max; public Range(T min, T max) { this.min = min; this.max = max; } public T lower() { return min; } public T upper() { return max; } }

Range<Integer> なら整数の範囲、Range<LocalDate> なら日付の範囲になります。フィールドを final にしておくと、作ったあとで書き換えられない箱になります。HashMap のキーに使ったあとに中身が変わってキーを見失う、という厄介な事故を防げます。

下限と上限で型が違うと、これでは足りない

Range<T> が使えるのは、2 つのフィールドが同じ型のときだけです。「文字列のラベルと整数の個数」のように型が違う 2 つを持たせたいときは、型パラメータをカンマで並べて 2 つ宣言します。

Java

public class Labeled<L, V> { private final L label; private final V value; // コンストラクタと取り出しメソッドは Range と同じ形で書く }

宣言が <L, V> の 2 つになっただけで、考え方は 1 つのときと変わりません。Labeled<String, Integer> と書けば、label は String、value は Integer に決まります。標準ライブラリの HashMap<K, V> や Map.Entry<K, V> も、まったく同じ仕組みで 2 つの型を受け取っています。

型パラメータの名前は 1 文字が慣習です。T は Type、E は Element、K と V は Key と Value、R は Result を表します。キーと値を持たせるなら <K, V> を選ぶと、読む人にすぐ伝わります。

決まりきったコードを毎回手で書くのが面倒

Range<T> を見返すと、フィールドとコンストラクタと取り出しメソッドが、ほとんど決まりきった形で並んでいます。値を入れるだけのクラスにこれを毎回書くのは退屈です。Java 16 以降なら record が使えます。

Java

public record Range<T>(T min, T max) {}

この 1 行で、final フィールド、コンストラクタ、min() max() の取り出しメソッド、そして equals hashCode toString が自動で作られます。型パラメータを 2 つにしたいときは、record でもクラス名の右にカンマで並べます。

取り出しメソッドの名前が getMin() ではなく min() になる点だけ気をつけてください。

自動で作られる equals が効いてくるのは、HashSet に入れて重複を消したいときです。普通のクラスだと、中身がまったく同じでもインスタンスが別なら別物として扱われます。record なら値が同じかどうかで判定してくれます。

よくある間違い

型パラメータを 2 つ宣言したときに、使う側で順番を逆に渡してしまう事故がよく起きます。Map<K, V> と同じくキーを先、値を後、の並びで揃えておくと迷いません。

もう 1 つ、setLabel のような setter を生やして中身を書き換えられるようにするのはやめましょう。値を持つだけのクラスは、作り直すほうが安全です。

要件

  1. Solution の中 (内部クラスでも record でも可) に、複数型パラメータ <K, V> を持つ Pair 相当のクラスを定義すること
  2. formatPair(String name, int age) の中で Pair<String, Integer> を new で生成し、key と value を取り出して name:age 形式の文字列を組み立てること
  3. 戻り値の区切り文字は半角コロン (:) ちょうど 1 つで、前後にスペースを入れないこと

入出力例

formatPair("Alice", 30) → "Alice:30" formatPair("Bob", 25) → "Bob:25" formatPair("", 0) → ":0" formatPair("タロウ", 120) → "タロウ:120"

ヒント

`Pair<K, V>` のフィールドは `final` 修飾子を付けると不変オブジェクトになり、`HashMap` のキーにしても安全になります

`Integer` を `String` に連結すると Java が自動で `toString` を呼ぶので、`pair.getKey() + ":" + pair.getValue()` のように書けば `"Alice:30"` の形になります

Java 14 以降なら `public record Pair<K, V>(K key, V value) {}` の 1 行で同じものが定義でき、`pair.key()` `pair.value()` で値を取り出せます

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/19·更新 2026/08/26

関連レッスン

  • ジェネリクス まとめクイズ

    ジェネリッククラス / ジェネリックメソッド / 境界型 / ワイルドカード / Pair の総まとめ。PECS や型消去 (type erasure) など実務で問われやすい論点を 4 択クイズで確認する。

  • try-catch で例外をつかむ

    Java の例外処理の基本となる try-catch 構文を学び、NumberFormatException を捕まえてデフォルト値を返すコードを書いてみよう。

  • Stream を作る

    Java の Stream API を学ぶ最初のステップとして、配列やコレクションから Stream を生成し、count などのターミナル操作で要素数を取得するコードを書いてみよう。

  • ラムダ式の基本

    Java 8 から導入されたラムダ式の文法と関数型インターフェースの考え方を学び、Stream と組み合わせて配列の合計を一行で書く感覚を身につけよう。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • セット重複を持たない順序なし集合
  • クラスデータと振る舞いを束ねる単位
  • フィールドクラスが持つデータ
  • 標準ライブラリPythonに同梱の公式モジュール群
  • コンストラクタインスタンス生成時の初期化処理
  • メソッドクラスに属する関数
  • インスタンスクラスから生成された実体
  • 戻り値呼び出し元への返答を表す点線矢印
main.java
学習モード
エディタを読み込んでいます

メモ

Pair<K,V> を作る

⌘S で保存