Najszybszy sposób na ustawienie wszystkich wartości tablicy?
Mam
char []
i chcę ustawić wartość każdego indeksu na tę samą wartośćchar.
Jest na to oczywisty sposób (iteracja):
char f = '+';
char [] c = new char [50];
for(int i = 0; i < c.length; i++){
c[i] = f;
}
Ale zastanawiałem się, czy istnieje sposób, w jaki mogę użyć
System.arraycopylub czegoś równoważnego, który obejdzie potrzebę iteracji. Czy jest na to sposób?
EDIT :
autor:
Arrays.java
public static void fill(char[] a, int fromIndex, int toIndex, char val) {
rangeCheck(a.length, fromIndex, toIndex);
for (int i = fromIndex; i < toIndex; i++)
a[i] = val;
}
To jest dokładnie ten sam proces, który pokazuje, że może nie być lepszego sposobu na zrobienie tego.
+1 dla wszystkich, którzy mimo wszystko zasugerowali
wypełnij- wszystko w porządku i dzięki.
Nie znaleziono powiązanych wyników
Zaproszony:
Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się
14 odpowiedzi
Anonimowy użytkownik
Potwierdzenie od:
tablice dokumentacji
http://docs.oracle.com/javase/ ... %255D,%20char%29
Anonimowy użytkownik
Potwierdzenie od:
System
http://docs.oracle.com/javase/ ... .html
które (jeśli używana maszyna JVM jest wystarczająco inteligentna) może zostać przekształcone w operację
memset
https://coderoad.ru/7367677/
:-
Ta decyzja została podjęta na podstawie badań IBM
„Wydajność serwera Java: wydajne budowanie, skalowalne Jvms” autorstwa R. Dimpsy, R. Arora, K. Kuiper
https://ieeexplore.ieee.org/document/5387064
.
Uproszczone wyjaśnienie
Jak sugeruje komentarz, ustawia to indeks 0 tablicy docelowej na twoją wartość, a następnie używa
systemowy
http://docs.oracle.com/javase/ ... .html
klasa do kopiowania jednego obiektu, czyli obiekt o indeksie 0 do indeksu 1, następnie te dwa obiekty (indeks 0 i 1) do 2 i 3, a następnie te cztery obiekty (0,1,2 i 3) do 4, 5,6 i 7 i tak dalej ...
Wydajność (w momencie pisania
artykuły)
W szybkim biegu, chwytając przed i po i obliczając czas trwania, który wymyśliłem: -
Kompilacja JVM i JIT
Należy zauważyć, że wraz z ewolucją JVM i JIT podejście to może stać się przestarzałe, ponieważ optymalizacje bibliotek i środowiska wykonawczego mogą osiągnąć lub nawet przekroczyć te liczby, używając po prostu .
W chwili pisania tego tekstu była to najszybsza opcja, jaką znalazłem. Wspomniano już, że może tak nie być w tej chwili, ale nie testowałem. To jest piękno i przekleństwo Javy.
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
http://www.ensta-paristech.fr/ ... .html
oferuje:
To zasadniczo powoduje wywołanie log2 (array.length) do System.arraycopy, który, miejmy nadzieję, używa zoptymalizowanej implementacji memcpy.
Jednak czy ta technika jest nadal wymagana w nowoczesnych JIT Java, takich jak Oracle/Android JIT?
Anonimowy użytkownik
Potwierdzenie od:
12:33:18
Dwukrotne przetwarzanie macierzy zajmuje 133536 nanosekund.
Cykl system.arraycopy trwa 22070 nano sekund.
Jedna runda Arrays.fill zajmuje 9777 nano sekund.
Dwie rundy wypełnienia Arrays.fill zajmą 93 028 nano sekund.
12:33:38
Dwuetapowe przetwarzanie tablic zajmuje 133816 nanosekund.
Cykl system.arraycopy trwa 22070 nano sekund.
Jedna runda Arrays.fill zajmuje 17042 nano sekund.
Dwie rundy Arrays.fill zajmą 95263 nano sekund.
12:33:51
Dwuetapowe przetwarzanie macierzy zajmuje 199187 nanosekund.
Cykl system.arraycopy trwa 44140 nano sekund.
Jedna runda Arrays.fill zajmuje 19555 nano sekund.
Dwie rundy wypełnienia Arrays.fill zajmą 449219 nano sekund.
12:34:16
Dwukrotne przetwarzanie macierzy zajmuje 199467 nanosekund.
Cykl Arraycopy System. trwa 42464 nano sekund.
Jedna runda Arrays.fill zajmuje 17600 nano sekund.
Dwie rundy Arrays.fill zajmą 170 971 nano sekund.
12:34:26
Dwuetapowe przetwarzanie macierzy zajmuje 198907 nanosekund.
Cykl Arraycopy System trwa 24584 nano sekund.
Jedna runda Arrays.fill zajmuje 10616 nano sekund.
Dwie rundy Arrays.fill zajmują 94,426 nano sekund.
Anonimowy użytkownik
Potwierdzenie od:
char [] b
, i chcesz zamienić na , możesz użyć .Anonimowy użytkownik
Potwierdzenie od:
opcja
https://docs.oracle.com/javase ... .html
setAll, która ustawia wszystkie elementy określonej tablicy przy użyciu podanej funkcji generatora do obliczenia każdego elementu.
Tylko z tych czterech przeciążeń
trzy
z nich przyjmują tablicę prymitywów, zadeklarowanych jako takie:
Przykłady wykorzystania powyższych metod:
Funkcja dostarczona do metody pobiera indeks elementu i zwraca wartość dla tego indeksu.
możesz się zastanawiać, co z tablicą znaków?
Tutaj pojawia się czwarte przeciążenie metody . Ponieważ nie ma przeciążenia, które zużywa tablicę prymitywów znaków, jedyną opcją, jaką mamy, jest zmiana deklaracji tablicy znaków na typ
Character []
.Jeśli zmiana typu tablicy na nie jest właściwa, możesz powrócić do metody Arrays.fill.
Przykład użycia metody z
Character []
:Chociaż dla
ustawienie pewnego
wartości łatwiej jest użyć metody niż metody .
Metoda ma tę zaletę, że możesz ustawić wszystkie elementy tablicy na tę samą wartość lub wygenerować tablicę liczb parzystych, nieparzystych lub dowolną inną formułę:
dawny.
Istnieje również kilka przeciążeń metody parallelSetAll, które są wykonywane równolegle, chociaż należy zauważyć, że funkcja przekazana do metody parallelSetAll jest
musi być wolny od skutków ubocznych
.
Wynik
Jeśli Twoim celem jest po prostu
ustalić pewne
value dla każdego elementu tablicy, wtedy użycie przeciążeń byłoby najbardziej odpowiednią opcją. Jeśli jednak chcesz być bardziej elastyczny lub generować elementy na żądanie, najlepiej jest użyć lub (w stosownych przypadkach).
Anonimowy użytkownik
Potwierdzenie od:
.
http://docs.oracle.com/javase/ ... .html
Metoda Arrays.fill:
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
http://docs.oracle.com/javase/ ... %255D,%20char%29
Chociaż jest całkowicie możliwe, że robi to pętlę w tle, a zatem nie jest bardziej wydajne niż to, co masz (poza zapisywaniem linii kodu). Jeśli naprawdę zależy Ci na wydajności, wypróbuj poniższe W porównaniu z powyższym:
Zauważ, że powyższe nie wywołuje funkcji array.size () dla każdej iteracji.
Anonimowy użytkownik
Potwierdzenie od:
W ten sposób robi to Arrays.fill.
(Przypuszczam, że możesz zajrzeć do JNI i użyć .)
Anonimowy użytkownik
Potwierdzenie od:
Dla
mały
prosta pętla tablicy jest szybsza niż metoda System.arraycopy ze względu na obciążenie związane z konfiguracją System.arraycopy. Dlatego lepiej jest wypełnić kilka pierwszych bajtów tablicy prostą pętlą i przechodzić do System.arraycopy tylko wtedy, gdy wypełniona tablica ma określony rozmiar.
Optymalny rozmiar początkowej pętli będzie zależał od maszyny JVM i oczywiście od konkretnego systemu.
Anonimowy użytkownik
Potwierdzenie od:
Oczywiście długość dopełnienia ma znaczenie - albo potrzebujesz źródła, które jest większe niż wszystkie możliwe miejsca docelowe, albo potrzebujesz pętli do wielokrotnego kopiowania w szyku porcji danych, aż miejsce docelowe będzie pełne.
Anonimowy użytkownik
Potwierdzenie od:
Jeśli musisz zapełniać duże tablice, chociaż od najnowszego idk 1.8 u102, istnieje szybszy sposób, w którym używa się System.arraycopy.
Możesz przyjrzeć się tej alternatywnej implementacji Arrays.fill:
Według
wzorce
https://github.com/zolyfarkas/ ... .java
JMH, możesz uzyskać prawie dwukrotny wzrost wydajności w przypadku dużych macierzy (1000+)
W każdym razie te implementacje powinny być używane tylko w razie potrzeby. JDKs Arrays.fill powinien być preferowanym wyborem.