W kwestii funkcji apache vs formater struny nie ma wątpliwości, że funkcja apache jest bardziej przejrzysta i czytelna. Zawijanie formatera w nazwach funkcji nie jest idealne.
Należy jednak pamiętać, że - jak inni wspominali i wykazali w tej odpowiedzi - String.format()i Formatterklasy w JDK są lepszymi opcjami. Użyj ich zamiast wspólnego kodu.
@Jonik, czy chciałbyś wymienić niektóre ze swoich powodów? Interfejsy API wyglądają prawie tak samo.
glen3b
3
@ glen3b: W przypadku pojedynczego narzędzia, takiego jak te pomocniki dopełniania łańcucha, tak naprawdę nie ma znaczenia, której biblioteki użyć. To powiedziawszy, Guava jest ogólnie bardziej nowoczesnym, czystszym i lepiej udokumentowanym libem niż jego odpowiedniki w różnych projektach Apache Commons (Commons Lang, Commons Collections, Commons IO itp.). Jest również zbudowany przez naprawdę inteligentnych facetów (Kevin Bourrillion i in.), Z których wielu jest aktywnych w SO . Sam skończyłem, zastępując różne biblioteki Apache Commons zaledwie Guava lata temu i nie żałowałem.
Co zrobić, jeśli potrzebujesz lpad z innymi znakami (nie spacjami)? Czy nadal jest to możliwe dzięki String.format? Nie jestem w stanie sprawić, żeby działało ...
@ Nullw0rm, jeśli odwołujesz się do rgagnon.com, pamiętaj, że RealHowTo jest także autorem rgagnon.com, więc sam by się podał ...
Colin Pickard
3
przynajmniej w mojej JVM „#” nie działa, „-” jest w porządku. (Wystarczy usunąć #). Może to być zgodne z dokumentacją formatyzatora, nie wiem; mówi: „# '' \ u0023 'Wymaga użycia wyjściowego formularza alternatywnego. Definicja formularza jest określona przez konwersję.”
gatoatigrado
6
Dzięki za świetną odpowiedź. Mam jednak wątpliwości, po co 1$? @leo udzielił bardzo podobnej odpowiedzi, która nie jest używana 1$i najwyraźniej ma ten sam efekt. Czy to robi różnicę?
Fabrício Matté
257
Wypełnienie do 10 znaków:
String.format("%10s","foo").replace(' ','*');String.format("%-10s","bar").replace(' ','*');String.format("%10s","longer than 10 chars").replace(' ','*');
Tak długo, jak wszyscy pamiętamy, aby nie przechodzić sznurkiem ze spacjami ...: D
leviathanbadger
4
Jestem z @ aboveyou00 - jest to przerażające rozwiązanie dla ciągów ze spacjami, w tym przykład podany przez Leo. Rozwiązanie wypełniania łańcucha po lewej lub po prawej stronie nie powinno zmieniać łańcucha wejściowego tak, jak jest wyświetlany na wyjściu, chyba że oryginalne wypełnienie łańcucha wejściowego powoduje, że przekracza on określoną długość dopełniania.
Brian Warshaw
3
Potwierdź problem dotyczący miejsca. .replace(' ', '*')miał raczej na celu pokazanie efektu wypełnienia. Wyrażenie ukrywania hasła i tak nie ma tego problemu ... Aby uzyskać lepszą odpowiedź na temat dostosowywania lewego i prawego łańcucha dopełniania za pomocą natywnej funkcji Java, zobacz moją drugą odpowiedź.
leo
Jeśli ciąg zawiera tylko pojedyncze spacje i chcesz wstawiać różne znaki, możesz użyć wyrażenia regularnego zastępując go spojrzeniem do tyłu / do przodu: String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")lubString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
Uwaga: odwrócono nazwy funkcji; jeśli go uruchomisz, zobaczysz.
niebieskawy
plus jeśli oryginalny ciąg zawiera spacje, to nie działa
Steven Shaw
@StevenShaw Jeśli się nie mylę, zamiana nie jest kierowana na oryginał str, więc jest to poprawne.
mafu
3
Zgodnie z konwencją nie należy używać wielkich liter w nazwach funkcji.
principal-ideal-domain
Czy brak jest warunku zwrócenia ciągu, gdy (length - str.length())jest 0? Formater zgłasza, FormatFlagsConversionMismatchExceptionkiedy %0sjest ciągiem formatu.
Devin Walters
7
Zajęło mi to trochę czasu. Prawdziwym kluczem jest przeczytanie dokumentacji formatera.
// Get your data from wherever.finalbyte[] data = getData();// Get the digest engine.finalMessageDigest md5=MessageDigest.getInstance("MD5");// Send your data through it.
md5.update(data);// Parse the data as a positive BigInteger.finalBigInteger digest =newBigInteger(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);
Dlaczego koniec jest tak skomplikowany? Mogłeś właśnie zrobić String hex = String.format ("% 032x", skrót); i miał dokładnie takie same wyniki, tylko bez niepotrzebnego zastępowania () i konieczności używania $, aby uzyskać dostęp do określonych zmiennych (w końcu jest tylko jedna.)
ArtOfWarfare
@ArtOfWarfare fair point. Ktoś pierwotnie poprosił o wartości szesnastkowe wypełniania w innym pytaniu, widziałem, że mam link do dokumentacji formatyzatora. Jest to skomplikowane ze względu na kompletność.
Nthalk
6
wiem, że ten wątek jest trochę stary i pierwotne pytanie dotyczyło łatwego rozwiązania, ale jeśli powinno być naprawdę szybkie, powinieneś użyć tablicy znaków.
Jeśli StringBuffernie można uzyskać dostępu do wielu wątków jednocześnie (co w tym przypadku jest prawdą), należy użyć StringBuilder(w JDK1.5 +), aby uniknąć narzutu synchronizacji.
glen3b
5
Oto inny sposób na przesunięcie w prawo:
// put the number of spaces, or any character you like, in your paddedStringString paddedString ="--------------------";String myStringToBePadded ="I like donuts";
myStringToBePadded = myStringToBePadded + paddedString.substring(myStringToBePadded.length());//result:
myStringToBePadded ="I like donuts-------";
Alternatywnie możesz ustawić długość wyniku jako parametr pad(...)metody. W takim przypadku dostosuj ukryte wypełnienie w tej metodzie zamiast w konstruktorze.
(Wskazówka: Aby uzyskać dodatkowy kredyt, upewnij się, że jest bezpieczny dla wątków! ;-)
To jest bezpieczne dla wątków, z wyjątkiem niebezpiecznej publikacji (oczywiście, aby pola były ostateczne). Myślę, że wydajność można poprawić, wykonując podłańcuch przed znakiem +, który powinien zostać zastąpiony przez concat (co dziwne).
Wypełni Twój Ciąg XXX do 9 Znaków spacją. Następnie wszystkie białe znaki zostaną zastąpione przez 0. Możesz zmienić białe znaki i 0 na cokolwiek chcesz ...
Powinieneś wywołać tę staticmetodę jako String.format(…)zamiast nadużywania pustego ciągu. Zapisanie czterech znaków w kodzie źródłowym z pewnością nie jest warte utraty czytelności.
Holger
2
publicstaticString padLeft(String in,int size,char padChar){if(in.length()<= size){char[] temp =newchar[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++;}returnnewString(temp);}return"";}
Pozwól, że zostawię odpowiedź na niektóre przypadki, w których musisz podać lewy / prawy dopełnienie (lub ciąg prefiksu / sufiksu lub spacje) przed połączeniem z innym ciągiem i nie chcesz testować długości ani żadnego warunku.
Tak samo jak w przypadku wybranej odpowiedzi, wolałbym StringUtilsApache Commons, ale używając tej metody:
Odpowiedzi @ck i @Marlon Tarak są jedynymi, które używają a char[], co jest najlepszym rozwiązaniem dla aplikacji, które mają kilka wywołań metod wypełniania na sekundę. Nie korzystają one jednak z żadnych optymalizacji manipulacji tablicami i są dla mnie trochę nadpisane; można to zrobić bez żadnych pętli .
publicstaticvoid 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));}
Wyjścia:
012345678901234567890123456789
cats
cats
cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too longfor your own good, buddy
Możesz użyć, getCharsaby pozwolić na Stringskopiowanie jego zawartości bezpośrednio do outtablicy, zamiast wywoływania source.toCharArray(), a następnie System.arraycopy. Rozważałbym nawet uproszczenie implementacji do 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);; choć wygląda na to, fillże wykonałby więcej pracy, w rzeczywistości pozwala JVM na wyeliminowanie domyślnego zerowania.
Holger
1
java.util.Formatterzrobi lewe i prawe wypełnienie. Nie ma potrzeby dziwnych zależności stron trzecich (czy chcesz je dodać do czegoś tak trywialnego).
[Pominąłem szczegóły i uczyniłem ten post „społecznością wiki”, ponieważ nie jest to coś, czego potrzebuję.]
Nie zgadzam się. W każdym większym projekcie Java zwykle wykonujesz tak dużo manipulacji ciągami, że zwiększona czytelność i unikanie błędów jest warte użycia Apache Commons Lang. Wszyscy znacie kod jak someString.subString (someString.indexOf (startCharacter), someString.lastIndexOf (endCharacter)), którego można łatwo uniknąć za pomocą StringUtils.
Bananeweizen
1
Wszystkie operacje na łańcuchach zwykle muszą być bardzo wydajne - szczególnie jeśli pracujesz z dużymi zestawami danych. Chciałem czegoś szybkiego i elastycznego, podobnego do tego, co dostaniesz w poleceniu pad plsql. Nie chcę też zawierać ogromnej biblioteki dla jednej drobnej rzeczy. Biorąc pod uwagę powyższe rozważania, żadne z tych rozwiązań nie było zadowalające. Oto rozwiązania, które wymyśliłem, które miały najlepsze wyniki testów porównawczych, jeśli ktokolwiek może to poprawić, proszę dodać komentarz.
Uwaga: wywoływana jest za pomocą String.toCharArray (), a wynik można przekonwertować na String za pomocą nowego ciągu ((wynik [char [])). Powodem tego jest to, że jeśli zastosujesz wiele operacji, możesz wykonać je wszystkie na char [], a nie konwertować między formatami - za kulisami String jest przechowywany jako char []. Gdyby te operacje zostały uwzględnione w samej klasie String, byłoby to dwa razy bardziej wydajne - pod względem szybkości i pamięci.
Oto wersja równoległa dla tych z was, którzy mają bardzo długie ciągi :-)
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));
Odpowiedzi:
Apache
StringUtils
ma kilka metod:leftPad
,rightPad
,center
irepeat
.Należy jednak pamiętać, że - jak inni wspominali i wykazali w tej odpowiedzi -
String.format()
iFormatter
klasy w JDK są lepszymi opcjami. Użyj ich zamiast wspólnego kodu.źródło
Od wersji Java 1.5
String.format()
można używać do wstawiania lewej / prawej strony danego ciągu.Wyjście to:
źródło
1$
? @leo udzielił bardzo podobnej odpowiedzi, która nie jest używana1$
i najwyraźniej ma ten sam efekt. Czy to robi różnicę?Wypełnienie do 10 znaków:
wynik:
Wyświetl znaki „*” dla znaków hasła:
wynik ma taką samą długość jak ciąg hasła:
źródło
.replace(' ', '*')
miał raczej na celu pokazanie efektu wypełnienia. Wyrażenie ukrywania hasła i tak nie ma tego problemu ... Aby uzyskać lepszą odpowiedź na temat dostosowywania lewego i prawego łańcucha dopełniania za pomocą natywnej funkcji Java, zobacz moją drugą odpowiedź.String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")
lubString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
W Guava jest to łatwe:
źródło
Coś prostego:
Wartość powinna być ciągiem. przekonwertować na ciąg, jeśli nie jest. Jak
"" + 123
lubInteger.toString(123)
Podciąg rozpoczyna się od indeksu długości wartości indeksu aż do końcowej długości dopełnienia:
Bardziej dokładnie
podkładka w prawo:
pad lewy:
źródło
Spójrz na
org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar)
.Ale algorytm jest bardzo prosty (pad aż do wielkości znaków):
źródło
Oprócz Apache Commons, zobacz także,
String.format
które powinny być w stanie zająć się prostym wypełnieniem (np. Spacjami).źródło
źródło
str
, więc jest to poprawne.(length - str.length())
jest0
? Formater zgłasza,FormatFlagsConversionMismatchException
kiedy%0s
jest ciągiem formatu.Zajęło mi to trochę czasu. Prawdziwym kluczem jest przeczytanie dokumentacji formatera.
źródło
wiem, że ten wątek jest trochę stary i pierwotne pytanie dotyczyło łatwego rozwiązania, ale jeśli powinno być naprawdę szybkie, powinieneś użyć tablicy znaków.
rozwiązanie formatyzatora nie jest optymalne. samo zbudowanie ciągu formatu tworzy 2 nowe ciągi.
rozwiązanie apache można ulepszyć, inicjując SB o docelowy rozmiar, zastępując go poniżej
z
zapobiegnie wzrostowi bufora wewnętrznego kogoś.
źródło
StringBuffer
nie można uzyskać dostępu do wielu wątków jednocześnie (co w tym przypadku jest prawdą), należy użyćStringBuilder
(w JDK1.5 +), aby uniknąć narzutu synchronizacji.Oto inny sposób na przesunięcie w prawo:
źródło
Od wersji Java 11 String.repeat (int) może być używany do wstawiania danego ciągu w lewo / w prawo.
Wynik:
źródło
Możesz zmniejszyć narzut na połączenie, zachowując dane wypełniania, zamiast odbudowywać je za każdym razem:
Alternatywnie możesz ustawić długość wyniku jako parametr
pad(...)
metody. W takim przypadku dostosuj ukryte wypełnienie w tej metodzie zamiast w konstruktorze.(Wskazówka: Aby uzyskać dodatkowy kredyt, upewnij się, że jest bezpieczny dla wątków! ;-)
źródło
Znaleziono to na Dzone
Pad z zerami:
źródło
możesz użyć wbudowanej metody StringBuilder append () i insert () do wypełniania zmiennych długości łańcucha:
Na przykład:
źródło
To działa:
Wypełni Twój Ciąg XXX do 9 Znaków spacją. Następnie wszystkie białe znaki zostaną zastąpione przez 0. Możesz zmienić białe znaki i 0 na cokolwiek chcesz ...
źródło
static
metodę jakoString.format(…)
zamiast nadużywania pustego ciągu. Zapisanie czterech znaków w kodzie źródłowym z pewnością nie jest warte utraty czytelności.źródło
Pozwól, że zostawię odpowiedź na niektóre przypadki, w których musisz podać lewy / prawy dopełnienie (lub ciąg prefiksu / sufiksu lub spacje) przed połączeniem z innym ciągiem i nie chcesz testować długości ani żadnego warunku.
Tak samo jak w przypadku wybranej odpowiedzi, wolałbym
StringUtils
Apache Commons, ale używając tej metody:Wyjaśnić:
myString
: ciąg, który wprowadzam, może być pustyStringUtils.leftPad(myString, 1)
: jeśli łańcuch jest pusty, to instrukcja również zwróci nulldefaultString
aby podać pusty ciąg, aby zapobiec konkatenacji wartości nullźródło
Odpowiedzi @ck i @Marlon Tarak są jedynymi, które używają a
char[]
, co jest najlepszym rozwiązaniem dla aplikacji, które mają kilka wywołań metod wypełniania na sekundę. Nie korzystają one jednak z żadnych optymalizacji manipulacji tablicami i są dla mnie trochę nadpisane; można to zrobić bez żadnych pętli .Prosta metoda testowa:
Wyjścia:
źródło
getChars
aby pozwolić naString
skopiowanie jego zawartości bezpośrednio doout
tablicy, zamiast wywoływaniasource.toCharArray()
, a następnieSystem.arraycopy
. Rozważałbym nawet uproszczenie implementacji dochar[] 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);
; choć wygląda na to,fill
że wykonałby więcej pracy, w rzeczywistości pozwala JVM na wyeliminowanie domyślnego zerowania.java.util.Formatter
zrobi lewe i prawe wypełnienie. Nie ma potrzeby dziwnych zależności stron trzecich (czy chcesz je dodać do czegoś tak trywialnego).[Pominąłem szczegóły i uczyniłem ten post „społecznością wiki”, ponieważ nie jest to coś, czego potrzebuję.]
źródło
Wszystkie operacje na łańcuchach zwykle muszą być bardzo wydajne - szczególnie jeśli pracujesz z dużymi zestawami danych. Chciałem czegoś szybkiego i elastycznego, podobnego do tego, co dostaniesz w poleceniu pad plsql. Nie chcę też zawierać ogromnej biblioteki dla jednej drobnej rzeczy. Biorąc pod uwagę powyższe rozważania, żadne z tych rozwiązań nie było zadowalające. Oto rozwiązania, które wymyśliłem, które miały najlepsze wyniki testów porównawczych, jeśli ktokolwiek może to poprawić, proszę dodać komentarz.
źródło
Użyj tej funkcji.
jak używać?
wyjście: 01 02 03 04 .. 11 12
źródło
Wiele osób ma kilka bardzo interesujących technik, ale chcę to uprościć, więc idę z tym:
źródło
Proste rozwiązanie bez interfejsu API będzie wyglądać następująco:
źródło
Oneliner w Javie, bez fantazyjnej biblioteki.
Pad w lewo, nie ograniczaj
Pad Prawo, nie ograniczaj
Pad Lewa, ograniczenie do długości padu
Pad Right, ograniczenie do długości padu
źródło
Co powiesz na użycie rekurencji? Rozwiązanie podane poniżej jest kompatybilne ze wszystkimi wersjami JDK i nie wymaga bibliotek zewnętrznych :)
UWAGA : To rozwiązanie doda dopełnienie, z niewielkim dopracowaniem możesz poprzedzić wartość pada.
źródło
Oto wersja równoległa dla tych z was, którzy mają bardzo długie ciągi :-)
źródło
Przykłady paddingu w Guava:
Przykłady wypełniania w Apache Commons:
Przykłady wypełniania w JDK:
źródło
Prostym rozwiązaniem byłoby:
źródło
Jak to jest
Łańcuch jest „cześć”, a wymagane wypełnienie to 15 z lewą podkładką „0”
źródło