Java Tips | 文字列処理:中央寄せ

Java Java
スポンサーリンク

中央寄せは「タイトルや見出しを“きれいに見せる”」ための技

左寄せ・右寄せは「読みやすさ」「桁そろえ」のためのテクニックでしたが、
中央寄せ(センタリング) はどちらかというと「見た目のバランス」を整えるための技です。

画面タイトル、レポートの見出し、区切り線の中のラベルなどで、
文字列を真ん中に置くだけで、ぐっと“ちゃんとしている感”が出ます。

========== Report ==========
        売上集計        
============================

この「真ん中に置く」を、機械的に・再現性高くやるのが中央寄せユーティリティの役割です。


中央寄せの考え方:「左右のスペースをどう分けるか」

「全体幅」と「文字列の長さ」の差をどう割るか

中央寄せは、次の3つで決まります。

全体の幅(width)
文字列の長さ(len)
左右にどれだけスペースを入れるか

例えば、幅 10 の枠に "ABC" を中央寄せしたいとします。

幅 10
文字列長 3
余り = 10 – 3 = 7

この 7 を「左側のスペース」と「右側のスペース」に分ければよいわけです。

左 3、右 4 にするか。
左 4、右 3 にするか。

どちらも「だいたい真ん中」ですが、
実装としては「余りを2で割って、左に floor(切り捨て)、右に残りを全部」というのが素直です。


実装:スペースで中央寄せするユーティリティ

左右のスペース数をきちんと計算する

まずは、指定した幅の中で、スペースを使って中央寄せする基本ユーティリティを作ります。

public final class Align {

    private Align() {}

    public static String center(String text, int width) {
        if (text == null) {
            text = "";
        }
        int len = text.length();
        if (len >= width) {
            return text;
        }
        int spaceTotal = width - len;
        int leftSpaces = spaceTotal / 2;          // 切り捨て
        int rightSpaces = spaceTotal - leftSpaces; // 残り全部

        StringBuilder sb = new StringBuilder(width);
        for (int i = 0; i < leftSpaces; i++) {
            sb.append(' ');
        }
        sb.append(text);
        for (int i = 0; i < rightSpaces; i++) {
            sb.append(' ');
        }
        return sb.toString();
    }
}
Java

使い方はこうなります。

System.out.println("[" + Align.center("ABC", 10) + "]");
// [   ABC    ]
System.out.println("[" + Align.center("タイトル", 12) + "]");
// [   タイトル    ]
System.out.println("[" + Align.center(null, 8) + "]");
// [        ]
System.out.println("[" + Align.center("とても長い文字列", 5) + "]");
// [とても長い文字列]
Java

ここで深掘りしたい重要ポイントは三つです。

一つ目は、「余りのスペース数を左右に分けている」ことです。
spaceTotal = width - lenleftSpacesrightSpaces に分割し、
左に spaceTotal / 2、右に残り全部を割り当てています。
これにより、「1文字ぶん左右差が出る」ケースでも、必ず全体幅がぴったり width になります。

二つ目は、「長さが足りないときだけスペースを追加し、長すぎるときはそのまま返している」ことです。
中央寄せは「見た目のため」のことが多いので、長すぎる文字列を無理に切らず、そのまま表示する設計にしています。
ここは要件によって、「長すぎるときは切る」「…を付ける」などに変えても構いません。

三つ目は、「null を空文字として扱っている」ことです。
null が来ても落ちずに、指定幅ぶんスペースだけの文字列を返します。
レポートのタイトルなどで「タイトルがない場合は空欄」という仕様にしやすくなります。


例題:レポートのタイトル行を中央寄せする

区切り線と組み合わせて「それっぽい」見た目にする

レポートやログのヘッダで、タイトルを中央寄せすると、
それだけで「ちゃんとしたレポート感」が出ます。

public final class ReportHeader {

    private ReportHeader() {}

    public static String buildHeader(String title, int width) {
        String line = repeat('=', width);
        String centered = Align.center(title, width);
        return line + System.lineSeparator()
             + centered + System.lineSeparator()
             + line;
    }

    private static String repeat(char ch, int count) {
        StringBuilder sb = new StringBuilder(count);
        for (int i = 0; i < count; i++) {
            sb.append(ch);
        }
        return sb.toString();
    }
}
Java

使い方はこうです。

System.out.println(ReportHeader.buildHeader("売上集計レポート", 30));
Java

出力イメージはこんな感じです。

==============================
        売上集計レポート        
==============================

ここでのポイントは、「中央寄せは“単体で使う”というより、区切り線や枠と組み合わせて使うと効果が大きい」ことです。
Align.center 自体は単純なスペース計算ですが、
repeat('=', width) と組み合わせることで、「タイトル付きの枠」という分かりやすい表現になります。


例題:メニューやダイアログのタイトルを中央寄せする

コンソールアプリでも“ちょっとした気遣い”になる

コンソールベースのツールやバッチでも、
メニューやダイアログ風の表示を中央寄せすると、ユーザー体験が少し良くなります。

public final class ConsoleUi {

    private ConsoleUi() {}

    public static void showMenu(String title) {
        int width = 40;
        String line = repeat('-', width);
        System.out.println(line);
        System.out.println(Align.center(title, width));
        System.out.println(line);
        System.out.println("1) 実行");
        System.out.println("2) 終了");
        System.out.println(line);
    }

    private static String repeat(char ch, int count) {
        StringBuilder sb = new StringBuilder(count);
        for (int i = 0; i < count; i++) {
            sb.append(ch);
        }
        return sb.toString();
    }
}
Java

使い方はこうです。

ConsoleUi.showMenu("メインメニュー");
Java

出力イメージはこんな感じです。

----------------------------------------
               メインメニュー           
----------------------------------------
1) 実行
2) 終了
----------------------------------------

ここでのポイントは、「中央寄せは“情報量”ではなく“印象”を整えるための技」ということです。
処理内容は何も変わりませんが、タイトルが真ん中にあるだけで、
「雑なツール」から「ちゃんと作られたツール」に一歩近づきます。


例題:中央寄せと全角・半角の“ズレ”問題

「見た目の幅」と「文字列長」が一致しないことを知っておく

ここまでの実装は、text.length() を使って「文字数ベース」で中央寄せしています。
しかし、日本語(全角文字)が混ざると、「見た目の幅」と「文字数」が一致しないことがあります。

例えば、"ABC" は長さ 3、"山田" も長さ 2 ですが、
コンソール上では "山田" のほうが横幅が広く表示されます。

そのため、「見た目まで完全に中央にしたい」場合は、
全角を2文字分としてカウントするような「表示幅計算」が必要になります。

ざっくりした例を挙げると、こんなイメージです。

public static int displayWidth(String text) {
    if (text == null) {
        return 0;
    }
    int width = 0;
    for (int i = 0; i < text.length(); i++) {
        char c = text.charAt(i);
        // 超ざっくり:ASCII は1、それ以外は2とみなす
        if (c <= 0x7F) {
            width += 1;
        } else {
            width += 2;
        }
    }
    return width;
}
Java

これを使って、「表示幅ベースの中央寄せ」を作ることもできます。
ただし、これはフォントや環境によっても変わるので、
「そこまで厳密にやるかどうか」はプロジェクトの要求次第です。

ここで大事なのは、「中央寄せを“文字数ベースでやるのか”“表示幅ベースでやるのか”を意識して選ぶ」ことです。
業務バッチのログ程度なら文字数ベースで十分なことが多く、
帳票や印刷物レベルで見た目をきっちり合わせたいなら、表示幅ベースを検討する価値があります。


まとめ:中央寄せユーティリティで身につけたい感覚

中央寄せは、「情報を変えずに“見た目のバランス”だけを整える」ためのテクニックであり、
実装としては「余りのスペースを左右に分けて埋める」というシンプルな計算です。

押さえておきたい感覚は、まず「全体幅 − 文字列長 = 余り」を左右にどう分けるか、という発想。
次に、「長すぎる文字列や null の扱いを決めて、Align.center のようなユーティリティにルールごと閉じ込める」こと。
そして、「レポートヘッダ、メニュータイトル、区切り線付きのラベルなど、“枠”と組み合わせて使うと効果が大きい」という感覚です。

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