Bagaimana saya bisa membuat String di Jawa?


432

Apakah ada cara mudah untuk memasang String di Jawa?

Sepertinya ada sesuatu yang harus ada di beberapa StringUtil-like API, tapi saya tidak dapat menemukan apa pun yang melakukan ini.


Pada masalah fungsi apache vs string formatter ada sedikit keraguan bahwa fungsi apache lebih jelas dan mudah dibaca. Membungkus formatter dengan nama fungsi tidak ideal.
Terra Caines

Jawaban:


189

Apache StringUtilsmemiliki beberapa metode: leftPad, rightPad, centerdan repeat.

Tetapi harap dicatat bahwa - seperti yang telah disebutkan dan didemonstrasikan dalam jawaban ini - String.format()dan Formatterkelas - kelas di JDK adalah pilihan yang lebih baik. Gunakan mereka di atas kode milik bersama.


91
java.util.Formatter (dan String.format ()) melakukan ini. Selalu lebih suka JDK daripada pustaka eksternal jika versi JDK melakukan pekerjaan (yang dilakukannya).
cletus

6
Untuk beberapa alasan, sekarang saya lebih suka Guava daripada Apache Commons; jawaban ini menunjukkan bagaimana melakukannya di Guava .
Jonik

1
@Jonik maukah kamu menuliskan beberapa alasanmu? API terlihat hampir sama.
glen3b

3
@ glen3b: Untuk utilitas perorangan, seperti helper padding string ini, benar-benar tidak ada bedanya lib mana yang digunakan. Yang mengatakan, Guava secara keseluruhan lebih modern, lebih bersih dan lebih baik didokumentasikan lib daripada rekan-rekannya di berbagai proyek Apache Commons (Commons Lang, Commons Collections, Commons IO, dll). Ini juga dibangun oleh orang-orang yang benar-benar pintar (Kevin Bourrillion et al), banyak dari mereka yang aktif di SO . Saya sendiri akhirnya mengganti berbagai Apache Commons libs hanya dengan Jambu tahun yang lalu, dan tidak menyesal.
Jonik

3
@ glen3b: Beberapa bacaan lanjutan yang bagus untuk pertanyaan ini .
Jonik

635

Sejak Java 1.5, String.format()dapat digunakan untuk kiri / kanan pad string yang diberikan.

public static String padRight(String s, int n) {
     return String.format("%-" + n + "s", s);  
}

public static String padLeft(String s, int n) {
    return String.format("%" + n + "s", s);  
}

...

public static void main(String args[]) throws Exception {
 System.out.println(padRight("Howto", 20) + "*");
 System.out.println(padLeft("Howto", 20) + "*");
}

Dan hasilnya adalah:

Howto               *
               Howto*

39
Bagaimana jika Anda perlu lpad dengan karakter lain (bukan spasi)? Apakah masih mungkin dengan String.format? Saya tidak dapat membuatnya bekerja ...
Guido

6
AFAIK String.format () tidak dapat melakukan itu tetapi tidak terlalu sulit untuk kode itu, lihat rgagnon.com/javadetails/java-0448.html (contoh 2)
RealHowTo

61
@ Nullw0rm, jika Anda merujuk ke rgagnon.com, ketahuilah bahwa RealHowTo adalah penulis rgagnon.com juga, jadi dia akan mengkredit dirinya sendiri ...
Colin Pickard

3
setidaknya di JVM saya, "#" tidak berfungsi, "-" baik-baik saja. (Hapus saja #). Ini mungkin konsisten dengan dokumentasi formatter, saya tidak tahu; ia mengatakan "'#' '\ u0023' Membutuhkan output menggunakan formulir alternatif. Definisi formulir ditentukan oleh konversi."
gatoatigrado

6
Terima kasih atas jawabannya. Tapi saya ragu, untuk apa 1$? @leo telah membuat jawaban yang sangat mirip yang tidak digunakan 1$dan ternyata memiliki efek yang sama. Apakah itu membuat perbedaan?
Fabrício Matté

257

Padding hingga 10 karakter:

String.format("%10s", "foo").replace(' ', '*');
String.format("%-10s", "bar").replace(' ', '*');
String.format("%10s", "longer than 10 chars").replace(' ', '*');

keluaran:

  *******foo
  bar*******
  longer*than*10*chars

Tampilkan '*' untuk karakter kata sandi:

String password = "secret123";
String padded = String.format("%"+password.length()+"s", "").replace(' ', '*');

output memiliki panjang yang sama dengan string kata sandi:

  secret123
  *********

50
Asalkan kita semua ingat untuk tidak melewati string dengan spasi ...: D
leviathanbadger

4
Saya dengan @ aboveyou00 - ini adalah solusi menghebohkan untuk string dengan spasi, termasuk contoh yang diberikan oleh leo. Solusi untuk melapisi string di sebelah kiri atau kanan tidak boleh mengubah string input seperti yang muncul di output, kecuali padding string input asli menyebabkannya melebihi panjang bantalan yang ditentukan.
Brian Warshaw

3
Akui masalah ruang angkasa. .replace(' ', '*')lebih dimaksudkan untuk menunjukkan efek padding. Ekspresi penyembunyian kata sandi tidak memiliki masalah ini ... Untuk jawaban yang lebih baik tentang menyesuaikan string padding kiri dan kanan menggunakan fitur Java asli, lihat jawaban saya yang lain.
leo

Jika string hanya berisi spasi tunggal dan Anda ingin membalut dengan karakter yang berbeda, Anda dapat menggunakan regex ganti dengan tampilan di belakang / depan: String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")atauString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
Jaroslaw Pawlak


33

Sesuatu yang sederhana:

Nilai harus berupa string. mengubahnya menjadi string, jika tidak. Suka "" + 123atauInteger.toString(123)

// let's assume value holds the String we want to pad
String value = "123";

Substring mulai dari nilai indeks panjang char sampai panjang akhir dari padded:

String padded="00000000".substring(value.length()) + value;

// now padded is "00000123"

Lebih tepat

pad kanan:

String padded = value + ("ABCDEFGH".substring(value.length())); 

// now padded is "123DEFGH"

pad kiri:

String padString = "ABCDEFGH";
String padded = (padString.substring(0, padString.length() - value.length())) + value;

// now padded is "ABCDE123"

24

Lihatlah org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar).

Tetapi algoritma ini sangat sederhana (pad hingga chars ukuran):

public String pad(String str, int size, char padChar)
{
  StringBuffer padded = new StringBuffer(str);
  while (padded.length() < size)
  {
    padded.append(padChar);
  }
  return padded.toString();
}

11
Perhatikan bahwa pada Java 1.5 ada baiknya menggunakan StringBuilder daripada StringBuffer.
Jon Skeet


17
public static String LPad(String str, Integer length, char car) {
  return (str + String.format("%" + length + "s", "").replace(" ", String.valueOf(car))).substring(0, length);
}

public static String RPad(String str, Integer length, char car) {
  return (String.format("%" + length + "s", "").replace(" ", String.valueOf(car)) + str).substring(str.length(), length + str.length());
}

LPad("Hi", 10, 'R') //gives "RRRRRRRRHi"
RPad("Hi", 10, 'R') //gives "HiRRRRRRRR"
RPad("Hi", 10, ' ') //gives "Hi        "
RPad("Hi", 1, ' ')  //gives "H"
//etc...

4
Perhatikan: Anda nama fungsi terbalik; jika Anda menjalankannya Anda akan melihat.
kebiruan

ditambah jika str asli berisi spasi maka ini tidak berfungsi
Steven Shaw

@ SvenvenShaw Jika saya tidak salah, ganti tidak menargetkan yang asli str, jadi ini benar.
mafu

3
Dengan konvensi, Anda tidak boleh menggunakan huruf kapital untuk nama fungsi.
principal-ideal-domain

Apakah ada persyaratan yang hilang untuk mengembalikan string seperti apa (length - str.length())adanya 0? Formatter melempar FormatFlagsConversionMismatchExceptionkapan %0sadalah string format.
Devin Walters

7

Saya butuh waktu beberapa saat untuk mencari tahu. Kunci sebenarnya adalah membaca dokumentasi Formatter itu.

// Get your data from wherever.
final byte[] data = getData();
// Get the digest engine.
final MessageDigest md5= MessageDigest.getInstance("MD5");
// Send your data through it.
md5.update(data);
// Parse the data as a positive BigInteger.
final BigInteger digest = new BigInteger(1,md5.digest());
// Pad the digest with blanks, 32 wide.
String hex = String.format(
    // See: http://download.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html
    // Format: %[argument_index$][flags][width]conversion
    // Conversion: 'x', 'X'  integral    The result is formatted as a hexadecimal integer
    "%1$32x",
    digest
);
// Replace the blank padding with 0s.
hex = hex.replace(" ","0");
System.out.println(hex);

Mengapa membuat akhirnya begitu rumit? Anda bisa saja melakukan String hex = String.format ("% 032x", digest); dan memiliki hasil yang sama persis, hanya tanpa penggantian yang tidak perlu () dan harus menggunakan $ untuk mengakses variabel tertentu (setelah itu hanya ada satu.)
ArtOfWarfare

Titik adil @ArtOfWarfare. Seseorang awalnya meminta nilai hex padding dalam pertanyaan lain, saya melihat bahwa saya memiliki tautan ke dokumentasi formatter. Ini rumit untuk kelengkapan.
Nthalk

6

Saya tahu utas ini agak tua dan pertanyaan awal adalah untuk solusi mudah tetapi jika itu seharusnya sangat cepat, Anda harus menggunakan array char.

public static String pad(String str, int size, char padChar)
{
    if (str.length() < size)
    {
        char[] temp = new char[size];
        int i = 0;

        while (i < str.length())
        {
            temp[i] = str.charAt(i);
            i++;
        }

        while (i < size)
        {
            temp[i] = padChar;
            i++;
        }

        str = new String(temp);
    }

    return str;
}

solusi formatter tidak optimal. hanya membangun string format membuat 2 string baru.

solusi apache dapat ditingkatkan dengan menginisialisasi sb dengan ukuran target jadi ganti di bawah ini

StringBuffer padded = new StringBuffer(str); 

dengan

StringBuffer padded = new StringBuffer(pad); 
padded.append(value);

akan mencegah buffer internal sb tumbuh.


Jika StringBuffertidak dapat diakses oleh banyak utas sekaligus (yang dalam hal ini benar), Anda harus menggunakan StringBuilder(dalam JDK1.5 +) untuk menghindari overhead sinkronisasi.
glen3b

5

Berikut cara lain untuk menyamping ke kanan:

// put the number of spaces, or any character you like, in your paddedString

String paddedString = "--------------------";

String myStringToBePadded = "I like donuts";

myStringToBePadded = myStringToBePadded + paddedString.substring(myStringToBePadded.length());

//result:
myStringToBePadded = "I like donuts-------";

5

Sejak Java 11, String.repeat (int) dapat digunakan untuk kiri / kanan pad string yang diberikan.

System.out.println("*".repeat(5)+"apple");
System.out.println("apple"+"*".repeat(5));

Keluaran:

*****apple
apple*****

1
Jawaban terbaik untuk java 11!
Nagy Attila

4

Anda dapat mengurangi overhead per panggilan dengan mempertahankan data padding, daripada membangunnya kembali setiap kali:

public class RightPadder {

    private int length;
    private String padding;

    public RightPadder(int length, String pad) {
        this.length = length;
        StringBuilder sb = new StringBuilder(pad);
        while (sb.length() < length) {
            sb.append(sb);
        }
        padding = sb.toString();
   }

    public String pad(String s) {
        return (s.length() < length ? s + padding : s).substring(0, length);
    }

}

Sebagai alternatif, Anda bisa menjadikan panjang parameter sebagai pad(...)metode. Dalam hal itu lakukan penyesuaian padding tersembunyi dalam metode itu daripada di konstruktor.

(Petunjuk: Untuk kredit ekstra, buat itu aman dari thread! ;-)


1
Itu aman utas, kecuali untuk publikasi yang tidak aman (menjadikan bidang Anda final, tentu saja). Saya pikir kinerja dapat ditingkatkan dengan melakukan substring sebelum + yang harus diganti dengan concat (anehnya).
Tom Hawtin - tackline

3

Menemukan ini di Dzone

Pad dengan nol:

String.format("|%020d|", 93); // prints: |00000000000000000093|

Ini harus jawabannya, sederhana dan ringkas, tidak perlu menginstal perpustakaan eksternal.
Wong Jia Hau

2

Anda dapat menggunakan metode built in StringBuilder append () dan insert (), untuk mengisi panjang string variabel:

AbstractStringBuilder append(CharSequence s, int start, int end) ;

Sebagai contoh:

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

Ini bekerja:

"".format("%1$-" + 9 + "s", "XXX").replaceAll(" ", "0")

Ini akan mengisi String XXX Anda hingga 9 Chars dengan spasi putih. Setelah itu semua spasi putih akan diganti dengan 0. Anda dapat mengubah spasi putih dan 0 untuk apa pun yang Anda inginkan ...


Anda harus menggunakan staticmetode ini String.format(…)alih-alih menyalahgunakan string kosong. Menyimpan empat karakter dalam kode sumber tentunya tidak sebanding dengan hilangnya keterbacaan.
Holger

2
public static String padLeft(String in, int size, char padChar) {                
    if (in.length() <= size) {
        char[] temp = new char[size];
        /* Llenado Array con el padChar*/
        for(int i =0;i<size;i++){
            temp[i]= padChar;
        }
        int posIniTemp = size-in.length();
        for(int i=0;i<in.length();i++){
            temp[posIniTemp]=in.charAt(i);
            posIniTemp++;
        }            
        return new String(temp);
    }
    return "";
}

2

Mari saya tinggalkan jawaban untuk beberapa kasus yang harus Anda beri bantalan kiri / kanan (atau string atau spasi awalan / akhiran) sebelum Anda menyambung ke string lain dan Anda tidak ingin menguji panjang atau kondisi apa pun.

Sama dengan jawaban yang dipilih, saya lebih suka StringUtilsApache Commons tetapi menggunakan cara ini:

StringUtils.defaultString(StringUtils.leftPad(myString, 1))

Menjelaskan:

  • myString: input string I, bisa nol
  • StringUtils.leftPad(myString, 1): jika string adalah nol, pernyataan ini akan mengembalikan nol juga
  • kemudian gunakan defaultStringuntuk memberikan string kosong untuk mencegah concatenate null

2

@ck 's dan @Marlon Tarak jawaban adalah satu-satunya yang menggunakan char[], yang untuk aplikasi yang memiliki beberapa panggilan untuk metode padding per detik adalah pendekatan terbaik. Namun, mereka tidak memanfaatkan optimasi manipulasi array dan sedikit ditimpa sesuai selera saya; ini bisa dilakukan tanpa loop sama sekali .

public static String pad(String source, char fill, int length, boolean right){
    if(source.length() > length) return source;
    char[] out = new char[length];
    if(right){
        System.arraycopy(source.toCharArray(), 0, out, 0, source.length());
        Arrays.fill(out, source.length(), length, fill);
    }else{
        int sourceOffset = length - source.length();
        System.arraycopy(source.toCharArray(), 0, out, sourceOffset, source.length());
        Arrays.fill(out, 0, sourceOffset, fill);
    }
    return new String(out);
}

Metode pengujian sederhana:

public static void main(String... args){
    System.out.println("012345678901234567890123456789");
    System.out.println(pad("cats", ' ', 30, true));
    System.out.println(pad("cats", ' ', 30, false));
    System.out.println(pad("cats", ' ', 20, false));
    System.out.println(pad("cats", '$', 30, true));
    System.out.println(pad("too long for your own good, buddy", '#', 30, true));
}

Output:

012345678901234567890123456789
cats                          
                          cats
                cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too long for your own good, buddy 

1
Anda dapat menggunakan getCharsuntuk membiarkan Stringsalinan isinya langsung ke dalam outarray, alih-alih memanggil source.toCharArray(), diikuti oleh System.arraycopy. Saya bahkan akan mempertimbangkan untuk menyederhanakan implementasi menjadi char[] out = new char[length]; Arrays.fill(out, 0, length, fill); source.getChars(0, source.length(), out, right? 0: length - source.length()); return new String(out);; sementara ini sepertinya fillakan melakukan lebih banyak pekerjaan, itu benar-benar memungkinkan JVM untuk menghilangkan pengisian nol default.
Holger

1

java.util.Formatterakan melakukan padding kiri dan kanan. Tidak perlu untuk dependensi pihak ketiga yang aneh (Anda ingin menambahkannya untuk sesuatu yang sepele).

[Saya telah meninggalkan detailnya dan menjadikan posting ini 'komunitas wiki' karena ini bukan sesuatu yang saya butuhkan.]


4
Saya tidak setuju. Dalam setiap proyek Java yang lebih besar, Anda biasanya akan melakukan banyak manipulasi String, sehingga peningkatan keterbacaan dan penghindaran kesalahan sangat layak menggunakan Apache Commons Lang. Anda semua tahu kode seperti someString.subString (someString.indexOf (startCharacter), someString.lastIndexOf (endCharacter)), yang dapat dengan mudah dihindari dengan StringUtils.
Bananeweizen

1

Semua operasi string biasanya harus sangat efisien - terutama jika Anda bekerja dengan set data yang besar. Saya menginginkan sesuatu yang cepat dan fleksibel, mirip dengan apa yang akan Anda dapatkan dalam perintah pad plsql. Juga, saya tidak ingin memasukkan lib besar hanya untuk satu hal kecil. Dengan pertimbangan ini tidak ada solusi yang memuaskan. Ini adalah solusi yang saya buat, yang memiliki hasil penilaian terbaik, jika ada yang bisa meningkatkannya, silakan tambahkan komentar Anda.

public static char[] lpad(char[] pStringChar, int pTotalLength, char pPad) {
    if (pStringChar.length < pTotalLength) {
        char[] retChar = new char[pTotalLength];
        int padIdx = pTotalLength - pStringChar.length;
        Arrays.fill(retChar, 0, padIdx, pPad);
        System.arraycopy(pStringChar, 0, retChar, padIdx, pStringChar.length);
        return retChar;
    } else {
        return pStringChar;
    }
}
  • perhatikan itu disebut dengan String.toCharArray () dan hasilnya dapat dikonversi ke String dengan hasil String ((char []) baru). Alasannya adalah, jika Anda menerapkan beberapa operasi, Anda dapat melakukan semuanya pada char [] dan tidak terus mengonversi antar format - di belakang layar, String disimpan sebagai char []. Jika operasi ini termasuk dalam kelas String itu sendiri, itu akan menjadi dua kali lebih efisien - kecepatan dan memori bijaksana.

Ini memang terlihat seperti cara yang paling efisien
David Lilljegren

1

Gunakan fungsi ini.

private String leftPadding(String word, int length, char ch) {
   return (length > word.length()) ? leftPadding(ch + word, length, ch) : word;
}

Cara Penggunaan?

leftPadding(month, 2, '0');

output: 01 02 03 04 .. 11 12


1

Banyak orang memiliki beberapa teknik yang sangat menarik tetapi saya ingin membuatnya tetap sederhana jadi saya ikuti ini:

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
Ini sangat tidak efisien, Anda harus menggunakan StringBuilder
wkarl

Karena Anda sudah mengetahui panjangnya, Anda harus memberi tahu StringBuilder untuk mengalokasikan banyak ruang saat Anda membuat instantiate.
Ariel

@Ririel menarik yang kamu sebutkan itu karena aku baru saja berbicara dengan orang lain tentang itu hari ini lol.
Aelphaeis

0

Solusi sederhana tanpa API adalah sebagai berikut:

public String pad(String num, int len){
    if(len-num.length() <=0) return num;
    StringBuffer sb = new StringBuffer();
    for(i=0; i<(len-num.length()); i++){
        sb.append("0");
    }
    sb.append(num);
    return sb.toString();
}

0

Oneliners Java, tidak ada perpustakaan mewah.

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

Pad Kiri, jangan batasi

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

Pad Kanan, jangan membatasi

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

Pad Kiri, batas ke panjang pad

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

Pad Kanan, batasi panjang pad

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

0

Bagaimana kalau menggunakan rekursi? Solusi yang diberikan di bawah ini kompatibel dengan semua versi JDK dan tidak ada perpustakaan eksternal yang diperlukan :)

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);
        }
    }

CATATAN : Solusi ini akan menambahkan padding, dengan sedikit perubahan Anda dapat awalan nilai pad.


0

Inilah versi paralelnya bagi Anda yang memiliki string sangat panjang :-)

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));

0

-1

Solusi sederhana adalah:

package nl;
public class Padder {
    public static void main(String[] args) {
        String s = "123" ;
        System.out.println("#"+("     " + s).substring(s.length())+"#");
    }
}

-1

Bagaimana ini

String "hello" dan padding yang dibutuhkan adalah 15 dengan "0" pad kiri

String ax="Hello";
while(ax.length() < 15) ax="0"+ax;

10
yang ini menghasilkan hingga 15 string baru.
claj

@claj Ya, tapi ini .
ruffin
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.