Java'da Dizeleri doldurmanın kolay bir yolu var mı?
Bazı StringUtil benzeri API'de olması gereken bir şey gibi görünüyor, ancak bunu yapan bir şey bulamıyorum.
Java'da Dizeleri doldurmanın kolay bir yolu var mı?
Bazı StringUtil benzeri API'de olması gereken bir şey gibi görünüyor, ancak bunu yapan bir şey bulamıyorum.
Yanıtlar:
Apaçi StringUtils
çeşitli yöntemler vardır: leftPad
, rightPad
, center
ve repeat
.
Ancak, diğerlerinin bu cevapta belirttiği ve gösterdiği gibi - String.format()
ve Formatter
JDK'daki sınıfların daha iyi seçenekler olduğunu lütfen unutmayın . Onları ortak kod üzerinde kullanın.
Java 1.5 beri, String.format()
belirli bir dizeyi sol / sağ pad için kullanılabilir.
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) + "*");
}
Ve çıktı:
Howto *
Howto*
1$
için? @leo kullanılmayan çok benzer bir cevap verdi 1$
ve görünüşe göre aynı etkiye sahip. Bir fark yaratır mı?
10 karaktere kadar dolgu:
String.format("%10s", "foo").replace(' ', '*');
String.format("%-10s", "bar").replace(' ', '*');
String.format("%10s", "longer than 10 chars").replace(' ', '*');
çıktı:
*******foo
bar*******
longer*than*10*chars
Şifre karakterleri için '*' göster:
String password = "secret123";
String padded = String.format("%"+password.length()+"s", "").replace(' ', '*');
Çıktı şifre dizesiyle aynı uzunlukta:
secret123
*********
.replace(' ', '*')
daha ziyade dolgu etkisini göstermeyi amaçlamıştır. Parola gizleme ifadesinde zaten bu sorun yok ... Yerel Java özelliğini kullanarak sol ve sağ dolgu dizesini özelleştirme konusunda daha iyi bir yanıt için diğer cevabımı görün.
String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")
veyaString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
In Guava , bu kolaydır:
Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');
Basit bir şey:
Değer bir dize olmalıdır. değilse dizeye dönüştürün. Beğen "" + 123
veyaInteger.toString(123)
// let's assume value holds the String we want to pad
String value = "123";
Alt dize, değer uzunluğu karakter indeksinden dolgulu bitiş uzunluğuna kadar başlar:
String padded="00000000".substring(value.length()) + value;
// now padded is "00000123"
Daha kesin
ped sağ:
String padded = value + ("ABCDEFGH".substring(value.length()));
// now padded is "123DEFGH"
ped sol:
String padString = "ABCDEFGH";
String padded = (padString.substring(0, padString.length() - value.length())) + value;
// now padded is "ABCDE123"
Bir bak org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar)
.
Ancak algoritma çok basittir (boyut karakterlerine kadar ped):
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'ın yanı sıra, String.format
hangilerinin basit dolguya (örneğin boşluklarla) bakabilmesi gerektiğini de görün .
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
, bu yüzden bu doğrudur.
(length - str.length())
olduğu gibi döndürmede eksik bir koşul var mı 0
? Formatlayıcı , format dizesi bir FormatFlagsConversionMismatchException
zaman atar %0s
.
Anlamak biraz zaman aldı. Gerçek anahtar bu Formatter belgelerini okumaktır.
// 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);
i bu konu eski tür ve orijinal soru kolay bir çözüm olduğunu biliyorum ama gerçekten hızlı olması gerekiyorsa, bir char dizi kullanmalısınız.
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;
}
formatlayıcı çözümü uygun değildir. sadece biçim dizesini oluşturmak 2 yeni dizge oluşturur.
apache'nin çözümü sb'yi hedef boyutla başlatarak geliştirilebilir, böylece aşağıda
StringBuffer padded = new StringBuffer(str);
ile
StringBuffer padded = new StringBuffer(pad);
padded.append(value);
SB'nin iç tamponunun büyümesini önleyecektir.
StringBuffer
(bu durumda doğrudur) Aynı anda birden fazla iş parçacığı tarafından erişilemez, bir kullanmalıdır StringBuilder
(JDK1.5 + olarak) senkronizasyon yükü önlemek için.
Sağa doğru basmanın başka bir yolu:
// 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'den bu yana, String.repeat (int) belirli bir dizeyi sol / sağ tuş takımı için kullanılabilir.
System.out.println("*".repeat(5)+"apple");
System.out.println("apple"+"*".repeat(5));
Çıktı:
*****apple
apple*****
Her seferinde yeniden oluşturmak yerine doldurma verilerini koruyarak arama başına ek yükü azaltabilirsiniz:
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);
}
}
Alternatif olarak, sonuç uzunluğunu pad(...)
yönteme bir parametre yapabilirsiniz . Bu durumda, gizli dolgu ayarını yapıcı yerine bu yöntemde yapın.
(İpucu: Ekstra kredi için, iş parçacığı açısından güvenli yapın! ;-)
değişken dize uzunluklarının doldurulması için yerleşik StringBuilder append () ve insert () yöntemlerini kullanabilirsiniz:
AbstractStringBuilder append(CharSequence s, int start, int end) ;
Örneğin:
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());
Bu çalışıyor:
"".format("%1$-" + 9 + "s", "XXX").replaceAll(" ", "0")
String XXX'nizi 9 karaktere kadar bir boşlukla dolduracaktır. Bundan sonra tüm Whitespaces 0 ile değiştirilecek. Beyaz alanı ve 0'ı istediğiniz gibi değiştirebilirsiniz ...
static
olarak yöntemini String.format(…)
yerine boş bir dize kötüye. Kaynak kodda dört karakter kaydetmek kesinlikle okunabilirlik kaybına değmez.
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 "";
}
Başka bir dizeye bitiştirmeden önce sol / sağ dolgu (veya önek / sonek dizesi veya boşlukları) vermeniz gereken bazı durumlar için bir cevap bırakalım ve uzunluğu veya herhangi bir if koşulunu test etmek istemiyorum.
Seçilen cevap için aynı StringUtils
, Apache Commons tercih ederim ama bu şekilde kullanarak:
StringUtils.defaultString(StringUtils.leftPad(myString, 1))
Açıklamak:
myString
: Girdiğim dize boş olabilirStringUtils.leftPad(myString, 1)
: dize null olursa, bu ifade de null değerini döndürürdefaultString
null değerini bitirmek için boş dize vermek için kullanın@ck ve @Marlon Tarak'ın cevapları a'yı kullanmak için sadece cevaplardır, char[]
bu da saniyede dolgu yöntemlerine birkaç çağrı yapan uygulamalar için en iyi yaklaşımdır. Ancak, herhangi bir dizi manipülasyon optimizasyonundan faydalanmazlar ve benim zevkime göre biraz üzerine yazılırlar; bu hiç bir döngü olmadan yapılabilir .
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);
}
Basit test yöntemi:
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));
}
Çıktılar:
012345678901234567890123456789
cats
cats
cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too long for your own good, buddy
getChars
izin String
doğrudan içine içeriğini kopyalamak out
yerine çağıran, dizinin source.toCharArray()
izledi System.arraycopy
. Uygulamayı basitleştirmeyi bile düşünürdüm 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);
; Bu fill
daha fazla iş yapar gibi görünüyor olsa da, aslında JVM'nin varsayılan sıfır dolumunu ortadan kaldırmasına izin verir.
java.util.Formatter
sol ve sağ dolgu yapacak. Garip üçüncü taraf bağımlılıklarına gerek yok (bunları önemsiz bir şey için eklemek ister misiniz).
[Ayrıntıları bıraktım ve ihtiyacım olan bir şey olmadığı için bu yayını 'topluluk wiki' yaptım.]
Tüm dize işlemlerinin genellikle çok verimli olması gerekir - özellikle büyük veri kümeleriyle çalışıyorsanız. Ben plsql pad komut alacak ne benzer, hızlı ve esnek bir şey istedim. Ayrıca, sadece küçük bir şey için büyük bir lib eklemek istemiyorum. Bu düşüncelerle bu çözümlerin hiçbiri tatmin edici değildi. Bu, benim geliştirdiğim, en iyi tezgah işaretleme sonuçlarına sahip olan çözümler, eğer herhangi biri üzerinde iyileştirebilirse, lütfen yorumunuzu ekleyin.
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;
}
}
Bu işlevi kullanın.
private String leftPadding(String word, int length, char ch) {
return (length > word.length()) ? leftPadding(ch + word, length, ch) : word;
}
nasıl kullanılır?
leftPadding(month, 2, '0');
çıktı: 01 02 03 04 .. 11 12
Bir çok insanın bazı çok ilginç teknikleri var ama bunu basit tutmayı seviyorum, bu yüzden bununla devam ediyorum:
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();
}
Herhangi bir API'sı olmayan basit bir çözüm aşağıdaki gibi olacaktır:
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, süslü kütüphane yok.
// 6 characters padding example
String pad = "******";
// testcases for 0, 4, 8 characters
String input = "" | "abcd" | "abcdefgh"
Pad Sol, sınırlama
result = pad.substring(Math.min(input.length(),pad.length())) + input;
results: "******" | "**abcd" | "abcdefgh"
Ped Sağ, sınırlama
result = input + pad.substring(Math.min(input.length(),pad.length()));
results: "******" | "abcd**" | "abcdefgh"
Ped Sol, ped uzunluğu ile sınırlandır
result = (pad + input).substring(input.length(), input.length() + pad.length());
results: "******" | "**abcd" | "cdefgh"
Ped Sağ, ped uzunluğuyla sınırlandır
result = (input + pad).substring(0, pad.length());
results: "******" | "abcd**" | "abcdef"
Özyineleme kullanmaya ne dersiniz? Aşağıda verilen çözüm tüm JDK sürümleriyle uyumludur ve harici kitaplığa gerek yoktur :)
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);
}
}
NOT : Bu çözüm dolguyu ekleyecektir, küçük bir değişiklikle ped değerini önekleyebilirsiniz.
İşte çok uzun Dizeleri olanlar için paralel bir sürüm :-)
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'da dolgu örnekleri:
Apache Commons'ta dolgu örnekleri:
JDK'da dolgu örnekleri:
Basit bir çözüm:
package nl;
public class Padder {
public static void main(String[] args) {
String s = "123" ;
System.out.println("#"+(" " + s).substring(s.length())+"#");
}
}
Bu nasıl
Dize "merhaba" ve gerekli dolgu "0" sol yastık ile 15
String ax="Hello";
while(ax.length() < 15) ax="0"+ax;