Szukam prostej wspólnej metody lub operatora, który pozwala mi powtarzać niektóre ciągi n razy. Wiem, że mógłbym to napisać za pomocą pętli for, ale chciałbym unikać pętli w razie potrzeby i gdzieś powinna istnieć prosta metoda bezpośrednia.
String str = "abc";
String repeated = str.repeat(3);
repeated.equals("abcabcabc");
Związany z:
powtórz ciąg javascript Utwórz NSString, powtarzając kolejny ciąg znaków określoną liczbę razy
Edytowane
Staram się unikać pętli, gdy nie są one całkowicie konieczne, ponieważ:
Zwiększają liczbę wierszy kodu, nawet jeśli są ukryte w innej funkcji.
Ktoś czytający mój kod musi dowiedzieć się, co robię w pętli for. Nawet jeśli jest komentowany i ma sensowne nazwy zmiennych, wciąż muszą się upewnić, że nie robi nic „mądrego”.
Programiści uwielbiają umieszczać sprytne rzeczy w pętlach, nawet jeśli piszę to, aby „robić tylko to, co jest przeznaczone”, co nie wyklucza, że ktoś przyjdzie i doda kilka dodatkowych sprytnych „poprawek”.
Bardzo często łatwo się pomylić. Pętle zawierające indeksy zwykle generują jeden błąd.
W przypadku pętli często ponownie używaj tych samych zmiennych, zwiększając szansę naprawdę trudnego znalezienia błędów dotyczących zakresu.
W przypadku pętli zwiększ liczbę miejsc, w których łowca błędów musi szukać.
Odpowiedzi:
String::repeat
Nowością w Javie 11 jest metoda,
String::repeat
która wykonuje dokładnie to, o co prosiłeś:Jego Javadoc mówi:
źródło
"abc".repeat(3)
Oto najkrótsza wersja (wymagana Java 1.5+):
Gdzie
n
jest ile razy chcesz powtórzyć ciąg is
jest ciąg do powtórzenia.Nie wymaga importu ani bibliotek.
źródło
char[]
w tym przypadku) są tworzone z wartościami null, następnie aString
jest tworzone zchar[]
, a wartości null sąreplaced()
z postacią, w której chceszs
...replace('\0', str)
należy użyć wersji String.replace(char oldChar, char newChar)
ireplace(CharSequence target, CharSequence replacement)
tak nie widzę, w jaki sposób, który mógłby pracowaćJeśli używasz Java <= 7 , jest to tak zwięzłe, jak to możliwe:
W Javie 8 i nowszych istnieje bardziej czytelny sposób:
Wreszcie, w Javie 11 i nowszych, istnieje nowa
repeat(int count)
metoda specjalnie dla tego ( link )Alternatywnie, jeśli twój projekt korzysta z bibliotek Java, istnieje więcej opcji.
Dla Apache Commons :
W przypadku Google Guava :
źródło
n
wynosi zero.s
musi być String, a nieChar
Commons Lang StringUtils.repeat ()
Stosowanie:
źródło
Java 8
String.join
zapewnia prosty sposób na zrobienie tego w połączeniu zCollections.nCopies
:źródło
Oto sposób na zrobienie tego przy użyciu tylko standardowych funkcji String i bez wyraźnych pętli:
źródło
replace()
. W Javie 1.5+ istnieje przeciążona wersja,replace()
która zajmuje dwaCharSequence
s (w tymString
s): download.oracle.com/javase/1.5.0/docs/api/java/lang/…n=3
: najpierw formatuje ciąg, aby wyglądał mniej więcej%03d
(%%
to jest znak ucieczki od znaku procentu), który jest kodem formatującym, aby dodać 3 zera dopełniające, a następnie formatuje0
z tym, prowadząc do000
, a na końcu zamienia0
je na ciągiJeśli jesteś podobny do mnie i chcesz korzystać z Google Guava, a nie Apache Commons. Możesz użyć metody repeat w klasie Struny Guava.
źródło
Z java-8, możesz także użyć
Stream.generate
.w razie potrzeby możesz owinąć go prostą metodą narzędziową:
źródło
return IntStream.range(0, times).mapToObj(i -> str).collect(joining());
który lepiej zrównuje się z sobąWięc chcesz uniknąć pętli?
Oto masz:
(oczywiście wiem, że to brzydkie i nieefektywne, ale nie ma pętli :-p)
Chcesz, żeby było to prostsze i ładniejsze? użyj jython:
Edycja : zoptymalizujmy to trochę :-D
Edit2 : Zrobiłem szybki i brudny test porównawczy dla 4 głównych alternatyw, ale nie mam czasu, aby uruchomić go kilka razy, aby uzyskać środki i zaplanować czasy dla kilku danych wejściowych ... Więc oto kod, jeśli ktoś chce spróbować tego:
Wymaga 2 argumentów, pierwszy to liczba iteracji (każda funkcja działa z czasami powtarzania arg od 1..n), a drugi to ciąg do powtórzenia.
Jak na razie szybka kontrola czasów z różnymi danymi wejściowymi pozostawia w rankingu coś takiego (lepiej na gorsze):
Nigdy bym nie zgadł, że funkcja rekurencyjna była szybsza niż
for
pętla: -oBaw się dobrze (ctional xD).
źródło
Zawiera mniej znaków niż twoje pytanie
źródło
commons-lang3.3.1-sources
i nie jesteś już taki dobry;) Ale jeśli ktoś już to macommons-lang
, popieram twoją odpowiedź.w oparciu o odpowiedź fortrana jest to wersja wielokrotnego użytku, która korzysta z StringBuilder:
źródło
używanie Dollara jest proste jak pisanie:
PS: powtarzanie działa również dla tablicy, listy, zestawu itp
źródło
Chciałem, aby funkcja utworzyła rozdzieloną przecinkami listę znaków zapytania do celów JDBC, i znalazłem ten post. Postanowiłem więc wziąć dwa warianty i sprawdzić, który z nich działa lepiej. Po milionie iteracji odmiana ogrodowa StringBuilder zajęła 2 sekundy (fun1), a tajemnicza, bardziej optymalna wersja (fun2) zajęła 30 sekund. Po co znów być tajemniczym?
źródło
Rozwiązanie OOP
Niemal każda odpowiedź proponuje funkcję statyczną jako rozwiązanie, ale myśląc o obiektach (dla celów ponownego użycia i przejrzystości) wymyśliłem rozwiązanie poprzez delegację poprzez interfejs CharSequence (który otwiera także użyteczność na zmiennych klasach CharSequence).
Poniższej klasy można używać zarówno z Separator-String / CharSequence, jak i bez niej, a każde wywołanie funkcji „toString ()” tworzy końcowy powtarzany ciąg. Input / Separator nie są ograniczone tylko do String-Class, ale mogą być każdą klasą, która implementuje CharSequence (np. StringBuilder, StringBuffer itp.)!
Kod źródłowy:
Przykład użycia:
Przykładowy wynik:
źródło
używając tylko klas JRE ( System.arraycopy ) i próbując zminimalizować liczbę obiektów tymczasowych, możesz napisać coś takiego:
EDYTOWAĆ
i bez pętli możesz wypróbować:
EDYCJA 2
korzystanie z kolekcji jest jeszcze krótsze:
jednak nadal lubię pierwszą wersję.
źródło
Nie najkrótszy, ale (myślę) najszybszym sposobem jest użycie StringBuilder:
źródło
Jeśli zależy Ci na szybkości, powinieneś zużywać jak najmniej kopii do pamięci. Dlatego wymagana jest praca z tablicami znaków.
Aby przetestować prędkość, podobna optymalna metoda przy użyciu StirngBuilder wygląda następująco:
i kod do przetestowania:
A oto wyniki z mojego systemu:
Zauważ, że testem pętli jest uruchomienie JIT i uzyskanie optymalnych wyników.
źródło
ze względu na czytelność i przenośność:
źródło
Jeśli martwisz się wydajnością, po prostu użyj StringBuilder wewnątrz pętli i wykonaj .toString () na wyjściu z pętli. Heck, napisz własną klasę util i użyj jej ponownie. 5 linii kodu maks.
źródło
Naprawdę podoba mi się to pytanie. Jest dużo wiedzy i stylów. Więc nie mogę tego zostawić bez pokazania mojego rock and rolla;)
Czy lubisz to?
źródło
źródło
Prosta pętla
źródło
times
do konstruktora StringBuilder.Wypróbuj to:
źródło
Używając rekurencji, możesz wykonać następujące czynności (używając operatorów trójskładnikowych, maksymalnie jedna linia):
Wiem, jest brzydka i prawdopodobnie nieefektywna, ale to jedna linia!
źródło
proste jednoliniowe rozwiązanie:
wymaga Java 8
źródło
Mimo że nie chcesz używać pętli, myślę, że powinieneś użyć pętli.
Powody, dla których nie używasz pętli for, nie są dobre. W odpowiedzi na twoją krytykę:
źródło
repetitions = -5
. b) pobierz Commons Lang i uruchomrepeatString('a', 1000)
milion razy w pętli; zrób to samo ze swoim kodem; porównaj czasy. Aby uzyskać dodatkowy kredyt, zrób to samo zrepeatString('ab', 1000)
.StringUtils.repeat("ab",1000)
? Ponieważ to była moja odpowiedź, którą głosowałeś. Działa również lepiej i nie ma błędów.Jeśli znasz tylko długość ciągu wyjściowego (i może nie być podzielna przez długość ciągu wejściowego), użyj tej metody:
Demo użycia:
Nie używaj z pustymi
s
ilength
> 0, ponieważ w tym przypadku nie można uzyskać pożądanego wyniku.źródło
oto najnowszy Stringutils.java StringUtils.java
nie musi być nawet tak duży, można go w to przekształcić i można go skopiować i wkleić do klasy użytkowej w projekcie.
Więc e5, myślę, że najlepszym sposobem na to byłoby po prostu użycie wyżej wspomnianego kodu lub dowolnej z odpowiedzi tutaj. ale wspólny język jest po prostu zbyt duży, jeśli jest to mały projekt
źródło
Stworzyłem metodę rekurencyjną, która robi to samo, co chcesz .. możesz użyć tego ...
mam tę samą odpowiedź na Czy mogę pomnożyć ciągi w Javie, aby powtarzać sekwencje?
źródło
StringBuilder
zamiast tego.Możesz użyć tej metody rekurencyjnej do osiągnięcia pożądanego celu.
źródło