キャメルケース変換は「バラバラな単語を“Java っぽい名前”にそろえる」技
業務システムを書いていると、こんな文字列がよく出てきます。
user_nameUSER_NAMEuser-nameuser name
人間から見れば全部「ユーザー名」ですが、Java の世界では userName のような「キャメルケース(camelCase)」で書くのが一般的です。
外部システムやDBから来た「スネークケース」「ケバブケース」「スペース区切り」の文字列を、
Java のフィールド名・メソッド名・DTO のプロパティ名として扱いやすい形に変換する――それがキャメルケース変換ユーティリティの役割です。
ここでは、「キャメルケースって何?」から始めて、実務で使える変換ユーティリティを一緒に組み立てていきます。
キャメルケースの種類をざっくり整理する
lowerCamelCase と UpperCamelCase の違い
キャメルケースには、ざっくり二種類あります。
userName のように、先頭が小文字で始まり、単語の区切りごとに先頭を大文字にする形。
これは「lowerCamelCase(ローワーキャメルケース)」と呼ばれ、Java のフィールド名・メソッド名でよく使われます。
UserName のように、先頭も大文字で始まる形。
これは「UpperCamelCase(アッパーキャメルケース)」または「PascalCase」と呼ばれ、クラス名などでよく使われます。
今回のユーティリティでは、
「スネークケースなどの“単語が区切られた文字列”」を、lowerCamelCase と UpperCamelCase のどちらにも変換できるようにしておくと実務で便利です。
基本方針:「単語に分解してから、組み立て直す」
いきなり変換しようとしないで「分解→整形→連結」
キャメルケース変換で一番大事なのは、いきなり文字列をゴリゴリ書き換えようとしないことです。
やるべきことはシンプルで、次の三段階に分けられます。
文字列を「単語」に分解する(区切り文字で split するイメージ)。
各単語を「全部小文字にする」「先頭だけ大文字にする」など、ルールに従って整形する。
整形した単語を、キャメルケースのルールに従って連結する。
この「分解→整形→連結」という流れをユーティリティとして固定しておくと、
スネークケースでもケバブケースでも、スペース区切りでも、同じパターンで処理できるようになります。
実装ステップ1:単語に分解するユーティリティ
区切り文字を正規表現でまとめて扱う
まずは、「単語に分解する」部分を作ります。
スネークケース(user_name)、ケバブケース(user-name)、スペース区切り(user name)などをまとめて扱いたいので、_ や - やスペースなどを「区切り文字」として一括で split します。
import java.util.ArrayList;
import java.util.List;
public final class Words {
private Words() {}
public static List<String> splitToWords(String text) {
List<String> result = new ArrayList<>();
if (text == null || text.isEmpty()) {
return result;
}
String[] parts = text.split("[_\\-\\s]+");
for (String p : parts) {
if (!p.isEmpty()) {
result.add(p);
}
}
return result;
}
}
Java使い方のイメージはこうです。
System.out.println(Words.splitToWords("user_name")); // [user, name]
System.out.println(Words.splitToWords("USER-NAME")); // [USER, NAME]
System.out.println(Words.splitToWords("user name id")); // [user, name, id]
Javaここで深掘りしたい重要ポイントは、「“区切り文字の扱い”を一箇所に閉じ込めている」ことです。[_\\-\\s]+ という正規表現で、「アンダースコア」「ハイフン」「空白文字(スペース・タブなど)」をまとめて区切りとして扱っています。
あとから「ドットも区切りにしたい」「スラッシュも区切りにしたい」となっても、このメソッドだけ直せば済みます。
実装ステップ2:lowerCamelCase に変換する
先頭だけ小文字、それ以外の単語は先頭大文字+残り小文字
次に、「分解された単語のリスト」を lowerCamelCase に組み立てるメソッドを作ります。
import java.util.List;
import java.util.Locale;
public final class CamelCases {
private CamelCases() {}
public static String toLowerCamel(String text) {
List<String> words = Words.splitToWords(text);
if (words.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
String first = words.get(0).toLowerCase(Locale.ROOT);
sb.append(first);
for (int i = 1; i < words.size(); i++) {
String w = words.get(i);
if (w.isEmpty()) {
continue;
}
String lower = w.toLowerCase(Locale.ROOT);
String camel = Character.toUpperCase(lower.charAt(0)) + lower.substring(1);
sb.append(camel);
}
return sb.toString();
}
}
Java使い方はこうです。
System.out.println(CamelCases.toLowerCamel("user_name")); // userName
System.out.println(CamelCases.toLowerCamel("USER_NAME")); // userName
System.out.println(CamelCases.toLowerCamel("user-name-id")); // userNameId
System.out.println(CamelCases.toLowerCamel(" user name ")); // userName
Javaここで深掘りしたい重要ポイントは三つあります。
一つ目は、「最初の単語だけは全部小文字にして、そのまま先頭に置く」ことです。
これが userName の「user」の部分にあたります。
二つ目は、「2単語目以降は、“全部小文字にしたうえで、先頭だけ大文字にする”」ことです。NAME や Name や name が来ても、最終的には Name になります。
三つ目は、「ロケールを明示して toLowerCase(Locale.ROOT) を使っている」ことです。
大文字・小文字変換はロケール依存の罠があるので、英字コードを扱うときは Locale.ROOT を指定するクセをつけておくと安全です。
実装ステップ3:UpperCamelCase に変換する
すべての単語の先頭を大文字にする
クラス名などで使う UpperCamelCase も、ほぼ同じパターンで書けます。
import java.util.List;
import java.util.Locale;
public final class CamelCases {
private CamelCases() {}
public static String toUpperCamel(String text) {
List<String> words = Words.splitToWords(text);
if (words.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
for (String w : words) {
if (w.isEmpty()) {
continue;
}
String lower = w.toLowerCase(Locale.ROOT);
String camel = Character.toUpperCase(lower.charAt(0)) + lower.substring(1);
sb.append(camel);
}
return sb.toString();
}
}
Java使い方はこうです。
System.out.println(CamelCases.toUpperCamel("user_name")); // UserName
System.out.println(CamelCases.toUpperCamel("USER-NAME")); // UserName
System.out.println(CamelCases.toUpperCamel("user name id")); // UserNameId
Javaここでのポイントは、「lowerCamel と UpperCamel の違いは“最初の単語を小文字にするかどうかだけ”」ということです。
実装を見比べると、toLowerCamel では最初の単語だけ特別扱いしているのに対し、toUpperCamel ではすべての単語を同じルールで処理しています。
この「最初の単語だけ特別扱い」という感覚を持っておくと、
キャメルケース変換の実装が頭の中でスッと整理されます。
例題:DB カラム名(スネークケース)を DTO のフィールド名に変換する
user_name → userName を自動でやりたい
実務でよくあるのが、「DB のカラム名は user_name だけど、Java のフィールド名は userName にしたい」というケースです。
マッピングライブラリを使う場合でも、「名前変換ルール」を自前で書く場面はよくあります。
public final class ColumnNameMapper {
private ColumnNameMapper() {}
public static String columnToField(String columnName) {
return CamelCases.toLowerCamel(columnName);
}
}
Java使い方はこうです。
System.out.println(ColumnNameMapper.columnToField("user_name")); // userName
System.out.println(ColumnNameMapper.columnToField("created_at")); // createdAt
System.out.println(ColumnNameMapper.columnToField("USER_ID")); // userId
Javaここでのポイントは、「“DB カラム名→フィールド名”という文脈をメソッド名に刻んでいる」ことです。
中身は単に toLowerCamel を呼んでいるだけですが、columnToField という名前がついているだけで、「これはDBとJavaの橋渡しなんだな」と一目で分かります。
例題:JSON のキー名(スネークケース)を Java のクラス名に変換する
user_profile → UserProfile のようなクラス名を作る
コード生成ツールや簡易スクリプトで、「JSON のキーからクラス名を作りたい」ということもあります。
public final class JsonNameMapper {
private JsonNameMapper() {}
public static String keyToClassName(String key) {
return CamelCases.toUpperCamel(key);
}
}
Java使い方はこうです。
System.out.println(JsonNameMapper.keyToClassName("user_profile")); // UserProfile
System.out.println(JsonNameMapper.keyToClassName("order_item")); // OrderItem
Javaここでのポイントは、「UpperCamelCase は“型名・クラス名”と相性がいい」ということです。toUpperCamel を「クラス名用」として意識しておくと、
「この名前はクラス名なのか、フィールド名なのか」が頭の中で整理しやすくなります。
エッジケースと設計のポイント
すでにキャメルケースっぽい文字列が来たらどうするか
例えば、入力がすでに userName だった場合、toLowerCamel("userName") はどう振る舞うべきか。
今の実装だと、Words.splitToWords は区切り文字でしか分割しないので、["userName"] という1単語扱いになります。
その結果、toLowerCamel はほぼそのまま userName を返します。
これは、「“すでにキャメルケースっぽいものは壊さない”」という意味で、実務的には悪くない挙動です。
もし「大文字と小文字の境目でも分割したい」という要件が出てきたら、Words.splitToWords を拡張して、「userName → user と Name に分ける」ようなロジックを足すこともできます。
数字や記号を含む場合の扱い
user_id2 や version_1_0 のように数字が混ざるケースもあります。
今の実装では、数字はそのまま単語の一部として扱われるので、
user_id2 → userId2version_1_0 → version10
のような結果になります。
ここをどうするかは、プロジェクトのルール次第です。
「version_1_0 は version1_0 のままがいい」なら、
区切り文字の定義や、数字の扱いを Words.splitToWords 側で調整していくことになります。
大事なのは、「キャメルケース変換は“万能変換”ではなく、“自分たちのプロジェクトでの命名ルールをコードに落とし込んだもの”だと捉える」ことです。
まとめ:キャメルケース変換ユーティリティで身につけたい感覚
キャメルケース変換は、「外の世界のバラバラな名前(user_name, USER-NAME, user name)を、Java の世界の名前(userName, UserName)にそろえる」ための技です。
押さえておきたい感覚は、まず「分解→整形→連結」という三段階で考えること。
次に、「区切り文字の扱いを Words.splitToWords のような一箇所に閉じ込めておき、スネーク・ケバブ・スペース区切りをまとめて処理する」こと。
そして、「toLowerCamel と toUpperCamel を用意し、DB カラム名→フィールド名、JSON キー→クラス名など、文脈ごとの変換を薄いラッパーメソッドとして名前付きにする」ことです。
もしあなたのコードのどこかに、replace("_", "") しながら手作業で大文字・小文字をいじっている箇所があるなら、
それを題材にして、ここで作った Words と CamelCases、ColumnNameMapper や JsonNameMapper のようなユーティリティに置き換えてみてください。
それだけで、「読みやすくて、再利用できて、命名ルールがコードとして生きている」文字列処理に、一段レベルアップできます。
