มีวิธีง่ายๆในการวาง Strings ใน Java หรือไม่?
ดูเหมือนว่ามีบางสิ่งที่ควรอยู่ใน API คล้าย StringUtil แต่ฉันไม่พบสิ่งใดที่ทำเช่นนี้
มีวิธีง่ายๆในการวาง Strings ใน Java หรือไม่?
ดูเหมือนว่ามีบางสิ่งที่ควรอยู่ใน API คล้าย StringUtil แต่ฉันไม่พบสิ่งใดที่ทำเช่นนี้
คำตอบ:
Apache StringUtils
มีวิธีการหลายวิธี: leftPad
, rightPad
, และcenter
repeat
แต่โปรดทราบว่า - อย่างที่คนอื่น ๆ พูดถึงและแสดงให้เห็นในคำตอบนี้ - String.format()
และFormatter
ชั้นเรียนใน JDK เป็นตัวเลือกที่ดีกว่า ใช้พวกเขามากกว่ารหัสทั่วไป
ตั้งแต่ Java 1.5, String.format()
สามารถใช้ในการซ้าย / ขวาแผ่นสตริงที่กำหนด
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) + "*");
}
และผลลัพธ์คือ:
Howto *
Howto*
1$
เพื่อ? @leo ทำให้คำตอบที่คล้ายกันมากที่ไม่ได้ใช้1$
และเห็นได้ชัดว่ามันมีผลเหมือนกัน มันสร้างความแตกต่างหรือไม่?
แพ็ดดิงถึง 10 ตัวอักษร:
String.format("%10s", "foo").replace(' ', '*');
String.format("%-10s", "bar").replace(' ', '*');
String.format("%10s", "longer than 10 chars").replace(' ', '*');
เอาท์พุท:
*******foo
bar*******
longer*than*10*chars
แสดง '*' สำหรับอักขระของรหัสผ่าน:
String password = "secret123";
String padded = String.format("%"+password.length()+"s", "").replace(' ', '*');
เอาต์พุตมีความยาวเท่ากับสตริงรหัสผ่าน:
secret123
*********
.replace(' ', '*')
ค่อนข้างตั้งใจจะแสดงผลของการขยาย นิพจน์การซ่อนรหัสผ่านไม่มีปัญหานี้อยู่แล้ว ... เพื่อให้ได้คำตอบที่ดีขึ้นเกี่ยวกับการกำหนดสตริงการแพ็ดด้านซ้ายและขวาโดยใช้คุณสมบัติ Java ดั้งเดิมโปรดดูคำตอบอื่นของฉัน
String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")
หรือString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
ในGuavaสิ่งนี้ง่ายมาก:
Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');
บางสิ่งง่าย ๆ :
ค่าควรเป็นสตริง แปลงเป็นสตริงถ้าไม่ใช่ กดไลค์"" + 123
หรือInteger.toString(123)
// let's assume value holds the String we want to pad
String value = "123";
ซับสตริงเริ่มต้นจากดัชนีถ่านความยาวค่าจนถึงความยาวท้ายของเบาะ:
String padded="00000000".substring(value.length()) + value;
// now padded is "00000123"
แม่นยำยิ่งขึ้น
แผ่นขวา:
String padded = value + ("ABCDEFGH".substring(value.length()));
// now padded is "123DEFGH"
แผ่นซ้าย:
String padString = "ABCDEFGH";
String padded = (padString.substring(0, padString.length() - value.length())) + value;
// now padded is "ABCDE123"
org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar)
มีลักษณะที่
แต่อัลกอริทึมนั้นง่ายมาก (แผ่นจนถึงขนาดตัวอักษร):
public String pad(String str, int size, char padChar)
{
StringBuffer padded = new StringBuffer(str);
while (padded.length() < size)
{
padded.append(padChar);
}
return padded.toString();
}
นอกจาก Apache Commons แล้วดูString.format
ว่าควรดูแลช่องว่างภายในที่เรียบง่ายเช่นช่องว่างหรือไม่
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...
str
ดังนั้นสิ่งนี้จึงถูกต้อง
(length - str.length())
เป็น0
? ฟอร์แมตเตอร์โยน a FormatFlagsConversionMismatchException
เมื่อ%0s
เป็นสตริงรูปแบบ
ฉันใช้เวลาสักครู่เพื่อคิดออก กุญแจสำคัญคือการอ่านเอกสารของฟอร์แมตเตอร์
// 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);
ฉันรู้ว่ากระทู้นี้เก่าและคำถามเดิมมีไว้เพื่อแก้ปัญหาที่ง่าย แต่ถ้ามันควรจะเร็วจริง ๆ คุณควรใช้อาร์เรย์ 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;
}
โซลูชันของตัวจัดรูปแบบไม่เหมาะสมที่สุด เพียงแค่สร้างสตริงรูปแบบสร้าง 2 สายใหม่
โซลูชั่นของ apache สามารถปรับปรุงได้โดยการเริ่มต้น sb ด้วยขนาดเป้าหมายเพื่อแทนที่ด้านล่าง
StringBuffer padded = new StringBuffer(str);
กับ
StringBuffer padded = new StringBuffer(pad);
padded.append(value);
จะป้องกันไม่ให้บัฟเฟอร์ภายในของ sb เติบโตขึ้น
StringBuffer
ไม่สามารถเข้าถึงหลายเธรดได้พร้อมกัน (ซึ่งในกรณีนี้เป็นจริง) คุณควรใช้StringBuilder
(ใน JDK1.5 +) เพื่อหลีกเลี่ยงค่าใช้จ่ายในการซิงโครไนซ์
นี่เป็นอีกวิธีในการปัดไปทางขวา:
// 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-------";
ตั้งแต่ Java 11, String.repeat (int) สามารถใช้ในการซ้าย / ขวา pad ของสตริงที่กำหนด
System.out.println("*".repeat(5)+"apple");
System.out.println("apple"+"*".repeat(5));
เอาท์พุท:
*****apple
apple*****
คุณสามารถลดค่าใช้จ่ายต่อการโทรได้โดยเก็บข้อมูลการเติมแทนที่จะสร้างใหม่ทุกครั้ง:
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);
}
}
คุณสามารถกำหนดความยาวผลลัพธ์เป็นพารามิเตอร์ให้กับpad(...)
เมธอดได้ ในกรณีนั้นทำการปรับค่า padding ที่ซ่อนอยู่ในเมธอดนั้นแทนใน constructor
(คำแนะนำ: สำหรับเครดิตเพิ่มเติมให้ใช้ thread-safe! ;-)
คุณสามารถใช้เมธอด StringBuilder ผนวก () และ 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());
งานนี้:
"".format("%1$-" + 9 + "s", "XXX").replaceAll(" ", "0")
มันจะเติมสตริง XXX ของคุณมากถึง 9 Chars ด้วยช่องว่าง หลังจากนั้นช่องว่างทั้งหมดจะถูกแทนที่ด้วย 0 คุณสามารถเปลี่ยนช่องว่างและ 0 เป็นสิ่งที่คุณต้องการ ...
static
เมธอดString.format(…)
แทนการใช้สตริงที่ไม่เหมาะสม การบันทึกอักขระสี่ตัวในซอร์สโค้ดย่อมไม่คุ้มกับการสูญเสียความสามารถในการอ่าน
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 "";
}
ให้ฉันออกคำตอบสำหรับบางกรณีที่คุณต้องให้ padding ซ้าย / ขวา (หรือคำนำหน้า / สตริงหรือช่องว่าง) ก่อนที่คุณจะเชื่อมต่อกับสตริงอื่นและคุณไม่ต้องการทดสอบความยาวหรือเงื่อนไขใด ๆ ถ้า
เหมือนกับคำตอบที่เลือกฉันต้องการStringUtils
Apache ของ Commons แต่ใช้วิธีนี้:
StringUtils.defaultString(StringUtils.leftPad(myString, 1))
อธิบาย:
myString
: สตริงที่ฉันป้อนเข้าอาจเป็นโมฆะStringUtils.leftPad(myString, 1)
: ถ้า string เป็นโมฆะประโยคนี้จะคืนค่า null เช่นกันdefaultString
เพื่อให้สตริงที่ว่างเปล่าเพื่อป้องกันการเชื่อมต่อที่ว่าง@ck 's และ@Marlon Tarak ' s คำตอบเป็นคนเดียวที่จะใช้char[]
ซึ่งสำหรับการใช้งานที่มีหลายสายวิธีการขยายต่อวินาทีเป็นวิธีที่ดีที่สุด อย่างไรก็ตามพวกเขาไม่ได้ใช้ประโยชน์จากการเพิ่มประสิทธิภาพการจัดการอาเรย์ใด ๆ และถูกเขียนทับเล็กน้อยสำหรับรสนิยมของฉัน สามารถทำได้โดยไม่ต้องวนซ้ำเลย
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);
}
วิธีทดสอบอย่างง่าย:
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));
}
ขาออก:
012345678901234567890123456789
cats
cats
cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too long for your own good, buddy
getChars
เพื่อให้String
คัดลอกเนื้อหาโดยตรงในout
อาร์เรย์แทนการโทรตามsource.toCharArray()
System.arraycopy
ฉันยังต้องการพิจารณาลดความซับซ้อนของการดำเนินการเพื่อ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);
; ในขณะที่สิ่งนี้ดูเหมือนว่าfill
จะทำงานได้มากขึ้นจริง ๆ แล้วมันอนุญาตให้ JVM กำจัดค่าเริ่มต้นการเติมศูนย์
java.util.Formatter
จะทำซ้ายและขวา padding ไม่จำเป็นต้องพึ่งพาบุคคลที่สามที่แปลก (คุณต้องการเพิ่มพวกเขาสำหรับสิ่งที่ไม่สำคัญ)
[ฉันได้ละรายละเอียดและทำให้โพสต์นี้เป็น 'ชุมชน wiki' เนื่องจากไม่ใช่สิ่งที่ฉันต้องการ]
การดำเนินการสตริงทั้งหมดมักจะต้องมีประสิทธิภาพมาก - โดยเฉพาะถ้าคุณทำงานกับชุดข้อมูลขนาดใหญ่ ฉันต้องการสิ่งที่รวดเร็วและยืดหยุ่นคล้ายกับสิ่งที่คุณจะได้รับในคำสั่ง plsql pad นอกจากนี้ฉันไม่ต้องการรวม lib ขนาดใหญ่สำหรับสิ่งเล็ก ๆ เพียงหนึ่ง ด้วยการพิจารณาเหล่านี้ไม่มีการแก้ปัญหาเหล่านี้เป็นที่น่าพอใจ นี่คือวิธีแก้ไขปัญหาที่ฉันนำเสนอซึ่งมีผลลัพธ์ที่ดีที่สุดหากใครก็ตามสามารถปรับปรุงได้โปรดเพิ่มความคิดเห็นของคุณ
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;
}
}
ใช้ฟังก์ชั่นนี้
private String leftPadding(String word, int length, char ch) {
return (length > word.length()) ? leftPadding(ch + word, length, ch) : word;
}
วิธีใช้?
leftPadding(month, 2, '0');
เอาท์พุท: 01 02 03 04 .. 11 12
ผู้คนจำนวนมากมีเทคนิคที่น่าสนใจ แต่ฉันชอบที่จะทำให้มันง่ายดังนั้นฉันจะไปกับสิ่งนี้:
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();
}
วิธีง่ายๆที่ไม่มี API ใด ๆจะเป็นดังนี้:
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();
}
Java oneliners ไม่มีไลบรารี่ที่น่าสนใจ
// 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"
Pad Left, จำกัดความยาวของ pad
result = (pad + input).substring(input.length(), input.length() + pad.length());
results: "******" | "**abcd" | "cdefgh"
ขวา Pad จำกัดความยาวของแผ่น
result = (input + pad).substring(0, pad.length());
results: "******" | "abcd**" | "abcdef"
ใช้การสอบถามซ้ำได้อย่างไร โซลูชันที่ระบุด้านล่างสามารถทำงานร่วมกับ 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);
}
}
หมายเหตุ : วิธีการนี้จะผนวกการเติมด้วยการปรับแต่งเล็กน้อยคุณสามารถเติมค่าของแผ่นนำหน้าได้
นี่เป็นเวอร์ชั่นคู่ขนานสำหรับพวกคุณที่มีเงื่อนไข จำกัด :-)
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));
ตัวอย่างการแพ็ดดิ้งใน Guava:
Padding ตัวอย่างใน Apache Commons:
Padding ตัวอย่างใน JDK:
ทางออกที่ง่ายจะเป็น:
package nl;
public class Padder {
public static void main(String[] args) {
String s = "123" ;
System.out.println("#"+(" " + s).substring(s.length())+"#");
}
}