如何在Java中填充字符串?

505

有没有一种简单的方法在Java中填充字符串?

这似乎是一些类似于StringUtil的API应该有的东西,但我找不到任何可以实现这一点的内容。

33个回答

2

Java一行代码,不使用花哨的库。

// 6 characters padding example
String pad = "******";
// testcases for 0, 4, 8 characters
String input = "" | "abcd" | "abcdefgh"

左填充,不限制

result = pad.substring(Math.min(input.length(),pad.length())) + input;
results: "******" | "**abcd" | "abcdefgh"

右侧填充,不限制长度

result = input + pad.substring(Math.min(input.length(),pad.length()));
results: "******" | "abcd**" | "abcdefgh"

向左填充,限制填充长度

result = (pad + input).substring(input.length(), input.length() + pad.length());
results: "******" | "**abcd" | "cdefgh"

向右填充,限制填充长度

result = (input + pad).substring(0, pad.length());
results: "******" | "abcd**" | "abcdef"

2

java.util.Formatter可以进行左右对齐。没有必要添加奇怪的第三方依赖(您会为如此微不足道的事情添加它们吗)。

(我省略了细节并将此帖子设置为“社区wiki”,因为我没有这方面的需求。)


4
我不同意。在任何较大的Java项目中,您通常需要进行大量字符串操作,这时使用Apache Commons Lang可以提高代码的可读性和避免错误。你们都知道像这样的代码:someString.subString(someString.indexOf(startCharacter), someString.lastIndexOf(endCharacter)),而这可以轻松地通过使用StringUtils来避免。 - Bananeweizen

2
您可以使用内置的StringBuilder append()和insert()方法,来对变量字符串长度进行填充:
AbstractStringBuilder append(CharSequence s, int start, int end) ;

例如:
private static final String  MAX_STRING = "                    "; //20 spaces

    Set<StringBuilder> set= new HashSet<StringBuilder>();
    set.add(new StringBuilder("12345678"));
    set.add(new StringBuilder("123456789"));
    set.add(new StringBuilder("1234567811"));
    set.add(new StringBuilder("12345678123"));
    set.add(new StringBuilder("1234567812234"));
    set.add(new StringBuilder("1234567812222"));
    set.add(new StringBuilder("12345678122334"));

    for(StringBuilder padMe: set)
        padMe.append(MAX_STRING, padMe.length(), MAX_STRING.length());

2
很多人有一些非常有趣的技巧,但我喜欢保持简单,所以我选择这个:
public static String padRight(String s, int n, char padding){
    StringBuilder builder = new StringBuilder(s.length() + n);
    builder.append(s);
    for(int i = 0; i < n; i++){
        builder.append(padding);
    }
    return builder.toString();
}

public static String padLeft(String s, int n,  char padding) {
    StringBuilder builder = new StringBuilder(s.length() + n);
    for(int i = 0; i < n; i++){
        builder.append(Character.toString(padding));
    }
    return builder.append(s).toString();
}

public static String pad(String s, int n, char padding){
    StringBuilder pad = new StringBuilder(s.length() + n * 2);
    StringBuilder value = new StringBuilder(n);
    for(int i = 0; i < n; i++){
        pad.append(padding);
    }
    return value.append(pad).append(s).append(pad).toString();
}

2
这样做非常低效,你应该使用 StringBuilder。 - wkarl
既然您已经知道长度,那么在实例化StringBuilder时应该告诉它分配这么多的空间。 - Ariel
@Ariel,你提到这个很有趣,因为今天我刚和另一个人谈论了这个问题,哈哈。 - Aelphaeis
这不是填充,而是简单的连接。您可以使用.repeat()或任何String.format函数。填充函数的整个思想是您提供可变长度的输入,它将返回固定长度的输出。 - Jp Lorandi
@JpLorandi,你可以使用padLeft(text, desiredLength - text.length(), ' ')来完成这个任务。 - Aelphaeis

2

这是一个高效的实用类,用于在Java中进行字符串的左侧填充右侧填充居中填充零填充

package com.example;

/**
 * Utility class for left pad, right pad, center pad and zero fill.
 */
public final class StringPadding {

    public static String left(String string, int length, char fill) {

        if (string.length() < length) {

            char[] chars = string.toCharArray();
            char[] output = new char[length];

            int delta = length - chars.length;

            for (int i = 0; i < length; i++) {
                if (i < delta) {
                    output[i] = fill;
                } else {
                    output[i] = chars[i - delta];
                }
            }

            return new String(output);
        }

        return string;
    }

    public static String right(String string, int length, char fill) {

        if (string.length() < length) {

            char[] chars = string.toCharArray();
            char[] output = new char[length];

            for (int i = 0; i < length; i++) {
                if (i < chars.length) {
                    output[i] = chars[i];
                } else {
                    output[i] = fill;
                }
            }

            return new String(output);
        }

        return string;
    }

    public static String center(String string, int length, char fill) {

        if (string.length() < length) {

            char[] chars = string.toCharArray();

            int delta = length - chars.length;
            int a = (delta % 2 == 0) ? delta / 2 : delta / 2 + 1;
            int b = a + chars.length;

            char[] output = new char[length];
            for (int i = 0; i < length; i++) {
                if (i < a) {
                    output[i] = fill;
                } else if (i < b) {
                    output[i] = chars[i - a];
                } else {
                    output[i] = fill;
                }
            }

            return new String(output);
        }

        return string;
    }

    public static String zerofill(String string, int length) {
        return left(string, length, '0');
    }

    private StringPadding() {
    }

    /**
     * For tests!
     */
    public static void main(String[] args) {

        String string = "123";
        char blank = ' ';

        System.out.println("left pad:    [" + StringPadding.left(string, 10, blank) + "]");
        System.out.println("right pad:   [" + StringPadding.right(string, 10, blank) + "]");
        System.out.println("center pad:  [" + StringPadding.center(string, 10, blank) + "]");
        System.out.println("zero fill:   [" + StringPadding.zerofill(string, 10) + "]");
    }
}

这是输出结果:
left pad:    [       123]
right pad:   [123       ]
center pad:  [    123   ]
zero fill:   [0000000123]

1

另一个使用递归的解决方案。

这个解决方案与所有JDK版本兼容,不需要外部库:

private static String addPadding(final String str, final int desiredLength, final String padBy) {
    String result = str;
    if (str.length() >= desiredLength) {
        return result;
    } else {
        result += padBy;
        return addPadding(result, desiredLength, padBy);
    }
}

注意: 此解决方案将添加填充,稍微调整即可在填充值前缀中使用。


1
“使用递归怎么样?”因为递归往往速度较慢,涉及重复(二次方)字符串分配,并且如果需要足够的步骤来填充字符串,则会导致堆栈溢出。 - ggorlen

0
编写自己的函数可能比其他答案更简单。
private static String padRight(String str, String padChar, int n) {

    String paddedString = str;

    while (paddedString.length() < n) {

        paddedString = padChar + str;

    }

    return paddedString;

}

private static String padLeft(String str, String padChar, int n) {

    String paddedString = str;

    while (paddedString.length() < n) {

        paddedString += padChar;

    }

    return paddedString;

}

2
这非常低效! - rmuller
但这非常简单 - C.B.

0

就我个人而言,我正在寻找一些能够填充空白的东西,然后我决定自己编写代码。它相当简洁,您可以轻松地从中推导出padLeft和padRight。

    /**
     * Pads around a string, both left and right using pad as the template, aligning to the right or left as indicated.
     * @param a the string to pad on both left and right
     * @param pad the template to pad with, it can be of any size
     * @param width the fixed width to output
     * @param alignRight if true, when the input string is of odd length, adds an extra pad char to the left, so values are right aligned
     *                   otherwise add an extra pad char to the right. When the input is of even length no extra chars will be inserted
     * @return the input param a padded around.
     */
    public static String padAround(String a, String pad, int width, boolean alignRight) {
        if (pad.length() == 0)
            throw new IllegalArgumentException("Pad cannot be an empty string!");
        int delta = width - a.length();
        if (delta < 1)
            return a;
        int half = delta / 2;
        int remainder = delta % 2;
        String padding = pad.repeat(((half+remainder)/pad.length()+1)); // repeating the padding to occupy all possible space
        StringBuilder sb = new StringBuilder(width);
//        sb.append( padding.substring(0,half + (alignRight ? 0 : remainder)));
        sb.append(padding, 0, half + (alignRight ? 0 : remainder));
        sb.append(a);
//        sb.append( padding.substring(0,half + (alignRight ? remainder : 0)));
        sb.append(padding, 0, half + (alignRight ? remainder : 0));

        return sb.toString();
    }

虽然它应该相当快,但可能会从这里和那里使用一些final受益。


0

稍微概括一下Eko的答案(Java 11+):

public class StringUtils {
    public static String padLeft(String s, char fill, int padSize) {
        if (padSize < 0) {
            var err = "padSize must be >= 0 (was " + padSize + ")";
            throw new java.lang.IllegalArgumentException(err);
        }

        int repeats = Math.max(0, padSize - s.length());
        return Character.toString(fill).repeat(repeats) + s;
    }

    public static String padRight(String s, char fill, int padSize) {
        if (padSize < 0) {
            var err = "padSize must be >= 0 (was " + padSize + ")";
            throw new java.lang.IllegalArgumentException(err);
        }

        int repeats = Math.max(0, padSize - s.length());
        return s + Character.toString(fill).repeat(repeats);
    }

    public static void main(String[] args) {
        System.out.println(padLeft("", 'x', 5)); // => xxxxx
        System.out.println(padLeft("1", 'x', 5)); // => xxxx1
        System.out.println(padLeft("12", 'x', 5)); // => xxx12
        System.out.println(padLeft("123", 'x', 5)); // => xx123
        System.out.println(padLeft("1234", 'x', 5)); // => x1234
        System.out.println(padLeft("12345", 'x', 5)); // => 12345
        System.out.println(padLeft("123456", 'x', 5)); // => 123456

        System.out.println(padRight("", 'x', 5)); // => xxxxx
        System.out.println(padRight("1", 'x', 5)); // => 1xxxx
        System.out.println(padRight("12", 'x', 5)); // => 12xxx
        System.out.println(padRight("123", 'x', 5)); // => 123xx
        System.out.println(padRight("1234", 'x', 5)); // => 1234x
        System.out.println(padRight("12345", 'x', 5)); // => 12345
        System.out.println(padRight("123456", 'x', 5)); // => 123456

        System.out.println(padRight("1", 'x', -1)); // => throws
    }
}

0

这里有一个并行版本,适用于那些具有非常长字符串的人们 :-)

int width = 100;
String s = "129018";

CharSequence padded = IntStream.range(0,width)
            .parallel()
            .map(i->i-(width-s.length()))
            .map(i->i<0 ? '0' :s.charAt(i))
            .collect(StringBuilder::new, (sb,c)-> sb.append((char)c), (sb1,sb2)->sb1.append(sb2));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接