【问题标题】:How to center a string using String.format?如何使用 String.format 使字符串居中?
【发布时间】:2011-11-16 15:41:40
【问题描述】:
public class Divers {
  public static void main(String args[]){

     String format = "|%1$-10s|%2$-10s|%3$-20s|\n";
     System.out.format(format, "FirstName", "Init.", "LastName");
     System.out.format(format, "Real", "", "Gagnon");
     System.out.format(format, "John", "D", "Doe");

     String ex[] = { "John", "F.", "Kennedy" };

     System.out.format(String.format(format, (Object[])ex));
  }
}

输出:

|FirstName |Init.     |LastName            |
|Real      |          |Gagnon              |
|John      |D         |Doe                 |
|John      |F.        |Kennedy             |

我希望输出居中。如果我不使用 '-' 标志,输出将向右对齐。

我没有在 API 中找到使文本居中的标志。

This 文章有一些关于格式的信息,但没有关于中心对齐的信息。

【问题讨论】:

标签: java string format string-formatting


【解决方案1】:

我很快就破解了这个。您现在可以在String.format 中使用StringUtils.center(String s, int size)

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class TestCenter {
    @Test
    public void centersString() {
        assertThat(StringUtils.center(null, 0), equalTo(null));
        assertThat(StringUtils.center("foo", 3), is("foo"));
        assertThat(StringUtils.center("foo", -1), is("foo"));
        assertThat(StringUtils.center("moon", 10), is("   moon   "));
        assertThat(StringUtils.center("phone", 14, '*'), is("****phone*****"));
        assertThat(StringUtils.center("India", 6, '-'), is("India-"));
        assertThat(StringUtils.center("Eclipse IDE", 21, '*'), is("*****Eclipse IDE*****"));
    }

    @Test
    public void worksWithFormat() {
        String format = "|%1$-10s|%2$-10s|%3$-20s|\n";
        assertThat(String.format(format, StringUtils.center("FirstName", 10), StringUtils.center("Init.", 10), StringUtils.center("LastName", 20)),
                is("|FirstName |  Init.   |      LastName      |\n"));
    }
}

class StringUtils {

    public static String center(String s, int size) {
        return center(s, size, ' ');
    }

    public static String center(String s, int size, char pad) {
        if (s == null || size <= s.length())
            return s;

        StringBuilder sb = new StringBuilder(size);
        for (int i = 0; i < (size - s.length()) / 2; i++) {
            sb.append(pad);
        }
        sb.append(s);
        while (sb.length() < size) {
            sb.append(pad);
        }
        return sb.toString();
    }
}

【讨论】:

  • 我会坚持使用 apache commons lang 中的 StringUtils,因为使用 maven 很容易集成它
  • pad 参数为String,但如果超过 1 个字符,该方法将无法正常工作。此测试将失败assertEquals("01foo01", StringUtils.center("foo", 6, "0123"));。应该是字符。我会解决的。
【解决方案2】:

https://www.leveluplunch.com/java/examples/center-justify-string/ 处的代码转换为方便的小型单行函数:

public static String centerString (int width, String s) {
    return String.format("%-" + width  + "s", String.format("%" + (s.length() + (width - s.length()) / 2) + "s", s));
}

用法:

public static void main(String[] args){
    String out = centerString(10, "afgb");
    System.out.println(out); //Prints "   afgb   "
}

我认为这是一个非常巧妙的解决方案,值得一提。

【讨论】:

  • 很好的解决方案!你能更详细地解释一下它是如何工作的吗?
【解决方案3】:

这是使用 apache commons lang StringUtils 的答案。

请注意,您必须将 jar 文件添加到构建路径。如果您使用的是 maven,请确保在依赖项中添加 commons lang。

import org.apache.commons.lang.StringUtils;
public class Divers {
  public static void main(String args[]){

    String format = "|%1$-10s|%2$-10s|%3$-20s|\n";
    System.out.format(format, "FirstName", "Init.", "LastName");
    System.out.format(format,StringUtils.center("Real",10),StringUtils.center("",10),StringUtils.center("Gagnon",20);

    System.out.format(String.format(format, (Object[])ex));
  }
}

【讨论】:

  • 这个答案更合适,因为为此目的使用了一个著名的库
  • 同意@PauloOliveira
【解决方案4】:
int spaceSize = n - s.length();
int prefixSize = spaceSize / 2;
int suffixSize = (spaceSize + 1) / 2

从 Java 11 开始的“单线”

return n > s.length()
     ? " ".repeat(prefixSize) + s + " ".repeat(suffixSize)
     : s;

将上述变量内联到一个返回值中我们可以得到:

returnn > s.length() ? " ".repeat((n - s.length()) / 2) + s + " ".repeat((n - s.length() + 1) / 2**)** :s;


从 Java 8 开始

Java 8 没有" ".repeat(10) 方法。所以

  • 只需将 " ".repeat(10) 替换为 Java 8 模拟。见https://stackoverflow.com/a/57514604/601844,和

  • 使用相同的(与 Java 11 ☝️)alg:

      int spaceSize = n - s.length();
      int prefixSize = spaceSize / 2;
      int suffixSize = (spaceSize + 1) / 2
      return n > s.length()
           ? space(prefixSize) + s + space(suffixSize)
           : s;
    
    
    private String space(int spaceSize) {
      return generate(() -> " ").limit(spaceSize).collect(joining());
    }
    

【讨论】:

    【解决方案5】:
    public static String center(String text, int len){
        String out = String.format("%"+len+"s%s%"+len+"s", "",text,"");
        float mid = (out.length()/2);
        float start = mid - (len/2);
        float end = start + len; 
        return out.substring((int)start, (int)end);
    }
    
    public static void main(String[] args) throws Exception{
        // Test
        String s = "abcdefghijklmnopqrstuvwxyz";
        for (int i = 1; i < 200;i++){
            for (int j = 1; j < s.length();j++){
                //center(s.substring(0, j),i);
                System.out.println(center(s.substring(0, j),i));
            }
        }
    }
    

    【讨论】:

    • 很好的答案!可能要考虑将您的方法名称设为小写,大写使其看起来像是一个类而不是方法。
    【解决方案6】:

    这是将字符串置于中心的另一种方式。

    public static void center(String s, int length, CharSequence ch) {
        /* It works as follows
         * String centerString = String.format("|%" + (length - s.length()) + "s", s);
         * centerString = String.format("%" + -length + "s|", centerString);
         * System.out.println(centerString);
         */
    
        String centerString = String.format("%-" + length + "s|", String.format("|%" + (length - s.length()) + "s", s));
        System.out.println(centerString);
    }
    

    【讨论】:

      【解决方案7】:

      我在上面玩了 Mertuarez 的优雅答案,并决定发布我的版本。

      public class CenterString {
      
          public static String center(String text, int len){
              if (len <= text.length())
                  return text.substring(0, len);
              int before = (len - text.length())/2;
              if (before == 0)
                  return String.format("%-" + len + "s", text);
              int rest = len - before;
              return String.format("%" + before + "s%-" + rest + "s", "", text);  
          }
      
          // Test
          public static void main(String[] args) {
              String s = "abcde";
              for (int i = 1; i < 10; i++){
                  int max = Math.min(i,  s.length());
                  for (int j = 1; j <= max; j++){
                      System.out.println(center(s.substring(0, j), i) + "|");
                  }
              }
          }
      }
      

      输出:

      a|
      a |
      ab|
       a |
      ab |
      abc|
       a  |
       ab |
      abc |
      abcd|
        a  |
       ab  |
       abc |
      abcd |
      abcde|
        a   |
        ab  |
       abc  |
       abcd |
      abcde |
         a   |
        ab   |
        abc  |
       abcd  |
       abcde |
         a    |
         ab   |
        abc   |
        abcd  |
       abcde  |
          a    |
         ab    |
         abc   |
        abcd   |
        abcde  | 
      

      与 Mertuarez 代码的实际区别:

      1. 我的先进行数学运算,并一次性制作出最终居中的字符串,而不是先制作太长的字符串,然后从中取出子字符串。我认为它的性能稍微好一些,但我没有对其进行测试。
      2. 对于不能完全居中的文本,我始终将其放在左侧半个字符,而不是将其放在右侧半个字符。
      3. 在文本长度超过指定长度的情况下,我始终返回以原始文本开头为根的指定长度的子字符串。

      【讨论】:

        【解决方案8】:

        这是我如何在 Java 中处理居中列标题的示例:

        public class Test {
            public static void main(String[] args) {
                String[] months = { "January", "February", "March", "April", "May", "June", "July", "August", "September",
                        "October", "November", "December" };
        
                // Find length of longest months value.
                int maxLengthMonth = 0;
                boolean firstValue = true;
                for (String month : months) {
                    maxLengthMonth = (firstValue) ? month.length() : Math.max(maxLengthMonth, month.length());
                    firstValue = false;
                }
        
                // Display months in column header row
                for (String month : months) {
                    StringBuilder columnHeader = new StringBuilder(month);
                    // Add space to front or back of columnHeader
                    boolean addAtEnd = true;
                    while (columnHeader.length() < maxLengthMonth) {
                        if (addAtEnd) {
                            columnHeader.append(" ");
                            addAtEnd = false;
                        } else {
                            columnHeader.insert(0, " ");
                            addAtEnd = true;
                        }
                    }
                    // Display column header with two extra leading spaces for each
                    // column
                    String format = "  %" + Integer.toString(maxLengthMonth) + "s";
                    System.out.printf(format, columnHeader);
                }
                System.out.println();
        
                // Display 10 rows of random numbers
                for (int i = 0; i < 10; i++) {
                    for (String month : months) {
                        double randomValue = Math.random() * 999999;
                        String format = "  %" + Integer.toString(maxLengthMonth) + ".2f";
                        System.out.printf(format, randomValue);
                    }
                    System.out.println();
                }
            }
        }
        

        【讨论】:

          【解决方案9】:

          这是另一个例子。允许您选择在字符串的开头和结尾添加不同数量的填充字符时如何处理中心。

          使用 Java 11 String::repeat

          public class Strings {
          
              public enum Lean {
                  START,
                  END
              }
          
              public static String center(String value, int targetLength, Lean lean) {
                  return center(value, targetLength, lean, ' ');
              }
          
              private static String center(String value, int targetLength, Lean lean, char pad) {
          
                  if (targetLength < 1) {
                      throw new IllegalArgumentException("Cannot center something into less than one space.");
                  }
          
                  int sourceLength = value.length();
          
                  if (sourceLength == targetLength) {
                      return value;
                  }
          
                  int paddingToAdd = targetLength - sourceLength;
                  int half = paddingToAdd / 2;
                  String spad = Character.toString(pad);
                  String padding = spad.repeat(half);
                  String startExtra = "";
                  String endExtra = "";
          
                  if (paddingToAdd % 2 == 1) {
                      if (lean == Lean.START) {
                          endExtra = spad;
                      } else {
                          startExtra = spad;
                      }
                  }
          
                  return padding + startExtra + value + endExtra + padding;
              }
          }
          
          
          
          public class StringsTest {
          
              @Test
              public void centerAbcIn9LeanStart() {
                  doTest(
                          "abc",
                          9,
                          Strings.Lean.START,
                          "   abc   "
                  );
              }
          
              @Test
              public void centerAbcIn9LeanEnd() {
                  doTest(
                          "abc",
                          9,
                          Strings.Lean.END,
                          "   abc   "
                  );
              }
          
              @Test
              public void centerAbcIn10LeanStart() {
                  doTest(
                          "abc",
                          10,
                          Strings.Lean.START,
                          "   abc    "
                  );
              }
          
              @Test
              public void centerAbcIn10LeanEnd() {
                  doTest(
                          "abc",
                          10,
                          Strings.Lean.END,
                          "    abc   "
                  );
              }
          
              @Test
              public void centerAbcdIn9LeanStart() {
                  doTest(
                          "abcd",
                          9,
                          Strings.Lean.START,
                          "  abcd   "
                  );
              }
          
              @Test
              public void centerAbcdIn9LeanEnd() {
                  doTest(
                          "abcd",
                          9,
                          Strings.Lean.END,
                          "   abcd  "
                  );
              }
          
              @Test
              public void centerAbcdIn10LeanStart() {
                  doTest(
                          "abcd",
                          10,
                          Strings.Lean.START,
                          "   abcd   "
                  );
              }
          
              @Test
              public void centerAbcdIn10LeanEnd() {
                  doTest(
                          "abcd",
                          10,
                          Strings.Lean.START,
                          "   abcd   "
                  );
              }
          
              @Test
              public void centerAIn1LeanStart() {
                  doTest(
                          "a",
                          1,
                          Strings.Lean.START,
                          "a"
                  );
              }
          
              @Test
              public void centerAIn1LeanEnd() {
                  doTest(
                          "a",
                          1,
                          Strings.Lean.END,
                          "a"
                  );
              }
          
              @Test
              public void centerAIn2LeanStart() {
                  doTest(
                          "a",
                          2,
                          Strings.Lean.START,
                          "a "
                  );
              }
          
              @Test
              public void centerAIn2LeanEnd() {
                  doTest(
                          "a",
                          2,
                          Strings.Lean.END,
                          " a"
                  );
              }
          
              @Test
              public void centerAIn3LeanStart() {
                  doTest(
                          "a",
                          3,
                          Strings.Lean.START,
                          " a "
                  );
              }
          
              @Test
              public void centerAIn3LeanEnd() {
                  doTest(
                          "a",
                          3,
                          Strings.Lean.END,
                          " a "
                  );
              }
          
              @Test
              public void centerAbIn3LeanStart() {
                  doTest(
                          "ab",
                          3,
                          Strings.Lean.START,
                          "ab "
                  );
              }
          
              @Test
              public void centerAbIn3LeanEnd() {
                  doTest(
                          "ab",
                          3,
                          Strings.Lean.END,
                          " ab"
                  );
              }
          
              public void doTest(String value, int targetLength, Strings.Lean lean, String expected) {
          
                  assertThat(
                          "Test setup error: targetLength != expected.length()",
                          targetLength,
                          equalTo(expected.length()));
          
                  assertThat(
                          "Test setup error: value != expected.trim()",
                          value,
                          equalTo(expected.trim()));
          
                  String actual = Strings.center(value, targetLength, lean);
                  assertThat(actual, equalTo(expected));
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2011-06-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多