スポンサーリンク

Javaで毎回ググる定番処理を卒業!そのまま貼れる便利スニペット集

スポンサーリンク
この記事は約35分で読めます。
スポンサーリンク

Javaって、ちょっとした処理でも「えーっと、これ毎回ググってるやつ…」ってなりがちですよね。
たとえば nullで落ちない取り出し方日付の作り方(Dateじゃなくてjava.time)Listの重複削除Mapのキーが無いときの安全な書き方ファイル読み書きあたり。
1回1回は小さいのに、積み重なると検索だけで時間が溶けます。

そこでこの記事は、実務でよく出る「定番処理」を “そのまま貼れる短いJavaスニペット” にして、シーン別にまとめた 道具箱 です。しかも「古い書き方 → 新しい書き方」もサッと分かるようにして、NG例と注意点も最小限だけ付けます。迷って変な書き方に寄るのを防ぐためです。

読み方はカンタンで、最初から全部読む必要はありません。困った瞬間に目次から飛んで、欲しいところだけコピペでOKです。ブックマークしておけば、次から「また検索…」を減らして、コーディングに時間を回せますよ。

  1. まず押さえる:この記事の使い方と“新しい書き方”の基準
    1. 想定するJava版(目安:Java 8〜17)と前提
    2. スニペットの見方(いつ使う?/1行説明/注意点)
    3. “古い→新しい”置き換え早見表(入口だけ)
  2. null対策:落ちない・読みやすい取り出し方(Optional含む)
    1. nullでも安全に取り出す(Optional.ofNullable / デフォルト値)
    2. nullなら作る(MapのcomputeIfAbsent)
    3. NG例:nullチェック地獄/Optionalの無理やり使用
  3. 文字列:結合・分割・整形・比較で迷わない
    1. ループの結合はStringBuilder(+連結NG例付き)
    2. join / split / trim / 空チェック
    3. フォーマット(String.format / java.textより簡単に)
  4. 日付時刻:Dateを卒業してjava.timeで安全に
    1. 今日・今を作る(LocalDate/LocalDateTime/Instant)
    2. 文字列↔日付(DateTimeFormatter)
    3. タイムゾーンの扱い(ZonedDateTime)とNG例
    4. おまけ:Dateを要求される時の“橋渡し”変換(補助スニペット)
  5. List/Set/Map:検索しがちな“あるある操作”を1発で
    1. 重複を消す/並び順を保つ
    2. フィルタ・変換・集計(Streamの最短例)
    3. Map:キーが無い時のデフォルト/安全な取得
  6. ファイルIO:読み書きの定番(try-with-resources)
    1. 1行ずつ読む/全部読む(Files)
    2. 書き込む(追記・上書き)
    3. 文字コード(UTF-8)と例外の扱い
  7. 例外とログ:ミスしやすい“地味ゾーン”を固める
    1. 例外メッセージの作り方(情報を入れる)
    2. 例外を握りつぶさない(NG例:空catch)
    3. ログ出力の型(info/debug/error)とテンプレ
  8. 正規表現:最小で使う(やりすぎない)
    1. ある文字だけ残す/数字だけ抜く
    2. 置換・抽出の最短例(Pattern/Matcher)
  9. 並列処理:使う前に“条件チェック”
    1. parallelStreamはいつ効く?(合うケース/合わないケース)
    2. スレッド安全の注意点(共有変数NG)
  10. テスト:まずは“動く安心”を作るスニペット
    1. JUnitで例外テスト
    2. パラメータ化テストの入口
  11. コピペ用チートシート(目次リンク)と検索のコツ
    1. カテゴリ別リンク(探す時間ゼロへ)
    2. “自分用スニペット箱”の作り方(運用ルール)
  12. よくある質問
スポンサーリンク

まず押さえる:この記事の使い方と“新しい書き方”の基準

この記事は「Javaの定番処理をコピペで終わらせる」ための道具箱です。なので読み方はシンプルで、困った瞬間に該当カテゴリへ飛んで、そのまま貼るのが正解です。

各スニペットは基本、短く・安全に・読みやすく寄せてあります。もし「これ、うちのプロジェクトの都合で変えたい」が出ても、土台があるだけで調整がめちゃ楽になります。

想定するJava版(目安:Java 8〜17)と前提

  • 目安は Java 8〜17 です(現場でよく使われる範囲)。
  • 日付は java.util.Date より java.time(LocalDate等) を優先します。
  • ファイルは java.nio.file.Files を中心にします(短く書ける&安全寄り)。
  • Stream/Optionalも出ますが、「やりすぎない」が方針です(読みにくくなったら素直にfor文でOKです)。

スニペットの見方(いつ使う?/1行説明/注意点)

本文の各所は、だいたいこの3点セットで出します。

  • いつ使う?:どんな場面で刺さるか(例:Mapにキーが無いかも)
  • 1行説明:結論だけ(例:無ければデフォルトを返す)
  • 注意点:ハマりどころを1つだけ(例:orElseは重い処理でも毎回呼ぶことがある)

ここを読むだけで「採用していいやつか」が判断できるようにしてあります。逆に、悩み始めたらその時点でNG例も見てください。“やっちゃいがち”を1個だけ潰します。

“古い→新しい”置き換え早見表(入口だけ)

まずは入口だけ、よくある置き換えを貼っておきます。迷ったら「右側」を選ぶ感じでOKです。

よくある古い書き方いまの定番(推し)ざっくり理由
Date / Calendarjava.timeLocalDateTime / Instant / ZonedDateTimeバグりにくい・読みやすい
try { ... } finally { close }try-with-resourcesclose漏れを減らせる
`str == nullstr.length() == 0`
map.containsKey(k) ? map.get(k) : xmap.getOrDefault(k, x)1行で安全
ループで s += ...StringBuilder無駄が減って速いことが多い

ちなみに「IDEの雛形機能」を使うと、この道具箱がさらに強くなります。
カテゴリ的には:IDE(無料:IntelliJ IDEA Community / Eclipse)のライブテンプレート、スニペット管理(無料:GitHub Gist / Notion / VS Codeスニペット)あたりを入れておくと、検索回数が体感で減ります。

null対策:落ちない・読みやすい取り出し方(Optional含む)

nullって、放置すると ある日突然NPE(NullPointerException)で落ちる地雷なんですよね。しかもnullチェックを増やしすぎると、今度はコードがゴチャゴチャして読めなくなります。

ここでは「落ちない」「短い」「意図が伝わる」を優先して、よく使う型を固定します。

nullでも安全に取り出す(Optional.ofNullable / デフォルト値)

いつ使う?:値が null かもしれない。だけど、欲しいのは「安全な値(デフォルト)」
1行説明Optional.ofNullable で包んで、無ければデフォルトを返します。
注意点orElse() の中が重い処理だと、nullじゃなくても毎回実行されることがあります(→ orElseGet)。

String name = Optional.ofNullable(user.getName())
        .orElse("(名無し)");

重いデフォルト生成(例:DBアクセス、計算、ログ組み立てなど)があるならこっち:

String name = Optional.ofNullable(user.getName())
        .orElseGet(() -> createDefaultName());

ついでに「加工してから取りたい」も定番です(nullなら途中で止まるのが嬉しいやつ):

int len = Optional.ofNullable(text)
        .map(String::trim)
        .filter(s -> !s.isEmpty())
        .map(String::length)
        .orElse(0);

nullなら作る(MapのcomputeIfAbsent)

いつ使う?:Mapに「無ければ作って入れて、それを使う」をしたい(集計・グルーピングで超ある)
1行説明computeIfAbsent で「無いなら作る」を1発にします。
注意点:作る処理の中で 同じMapをいじるとややこしくなるので、生成は素直に。

Map<String, List<String>> map = new HashMap<>();

map.computeIfAbsent("A", k -> new ArrayList<>())
   .add("apple");

「キーが無いなら0」みたいな定番は getOrDefault も楽です:

int count = counts.getOrDefault(key, 0);

NG例:nullチェック地獄/Optionalの無理やり使用

いつ使う?:やってしまいがちなので、避けるために見るやつ
1行説明:ネストifは見通しが死にます。Optionalも“型にするため”に乱用すると逆に読みにくいです。
注意点:Optionalは「戻り値として使う」寄りで、フィールドに持たせる運用は基本おすすめしません(チーム方針があるならそれ優先でOKです)。

こういうの、増えた瞬間に辛くなります:

// NG:nullチェックがネストして読めない
if (user != null) {
    if (user.getProfile() != null) {
        if (user.getProfile().getName() != null) {
            return user.getProfile().getName();
        }
    }
}
return "(名無し)";

代わりに「Optionalでスパッ」と書くか、素直に早期returnで平らにするのが安定です(このあともそのノリで統一します)。

補助として触れるなら、入力チェックが多い人は バリデーション(Jakarta Bean Validation)、nullの危険を早めに見つけたい人は 静的解析(SpotBugs / Error Prone:無料〜) あたりが相性いいです(導入は必要な人だけでOKです)。

文字列:結合・分割・整形・比較で迷わない

文字列って、地味に「いつものやつ」が多いですよね。しかも雑に書くと、遅くなったり空文字やスペースでバグったり比較が逆で落ちたりします。ここでは「迷ったらこれ」を固定します。

ループの結合はStringBuilder(+連結NG例付き)

いつ使う?:ループで文字列をどんどん足したい(ログ、CSVっぽい出力、HTML生成…)
1行説明:ループ結合は StringBuilder が定番です。
注意点:最終的に toString() を忘れないようにだけ注意です。

StringBuilder sb = new StringBuilder();
for (String s : list) {
    sb.append(s).append(",");
}
String result = sb.toString();

区切り文字を綺麗にしたいなら「最後だけ消す」か、joinを使うのが楽です(joinは次で出します)。

NG例:ループで + 連結(小さいデータなら動きますが、増えると急にしんどくなりがち)

// NG:ループで + 連結(意図せず重くなることがある)
String result = "";
for (String s : list) {
    result += s;
}

join / split / trim / 空チェック

いつ使う?:配列・Listを結合したい/文字列を区切って配列にしたい/空っぽ判定したい
1行説明:結合は String.join、分割は split、空チェックは用途で分けます。
注意点split正規表現なので、.| を区切りにする時はエスケープが必要です。

結合(Listでも配列でもOK):

String joined = String.join(",", list);

分割(カンマ区切り):

String[] parts = text.split(",");

ピリオドで分割したい場合(. は正規表現だと「なんでも1文字」扱い):

String[] parts = text.split("\\.");

trim(前後の空白を削る):

String cleaned = text.trim();

空チェック:

  • Java 11+なら「空白だけ」も空扱いにできる isBlank() が便利です。
if (text == null || text.isBlank()) {
    return;
}

Java 8で isBlank() が使えない場合はこれで代用します:

if (text == null || text.trim().isEmpty()) {
    return;
}

フォーマット(String.format / java.textより簡単に)

いつ使う?:メッセージや表示用文字列を「読みやすく」組み立てたい
1行説明String.format を使うと、+ だらけより読みやすくなります。
注意点:ログ用途は String.format より、後で出す SLF4Jの {} が軽くて便利なことが多いです(必要な人だけでOK)。

String msg = String.format("userId=%s, items=%d", userId, items.size());

文字列比較の安全形も、ここで固定しちゃうと楽です(nullでも落ちないやつ):

if ("OK".equals(status)) {
    // statusがnullでも落ちない
}

文字列が多い現場なら、ログ出力と相性がいい SLF4J({} プレースホルダ)、補助で Apache Commons Lang(StringUtils) みたいなユーティリティを「必要な場面だけ」入れるのもアリです(入れすぎ注意で)。

日付時刻:Dateを卒業してjava.timeで安全に

日付まわりって、油断すると一気に事故りますよね。特にタイムゾーン文字列パース。なのでここは方針を先に固定します。
基本は java.time(LocalDate/LocalDateTime/Instant/ZonedDateTime)で統一。そして毎回これだけ確認してください:

  • 「タイムゾーンが必要?」 → 必要なら ZonedDateTime / Instant 側に寄せる
  • ただの「日付だけ」→ LocalDate
  • 「日時だけ(タイムゾーン不要)」→ LocalDateTime

今日・今を作る(LocalDate/LocalDateTime/Instant)

いつ使う?:現在日時・今日の日付が欲しい
1行説明:日付だけは LocalDate、日時は LocalDateTime、世界共通の時刻は Instant
注意点LocalDateTime はタイムゾーン情報を持たないので、「どこの時間?」が必要なら後述の ZonedDateTime にします。

LocalDate today = LocalDate.now();
LocalDateTime now = LocalDateTime.now();
Instant nowUtc = Instant.now(); // UTC基準の“点”

「ミリ秒が欲しい」みたいなときも、まず Instant を基準にすると事故りにくいです。

文字列↔日付(DateTimeFormatter)

いつ使う?:APIやファイルの文字列を日付にしたい/日付を文字列で出したい
1行説明DateTimeFormatter をテンプレ化して使い回します。
注意点:フォーマットはプロジェクト内で統一するのが正義です(人によって違うと地獄です)。

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

LocalDateTime dt = LocalDateTime.parse("2025-12-24 10:30:00", fmt);
String text = dt.format(fmt);

日付だけならこっち:

DateTimeFormatter dateFmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");

LocalDate d = LocalDate.parse("2025-12-24", dateFmt);
String s = d.format(dateFmt);

タイムゾーンの扱い(ZonedDateTime)とNG例

いつ使う?:表示や締め処理が「日本時間で」とか、国をまたぐ時刻を扱う
1行説明:タイムゾーンが絡むなら ZonedDateTime(または保存は Instant)で持ちます。
注意点:サーバーのデフォルトタイムゾーンに乗っかると、環境差でズレます(本番だけズレる、が最悪パターンです)。

ZoneId tokyo = ZoneId.of("Asia/Tokyo");

ZonedDateTime zdt = ZonedDateTime.now(tokyo);
Instant instant = zdt.toInstant(); // 保存・通信はInstantが楽なこと多い

NG例:「サーバー時刻=日本時間」と思い込む(環境でズレます)

// NG:実行環境のデフォルトタイムゾーンに依存してしまう
LocalDateTime now = LocalDateTime.now();

「日本時間で処理したい」なら、最初から指定します:

ZonedDateTime nowJst = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));

おまけ:Dateを要求される時の“橋渡し”変換(補助スニペット)

いつ使う?:古いAPIが java.util.Date を要求してくる(まだ現場であります)
1行説明:内部は java.time で持って、境界だけ変換します。
注意点:内部ロジックまでDateに引きずられないのがコツです。

// Instant -> Date
Date legacyDate = Date.from(Instant.now());

// Date -> Instant
Instant instant = legacyDate.toInstant();

// LocalDateTime -> Date(タイムゾーンを決めてから)
ZoneId tokyo = ZoneId.of("Asia/Tokyo");
Date dateFromLdt = Date.from(localDateTime.atZone(tokyo).toInstant());
筆者
筆者

この章の結論はこれです:タイムゾーンが要るなら明示、要らないならLocal系、保存・通信はInstantが安定。ここを守るだけで「日付の事故」がかなり減ります。

List/Set/Map:検索しがちな“あるある操作”を1発で

コレクション操作って、「やりたいことは決まってるのに、書き方を毎回思い出せない」代表ですよね。

ここは “やりたいこと → 最短スニペット” で並べます。

あと大事な方針を1つだけ:
Streamは1行でやりすぎない。読みにくくなったら、素直にfor文に戻ってOKです(現場はそれで勝ちです)。

重複を消す/並び順を保つ

いつ使う?:Listの重複を消したい(しかも元の順番は残したい)
1行説明LinkedHashSet を使うと「重複なし+順序保持」が一発です。
注意点:Setは要素の重複を許さないので、最初に出た方が残る(後勝ちにしたいなら別ロジック)。

List<String> unique = new ArrayList<>(new LinkedHashSet<>(list));

Streamでやる版(見た目が好きなら):

List<String> unique = list.stream()
        .distinct()
        .toList(); // Java 16+

Java 8〜15なら collect(Collectors.toList()) でOKです:

List<String> unique = list.stream()
        .distinct()
        .collect(Collectors.toList());

フィルタ・変換・集計(Streamの最短例)

いつ使う?:条件で絞る/形を変える/合計や件数を出す
1行説明filtermapcollect を“2〜3行”で止めます。
注意点:途中で「何してるか分からん」になったら、変数に分けるかforへ。

フィルタして変換してListへ:

List<String> names = users.stream()
        .filter(u -> u.isActive())
        .map(User::getName)
        .collect(Collectors.toList());

合計(数値の合計):

int total = items.stream()
        .mapToInt(Item::getPrice)
        .sum();

件数(条件に合う数):

long count = users.stream()
        .filter(User::isActive)
        .count();

グルーピング(例:部署ごとに社員をまとめる):

Map<String, List<User>> byDept = users.stream()
        .collect(Collectors.groupingBy(User::getDepartment));

グルーピングして件数(部署ごとの人数):

Map<String, Long> deptCounts = users.stream()
        .collect(Collectors.groupingBy(User::getDepartment, Collectors.counting()));

Map:キーが無い時のデフォルト/安全な取得

いつ使う?:Mapにキーが無いかも/無いなら0や空を返したい/無いなら作りたい
1行説明getOrDefaultcomputeIfAbsent を覚えると検索回数が激減します。
注意点map.get(k)戻りがnullになり得るので、その前提で扱います(油断するとNPEの入口です)。

デフォルト値で受ける:

int n = counts.getOrDefault(key, 0);

「無ければ作って使う」(集計の鉄板):

map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);

「ある時だけ処理したい」なら Optional で安全に(null回避):

Optional.ofNullable(map.get(key))
        .ifPresent(v -> System.out.println(v));

補足(判断基準):
大きめデータの集計でStreamが読みにくくなったら、素直なforが一番事故りません。
もしMap操作がどうしても多くて標準がしんどい人だけ、Guavaみたいな補助ライブラリを検討する、くらいでOKです(全員に必須ではないです)。

ファイルIO:読み書きの定番(try-with-resources)

ファイル操作って「動くけど地味にミスる」ゾーンですよね。

なので方針はこれで固定します:
基本は Files で短く、ストリーム系は try-with-resourcesで確実に閉じる、文字コードは UTF-8を明示。例外処理をゴリゴリ書き始めると長くなるので、ここでは最小にして、困ったら例外とログに橋渡しします。

1行ずつ読む/全部読む(Files)

いつ使う?:ログやCSVっぽいテキストを読む/設定ファイルを読む
1行説明:小さめなら「全部読む」、大きめなら「1行ずつ」が安全です。
注意点:でかいファイルを readAllLines で全部読むと、メモリが死ぬことがあります。

全部読む(Java 11+ の最短):

Path path = Path.of("data.txt");
String text = Files.readString(path, StandardCharsets.UTF_8);

行で全部読む(小さめ向け):

List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);

1行ずつ読む(大きめ向け:try-with-resources必須):

try (Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) {
    lines.forEach(System.out::println);
}

書き込む(追記・上書き)

いつ使う?:結果をファイルに出したい/ログ的に追記したい
1行説明writeString / write で十分なことが多いです。
注意点:追記は StandardOpenOption.APPEND を忘れると上書きになります。

上書き(Java 11+):

Files.writeString(path, "hello\n", StandardCharsets.UTF_8);

追記:

Files.writeString(
        path,
        "more\n",
        StandardCharsets.UTF_8,
        StandardOpenOption.CREATE,
        StandardOpenOption.APPEND
);

細かく書きたい(大量出力・逐次出力)なら BufferedWriter

try (BufferedWriter w = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
    w.write("line1");
    w.newLine();
}

文字コード(UTF-8)と例外の扱い

いつ使う?:文字化けを避けたい/OSや環境で挙動を揃えたい
1行説明UTF-8を明示して、例外は上に投げるか、ログして判断します。
注意点new FileReader(...) みたいに文字コードを省略すると、環境依存で事故ります。

メソッド側で投げる最短(呼び出し側でまとめて処理したい時):

String read(Path path) throws IOException {
    return Files.readString(path, StandardCharsets.UTF_8);
}

補助メモ:ローカル確認は、まずはOS標準のテキスト表示で十分です(変にツール増やさないのが楽)。
でかいファイルは「全部読む」より「1行ずつ」に寄せる、ここだけ守ると事故が減ります。

例外とログ:ミスしやすい“地味ゾーン”を固める

例外とログって、派手じゃないけど「後から効く」ゾーンです。ここが弱いと、障害対応で “で、何が起きたの?” から始まって地獄になります。方針はこれで固定します:

  • 例外メッセージは 状況がわかる情報を入れる
  • catchは 握りつぶさない(やむを得ないならログ+理由を書く)
  • ログは 漏れて困る情報を書かない(ユーザー向け文章じゃない)

例外メッセージの作り方(情報を入れる)

いつ使う?:失敗したときに「何の処理で」「何を入力に」「何がダメだったか」を残したい
1行説明:例外メッセージはテンプレで作ると、調査が速くなります。
注意点:個人情報・パスワード・トークンなど、漏れて困るものは入れない(IDや件数などに寄せる)。

テンプレ例(最低これだけ入ると強いです):

  • 何をしようとした?(処理名)
  • どのID?(userId / orderId など)
  • 入力の要点は?(件数、範囲、キーなど)
throw new IllegalArgumentException(
        String.format("updateUser failed: userId=%s, reason=empty name", userId)
);

原因となる例外をつなげる(スタックトレースを残す):

try {
    doSomething();
} catch (IOException e) {
    throw new UncheckedIOException(
            String.format("read failed: path=%s", path),
            e
    );
}

例外を握りつぶさない(NG例:空catch)

いつ使う?:つい「とりあえず握るか…」ってなりそうな場面
1行説明:空catchは“失敗を消す”ので、後で絶対困ります。
注意点:どうしても握るなら、握る理由代替動作をセットにします(ログだけでも残す)。

// NG:何もせず握りつぶす(後で原因が追えない)
try {
    save();
} catch (Exception e) {
    // 何もしない
}

やむを得ず続行するなら、最低これ:

try {
    save();
} catch (IOException e) {
    logger.warn("save skipped: path={}, reason={}", path, e.toString());
    // ここで「続行してOKな理由」をコメントで残すとさらに良いです
}

ログ出力の型(info/debug/error)とテンプレ

いつ使う?:後で調査できるように、必要な情報を残したい
1行説明:info=イベント、debug=調査用、error=失敗。テンプレで迷いを減らします。
注意点:ログはユーザー向け文章じゃないです。機密情報は出さない、そして文字列連結で重くしない(プレースホルダ推奨)。

(SLF4J系の {} を想定したテンプレ)

// info:業務イベント(開始・完了・件数など)
logger.info("import start: file={}, size={}", fileName, size);

// debug:調査用(普段はOFFでもOKな情報)
logger.debug("parsed row: rowNo={}, value={}", rowNo, value);

// error:失敗(例外は第2引数で渡すのが定番)
logger.error("import failed: file={}, reason={}", fileName, e.toString(), e);

商品紹介のカテゴリ感だけ触れるなら:
ログ基盤は SLF4J + Logback(OSS) が最小構成で分かりやすいです(Spring触る人は特に)。
例外監視は Sentry みたいなサービスがある、くらい名前だけ知っておけばOKです(深追いは不要です)。

正規表現:最小で使う(やりすぎない)

正規表現って便利なんですが、やりすぎると一気に「読めない暗号」になります。なのでこの章は方針を固定します:

  • 置換は replaceAll(短く済むならこれ)
  • 抽出は Pattern / Matcher(必要なときだけ)
  • 正規表現を使ったら コメントを1行 添える(未来の自分を助けるやつ)

ある文字だけ残す/数字だけ抜く

いつ使う?:入力から「数字だけ」「英数字だけ」みたいに、余計なものを消したい
1行説明replaceAll で「残したい以外を消す」が最短です。
注意点replaceAll の第1引数は 正規表現です(.+ には意味があります)。

数字だけ残す(電話番号っぽいのを作る、とか):

// 数字以外を消して、数字だけ残す
String digits = text.replaceAll("\\D", "");

英数字とアンダースコアだけ残す(ユーザー名っぽい整形):

// [a-zA-Z0-9_] 以外を消す
String safe = text.replaceAll("[^a-zA-Z0-9_]", "");

空白をまとめる(連続スペース→1個):

// 連続する空白を1つにする
String normalized = text.trim().replaceAll("\\s+", " ");

置換・抽出の最短例(Pattern/Matcher)

いつ使う?:置換じゃなくて「一部を取り出したい」(例:メールっぽい文字列、IDっぽい部分)
1行説明Pattern を作って Matcherfind()、取るなら group()
注意点:複雑にしない。分からなくなったら正規表現を諦めて、素直にパースするのもアリです。

メールっぽいものを1個だけ抽出(※ガチの厳密判定ではなく“軽く”です):

// メールっぽい文字列を抽出(簡易)
Pattern p = Pattern.compile("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}");
Matcher m = p.matcher(text);

if (m.find()) {
    String email = m.group();
}

「orderId=12345」みたいな数字だけ抜く:

// "orderId=数字" から数字部分を抽出
Pattern p = Pattern.compile("orderId=(\\d+)");
Matcher m = p.matcher(text);

if (m.find()) {
    String orderId = m.group(1);
}

補助の考え方:正規表現は手元で確認できると安心です。
Webの正規表現テスターみたいなツールがあるので、「合ってるか不安な時は試す」くらいでOKです(本文でリンクは不要、存在だけ知っておけば十分です)。

並列処理:使う前に“条件チェック”

parallelStream()、うまくハマると速いんですが、条件が合わないと 逆に遅くなることも普通にあります。

なので先に結論です:
「速そうだから並列」はNG。使う前にチェックして、ダメそうなら素直に通常stream(or for)にします。

parallelStreamはいつ効く?(合うケース/合わないケース)

いつ使う?:大量データを処理する/1件あたりの処理が重い
1行説明:並列が効くのは「データ量が多い」かつ「処理が重い」かつ「独立している」時です。
注意点:I/O(DB・ファイル・ネットワーク)を並列にすると、別のボトルネックで詰まることがあります。

合うケース(だいたい勝ちやすい)

  • 要素数が多い(目安:数万〜、ただし環境による)
  • 1要素の処理が重い(計算、画像処理、圧縮、暗号化など)
  • 順序がいらない
  • 各要素の処理が独立している(共有状態がない)

合わないケース(だいたい負けやすい)

  • 要素数が少ない(並列化コストが勝つ)
  • 処理が軽い(足し算だけ、文字列ちょい加工、など)
  • 順序が重要(並列にしても結局整列コスト)
  • 共有データを更新する必要がある(次の章でNG例)

最短例(向いてる時だけ):

long count = list.parallelStream()
        .filter(this::heavyCheck)
        .count();

スレッド安全の注意点(共有変数NG)

いつ使う?:parallelStreamで結果を集めたい
1行説明:共有Listに add するみたいな “共有変数更新” は壊れます。
注意点:集めるなら collect を使う(=並列で安全に集約する道具に任せる)。

NG例:共有Listにadd(壊れます)

// NG:共有のListを並列で更新(データ欠け・例外などの原因)
List<String> out = new ArrayList<>();
list.parallelStream().forEach(s -> out.add(s));

OK例:collectで集める

List<String> out = list.parallelStream()
        .map(String::trim)
        .collect(Collectors.toList());

Mapに集計するなら groupingByConcurrent(必要な人だけ。まずは通常のgroupingByでOK):

Map<String, Long> counts = list.parallelStream()
        .collect(Collectors.groupingByConcurrent(s -> s, Collectors.counting()));

商品紹介というより判断基準の話ですが、並列は「標準機能で十分」です。
まずは 測ってから にしてください。計測の世界だとJMHって道具がある、くらい名前だけ知っておけばOKです(ここで深追いはしません)。

テスト:まずは“動く安心”を作るスニペット

テストって、完璧を目指すと重くなるんですが、最低限でも「壊れてない安心」が手に入ると開発がめちゃ楽になります。ここは 小さく・すぐ書ける形を固定します。

まずは JUnitで例外テスト、次に パラメータ化テストの入口。これだけで「毎回手で実行して確認…」が減ります。

JUnitで例外テスト

いつ使う?:不正な入力でちゃんと例外になるか確認したい
1行説明assertThrows で「例外が出ること」をテストします。
注意点:例外の型だけじゃなく、可能なら メッセージも軽く確認すると原因が分かりやすいです(ただし厳密にしすぎない)。

JUnit 5の最短例:

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

class UserServiceTest {

    @Test
    void nameが空なら例外() {
        UserService sut = new UserService();

        IllegalArgumentException e = assertThrows(
                IllegalArgumentException.class,
                () -> sut.createUser("")
        );

        assertTrue(e.getMessage().contains("name"));
    }
}

パラメータ化テストの入口

いつ使う?:同じテストを入力だけ変えて回したい(3ケースくらい)
1行説明@ParameterizedTest@CsvSource で「入力セット」を並べます。
注意点:最初は 3ケースだけでOKです。増やしすぎると読むのがしんどくなります。

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

class PriceTest {

    @ParameterizedTest
    @CsvSource({
        "100, 110",  // 税10%の例
        "0,   0",
        "999, 1098"
    })
    void 税込計算(int base, int expected) {
        assertEquals(expected, Tax.calc(base));
    }
}

おまけ:命名のコツ(1つだけ)

テスト名は迷ったらこれでOKです:

  • 「条件」_「期待する結果」

例:nameが空なら例外()上限超えならfalse() みたいに書くと、後で見返したときに理解が速いです。

商品紹介のカテゴリ感だけ:基本は JUnit で十分です。読みやすさ派なら AssertJ を“好みで”足す、くらいがちょうどいいです(必須ではないです)。

コピペ用チートシート(目次リンク)と検索のコツ

ここまで読んだあなた、もう今日は勝ちです。あとはこの記事を「読み物」で終わらせずに、辞書として運用できる形にして閉じます。

狙いは1つ、次回から「また検索…」を減らすことです。必要なときに、必要な場所へ一瞬で飛べればOKです。

カテゴリ別リンク(探す時間ゼロへ)

使うときは、まず“やりたいこと”で探してください。日本語でざっくり合ってれば辿り着けるように並べます。

  • まず押さえる(基準)
    • 「古い→新しい」置き換え早見表(Date→java.time / try-with-resources など)
  • null対策
    • nullでも安全に取り出す(Optional.ofNullable / orElse / orElseGet
    • 無ければ作る(computeIfAbsent
    • NG:nullチェック地獄/Optional乱用
  • 文字列
    • ループ結合は StringBuilder(NG:ループで +
    • join / split / trim / 空チェック(isBlank代替)
    • String.format"x".equals(s) の安全形
  • 日付時刻(java.time)
    • 今日・今(LocalDate/LocalDateTime/Instant
    • 文字列↔日付(DateTimeFormatter
    • タイムゾーン(ZonedDateTime)とNG例
    • 旧API用:Dateとの変換(橋渡し)
  • List/Set/Map
    • 重複削除+順序保持(LinkedHashSet / distinct
    • Streamの最短(filter/map/sum/count/groupingBy)
    • Mapの安全取得(getOrDefault / computeIfAbsent
  • ファイルIO
    • 全部読む/1行ずつ読む(Files.readString/readAllLines/lines
    • 書く(上書き/追記)
    • UTF-8明示と例外の橋渡し
  • 例外とログ
    • 例外メッセージのテンプレ(処理名・ID・入力要点)
    • NG:空catch
    • ログ(info/debug/error)テンプレ
  • 正規表現
    • 数字だけ残す/英数字だけ残す(replaceAll
    • 抽出(Pattern/Matcher
  • 並列処理
    • parallelStream条件チェック(合う/合わない)
    • 共有変数NG → collectで集める
  • テスト
    • JUnitの例外テスト(assertThrows
    • パラメータ化テスト入口(@CsvSource

実装的には「目次リンク」をちゃんと効かせるために、見出しの文言をこのまま使うのが強いです(検索もしやすくなります)。

“自分用スニペット箱”の作り方(運用ルール)

この記事を最強にするのは、あなたの現場向けに“育てる”ことです。難しいことは不要で、運用ルールを3つだけにします。

  • 保存先を1つに決める
    • 個人なら:GitHub Gist(無料) / Notion(無料〜) / VS Codeスニペット
    • チームなら:社内Wiki / Notion / リポジトリのdocs
  • 追加する時は「いつ使う?/注意点」を1行で添える
    • コードだけ貼ると、半年後に「これ何?」になります。1行でいいので理由を残すのがコスパ最強です。
  • 月1で“古い例を消す”
    • 追記だけだと倉庫がゴミ屋敷化します。月1で「使ってない」「古い書き方」を消すだけで、箱がずっと使えます。

管理カテゴリの目安:

  • IDEの雛形(無料):IntelliJ IDEA Community / Eclipse のライブテンプレート
  • スニペット管理(無料〜):GitHub Gist / Notion / VS Codeスニペット
    これを入れると「探す→コピペ」の速度がさらに上がります。

よくある質問

Q
この記事はJava初心者でも読めますか?
A

はい、読めます。専門用語はなるべく避けていて、「小学生でも流れが分かる」を基準に書いています。ただし、for文やクラスが何か分からない完全初心者さんは、少しだけ基礎を知ってから読むと、さらにスッと入ります。

Q
Javaのバージョンはいくつを想定していますか?
A

目安は Java 8〜17 です。現場でよく使われる範囲に合わせています。
Java 11以降限定の機能(isBlankreadString など)は、代替コードも一緒に載せています

Q
そのままコピペして本当に大丈夫ですか?
A

はい、基本は そのままコピペ前提です。
ただし、クラス名や変数名はサンプルなので、自分のプロジェクト用に名前だけ調整してください。

Q
Optionalはどこまで使うのが正解ですか?
A

「nullかも」を表現したい 戻り値 で使うのが無難です。
フィールドにOptionalを持たせたり、無理やり全部Optionalにするのは、読みづらくなることが多いのでおすすめしていません。

Q
Streamとfor文、どっちを使えばいいですか?
A

迷ったら 読みやすい方でOKです。
この記事ではStreamをよく出しますが、長くなったらfor文に戻すのは正解です。パフォーマンスも保守性も大事です。

Q
parallelStreamは使ったほうが速いですか?
A

条件が合えば速いですが、何も考えずに使うと遅くなることもあります。
データ量が多くて、処理が重くて、共有変数が無いときだけ使う、が安全です。

Q
Dateはもう使っちゃダメですか?
A

新規コードでは、基本 使わない方がいいです。
ただし、古いAPIや外部ライブラリで必要な場合はあるので、この記事では java.timeとの変換スニペットも載せています。

Q
正規表現が苦手です。避けてもいいですか?
A

全然OKです。
この記事でも「最小で使う」方針にしています。読みにくくなるなら、正規表現を使わずに普通の処理で書いたほうが、将来の自分に優しいです。

Q
テストはどこまで書けばいいですか?
A

まずは 例外がちゃんと出るか最低限の正常ケースだけでOKです。
完璧を目指すより、「壊れてない安心」を早く作るほうが、結果的に開発が速くなります。

Q
このスニペット集、どうやって運用するのがおすすめですか?
A

ブックマーク+自分用に少しずつ追加が最強です。
GitHub GistやNotionに「いつ使うか」を1行添えて保存して、月1で古い例を消す。これだけで、検索時間がかなり減ります。

タイトルとURLをコピーしました