Có một số cách dễ dàng để đệm Chuỗi trong Java?
Có vẻ như một cái gì đó nên có trong một số API giống như StringUtil, nhưng tôi không thể tìm thấy bất cứ thứ gì làm được điều này.
Có một số cách dễ dàng để đệm Chuỗi trong Java?
Có vẻ như một cái gì đó nên có trong một số API giống như StringUtil, nhưng tôi không thể tìm thấy bất cứ thứ gì làm được điều này.
Câu trả lời:
Apache StringUtils
có một số phương pháp: leftPad
, rightPad
, center
và repeat
.
Nhưng xin lưu ý rằng - như những người khác đã đề cập và thể hiện trong câu trả lời này - String.format()
và các Formatter
lớp trong JDK là các tùy chọn tốt hơn. Sử dụng chúng trên mã commons.
Vì Java 1.5, String.format()
có thể được sử dụng để đệm trái / phải một chuỗi nhất định.
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) + "*");
}
Và đầu ra là:
Howto *
Howto*
1$
cho? @leo đã đưa ra một câu trả lời rất giống nhau mà không sử dụng 1$
và rõ ràng nó có tác dụng tương tự. Liệu nó có làm cho một sự khác biệt?
Đệm đến 10 ký tự:
String.format("%10s", "foo").replace(' ', '*');
String.format("%-10s", "bar").replace(' ', '*');
String.format("%10s", "longer than 10 chars").replace(' ', '*');
đầu ra:
*******foo
bar*******
longer*than*10*chars
Hiển thị '*' cho các ký tự của mật khẩu:
String password = "secret123";
String padded = String.format("%"+password.length()+"s", "").replace(' ', '*');
đầu ra có cùng độ dài với chuỗi mật khẩu:
secret123
*********
.replace(' ', '*')
đã được dự định để hiển thị hiệu quả của đệm. Biểu thức ẩn mật khẩu dù sao cũng không có vấn đề này ... Để có câu trả lời tốt hơn về việc tùy chỉnh chuỗi đệm trái và phải bằng tính năng Java gốc, hãy xem câu trả lời khác của tôi.
String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")
hoặcString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
Ở ổi , điều này thật dễ dàng:
Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');
Một cái gì đó đơn giản:
Giá trị phải là một chuỗi. chuyển đổi nó thành chuỗi, nếu không. Thích "" + 123
hoặcInteger.toString(123)
// let's assume value holds the String we want to pad
String value = "123";
Chuỗi con bắt đầu từ chỉ số char chiều dài giá trị cho đến khi hết chiều dài của phần đệm:
String padded="00000000".substring(value.length()) + value;
// now padded is "00000123"
Chính xác hơn
đệm phải:
String padded = value + ("ABCDEFGH".substring(value.length()));
// now padded is "123DEFGH"
đệm bên trái:
String padString = "ABCDEFGH";
String padded = (padString.substring(0, padString.length() - value.length())) + value;
// now padded is "ABCDE123"
Có một cái nhìn vào org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar)
.
Nhưng thuật toán rất đơn giản (pad phải lên tới kích thước ký tự):
public String pad(String str, int size, char padChar)
{
StringBuffer padded = new StringBuffer(str);
while (padded.length() < size)
{
padded.append(padChar);
}
return padded.toString();
}
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
, vì vậy điều này là chính xác.
(length - str.length())
là 0
? Trình định dạng ném một FormatFlagsConversionMismatchException
khi %0s
là chuỗi định dạng.
Điều này làm tôi mất một chút thời gian để tìm ra. Chìa khóa thực sự là đọc tài liệu Formatter đó.
// 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);
Tôi biết chủ đề này là loại cũ và câu hỏi ban đầu là một giải pháp dễ dàng nhưng nếu nó được cho là rất nhanh, bạn nên sử dụng một mảng 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;
}
các giải pháp định dạng là không tối ưu. chỉ cần xây dựng chuỗi định dạng sẽ tạo ra 2 chuỗi mới.
Giải pháp của apache có thể được cải thiện bằng cách khởi tạo sb với kích thước đích để thay thế bên dưới
StringBuffer padded = new StringBuffer(str);
với
StringBuffer padded = new StringBuffer(pad);
padded.append(value);
sẽ ngăn chặn bộ đệm nội bộ của sb phát triển.
StringBuffer
không thể truy cập nhiều luồng cùng một lúc (trong trường hợp này là đúng), bạn nên sử dụng một StringBuilder
(trong JDK1.5 +) để tránh chi phí đồng bộ hóa.
Đây là một cách khác để đệm sang phải:
// 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-------";
Vì Java 11, String.repeat (int) có thể được sử dụng để đệm trái / phải một chuỗi đã cho.
System.out.println("*".repeat(5)+"apple");
System.out.println("apple"+"*".repeat(5));
Đầu ra:
*****apple
apple*****
Bạn có thể giảm chi phí cho mỗi cuộc gọi bằng cách giữ lại dữ liệu đệm, thay vì xây dựng lại mỗi lần:
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);
}
}
Thay vào đó, bạn có thể đặt độ dài kết quả làm tham số cho pad(...)
phương thức. Trong trường hợp đó, điều chỉnh phần đệm ẩn trong phương thức đó thay vì trong hàm tạo.
(Gợi ý: Để có thêm tín dụng, hãy làm cho nó an toàn theo chủ đề! ;-)
Tìm thấy cái này trên Dzone
Pad với số không:
String.format("|%020d|", 93); // prints: |00000000000000000093|
bạn có thể sử dụng các phương thức append () và insert () được xây dựng trong StringBuilder để đệm các độ dài chuỗi thay đổi:
AbstractStringBuilder append(CharSequence s, int start, int end) ;
Ví dụ:
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());
Những công việc này:
"".format("%1$-" + 9 + "s", "XXX").replaceAll(" ", "0")
Nó sẽ lấp đầy Chuỗi XXX của bạn lên đến 9 Chars bằng một khoảng trắng. Sau đó, tất cả các khoảng trắng sẽ được thay thế bằng 0. Bạn có thể thay đổi khoảng trắng và 0 thành bất cứ thứ gì bạn muốn ...
static
phương thức String.format(…)
thay vì lạm dụng một chuỗi rỗng. Lưu bốn ký tự trong mã nguồn chắc chắn không đáng để mất khả năng đọc.
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 "";
}
Hãy để tôi trả lời cho một số trường hợp bạn cần cung cấp phần đệm trái / phải (hoặc chuỗi tiền tố / hậu tố hoặc dấu cách) trước khi bạn nối với một chuỗi khác và bạn không muốn kiểm tra độ dài hoặc bất kỳ điều kiện nào.
Tương tự với câu trả lời đã chọn, tôi thích StringUtils
Apache Commons hơn nhưng sử dụng cách này:
StringUtils.defaultString(StringUtils.leftPad(myString, 1))
Giải thích:
myString
: chuỗi tôi nhập, có thể là nullStringUtils.leftPad(myString, 1)
: nếu chuỗi là null, câu lệnh này cũng sẽ trả về nulldefaultString
để cung cấp chuỗi rỗng để ngăn chặn null@ck 's và @Marlon Tarak ' câu trả lời của là những người duy nhất sử dụng một char[]
, mà cho các ứng dụng có một số cuộc gọi đến các phương pháp đệm mỗi thứ hai là phương pháp tốt nhất. Tuy nhiên, họ không tận dụng bất kỳ tối ưu hóa thao tác mảng nào và bị ghi đè lên một chút theo sở thích của tôi; điều này có thể được thực hiện mà không có vòng lặp nào cả .
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);
}
Phương pháp kiểm tra đơn giản:
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));
}
Đầu ra:
012345678901234567890123456789
cats
cats
cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too long for your own good, buddy
getChars
để cho phép String
sao chép nội dung của nó trực tiếp vào out
mảng, thay vì gọi source.toCharArray()
, theo sau là System.arraycopy
. Tôi thậm chí sẽ xem xét đơn giản hóa việc thực hiện để 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);
; trong khi điều này có vẻ như fill
sẽ làm được nhiều việc hơn, nó thực sự cho phép JVM loại bỏ việc điền không mặc định.
java.util.Formatter
sẽ làm đệm trái và phải. Không cần phụ thuộc vào bên thứ ba kỳ quặc (bạn có muốn thêm chúng cho một cái gì đó quá tầm thường).
[Tôi đã bỏ qua các chi tiết và tạo bài đăng này 'wiki cộng đồng' vì nó không phải là thứ tôi cần.]
Tất cả các hoạt động chuỗi thường cần phải rất hiệu quả - đặc biệt nếu bạn đang làm việc với các bộ dữ liệu lớn. Tôi muốn một cái gì đó nhanh và linh hoạt, tương tự như những gì bạn sẽ nhận được trong lệnh pad pad. Ngoài ra, tôi không muốn bao gồm một lib lớn cho chỉ một điều nhỏ. Với những cân nhắc này, không có giải pháp nào trong số này là thỏa đáng. Đây là giải pháp tôi đã đưa ra, có kết quả đánh dấu băng ghế tốt nhất, nếu có ai có thể cải thiện nó, vui lòng thêm nhận xét của bạn.
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;
}
}
Sử dụng chức năng này.
private String leftPadding(String word, int length, char ch) {
return (length > word.length()) ? leftPadding(ch + word, length, ch) : word;
}
sử dụng như thế nào?
leftPadding(month, 2, '0');
đầu ra: 01 02 03 04 .. 11 12
Rất nhiều người có một số kỹ thuật rất thú vị nhưng tôi thích giữ nó đơn giản nên tôi thực hiện theo cách này:
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();
}
Một giải pháp đơn giản không có API sẽ như sau:
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, không có thư viện ưa thích.
// 6 characters padding example
String pad = "******";
// testcases for 0, 4, 8 characters
String input = "" | "abcd" | "abcdefgh"
Pad còn lại, không giới hạn
result = pad.substring(Math.min(input.length(),pad.length())) + input;
results: "******" | "**abcd" | "abcdefgh"
Pad phải, không giới hạn
result = input + pad.substring(Math.min(input.length(),pad.length()));
results: "******" | "abcd**" | "abcdefgh"
Pad còn lại, giới hạn chiều dài pad
result = (pad + input).substring(input.length(), input.length() + pad.length());
results: "******" | "**abcd" | "cdefgh"
Pad Phải, giới hạn chiều dài pad
result = (input + pad).substring(0, pad.length());
results: "******" | "abcd**" | "abcdef"
Làm thế nào về việc sử dụng đệ quy? Giải pháp đưa ra dưới đây tương thích với tất cả các phiên bản JDK và không yêu cầu thư viện bên ngoài :)
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);
}
}
LƯU Ý : Giải pháp này sẽ nối thêm phần đệm, với một chút tinh chỉnh bạn có thể thêm tiền tố vào giá trị pad.
Đây là phiên bản song song dành cho những bạn có Chuỗi rất dài :-)
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));
Ví dụ đệm trong ổi:
Các ví dụ đệm trong Apache Commons:
Các ví dụ đệm trong JDK:
Một giải pháp đơn giản sẽ là:
package nl;
public class Padder {
public static void main(String[] args) {
String s = "123" ;
System.out.println("#"+(" " + s).substring(s.length())+"#");
}
}