Maak een kopie van een array

Ik heb een array adie constant wordt bijgewerkt. Laten we zeggen a = [1,2,3,4,5]. Ik moet een exacte kopie maken van aen deze bnoemen. Als azou veranderen in [6,7,8,9,10], zou bnog steeds [1,2,3,4,5]. Wat is de beste manier om dit te doen? Ik heb een for-lus geprobeerd, zoals:

for(int i=0; i<5; i++) {
    b[i]=a[i];
}

maar dat lijkt niet goed te werken. Gebruik geen geavanceerde termen zoals deep copy, enz., want ik weet niet wat dat betekent.


Antwoord 1, autoriteit 100%

Je kunt proberen System.arraycopy()

int[] src  = new int[]{1,2,3,4,5};
int[] dest = new int[5];
System.arraycopy( src, 0, dest, 0, src.length );

Maar in de meeste gevallen is het waarschijnlijk beter om clone() te gebruiken:

int[] src = ...
int[] dest = src.clone();

Antwoord 2, autoriteit 41%

u kunt gebruiken

int[] a = new int[]{1,2,3,4,5};
int[] b = a.clone();

ook.


Antwoord 3, autoriteit 32%

Als u een kopie wilt maken van:

int[] a = {1,2,3,4,5};

Dit is de manier om te gaan:

int[] b = Arrays.copyOf(a, a.length);

Arrays.copyOfis mogelijk sneller dan a.clone()op kleine arrays. Beide kopieerelementen zijn even snel, maar clone() retourneert Object, dus de compiler moet een impliciete cast invoegen in int[]. Je kunt het zien in de bytecode, ongeveer als volgt:

ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2

Antwoord 4, autoriteit 11%

Leuke uitleg van http://www.journaldev.com /753/hoe-matrices-in-java te kopiëren

Java-array-kopieermethoden

Object.clone(): Object klasse biedt clone() methode en aangezien array
in java is ook een object, u kunt deze methode gebruiken om volledig te bereiken
array kopie. Deze methode is niet geschikt voor u als u een gedeeltelijke kopie wilt van
de array.

System.arraycopy(): systeemklasse arraycopy() is de beste manier om
gedeeltelijke kopie van een array. Het biedt u een gemakkelijke manier om de
totaal aantal te kopiëren elementen en de bron- en doelarray
indexposities. Bijvoorbeeld System.arraycopy(bron, 3, bestemming,
2, 5)
kopieert 5 elementen van bron naar bestemming, te beginnen vanaf
3e index van bron tot 2e index van bestemming.

Arrays.copyOf():Als u de eerste paar elementen van een array of
volledige kopie van array, kunt u deze methode gebruiken. Het is duidelijk niet
veelzijdig zoals System.arraycopy() maar het is ook niet verwarrend en gemakkelijk
te gebruiken.

Arrays.copyOfRange(): als u enkele elementen van een array wilt
gekopieerd, waarbij de startindex niet 0 is, kunt u deze methode gebruiken om te kopiëren
gedeeltelijke array.


Antwoord 5, Autoriteit 6%

Ik heb het gevoel dat al deze “betere manieren om een ​​array te kopiëren” niet echt uw probleem op te lossen.

u zegt

Ik probeerde een voor lus zoals […] maar dat lijkt niet correct te werken?

Kijkend naar die lus, er is geen voor de hand liggende reden omdat het niet werkt … Tenzij:

  • U hebt op de een of andere manier de aen barrays in de war (bijv. aEN bverwijzen naar hetzelfde array), of
  • Uw aanvraag is multi-threaded en verschillende threads lezen en bijwerken van de aarray gelijktijdig.

In beide gevallen zullen alternatieve manieren van het kopiëren het onderliggende probleem niet oplossen.

De oplossing voor het eerste scenario is duidelijk. Voor het tweede scenario moet je een manier vinden om de draden te synchroniseren. Atomic Array-klassen helpen niet omdat ze geen atomaire kopie-constructeurs of kloonmethoden hebben, maar synchroniseren met behulp van een primitieve mutex zullen de truc doen.

(er zijn hints in uw vraag die me ertoe leiden dat dit inderdaad gerelateerd is, b.v. Uw verklaring dat aconstant verandert.)


Antwoord 6, Autoriteit 3%

U kunt proberen arrays.copyof () in Java

te gebruiken

int[] a = new int[5]{1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);

Antwoord 7, Autoriteit 2%

Alle oplossing die lengte van array bellen, voeg uw code redundant NULL CheckersSconsider Voorbeeld:

int[] a = {1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();
//What if array a comes as local parameter? You need to use null check:
public void someMethod(int[] a) {
    if (a!=null) {
        int[] b = Arrays.copyOf(a, a.length);
        int[] c = a.clone();
    }
}

Ik raad u aan om het wiel niet te bedenken en gebruik van hulpprogramma’s waar alle benodigde controles al hebben uitgevoerd. Overweeg arrayutils van Apache Commons. Je codeert wordt korter:

public void someMethod(int[] a) {
    int[] b = ArrayUtils.clone(a);
}

Apache Commons U kunt daar


Antwoord 8, Autoriteit 2%

U kunt Arrays.copyOfRange.

voorbeeld :

public static void main(String[] args) {
    int[] a = {1,2,3};
    int[] b = Arrays.copyOfRange(a, 0, a.length);
    a[0] = 5;
    System.out.println(Arrays.toString(a)); // [5,2,3]
    System.out.println(Arrays.toString(b)); // [1,2,3]
}

Deze methode is vergelijkbaar met Arrays.copyOf, maar het is flexibeler. Beide gebruiken System.arraycopyonder de kap.

Zie :


Antwoord 9

Voor een null-safe-kopie van een array, kunt u ook een optioneel gebruiken met de Object.clone()methode in deze Antwoord .

int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);

Antwoord 10

Als u moet werken met rauwe arrays en niet ArrayListdan Arraysheeft wat u nodig hebt. Als u naar de broncode kijkt, zijn dit de absoluut de beste manieren om een ​​kopie van een array te krijgen. Ze hebben een goed bit van defensieve programmering omdat de System.arraycopy()Method met veel niet-gecontroleerde uitzonderingen gooit als u IT ILLOGICAL PARAMETERS voedt.

u kunt Arrays.copyOf()die van de eerste naar Nth-element naar de nieuwe kortere array kopiëren.

public static <T> T[] copyOf(T[] original, int newLength)

Kopieert de opgegeven array, het afknippen of opvullen met nulls (als
noodzakelijk), zodat de kopie de opgegeven lengte heeft. Voor alle indices die
zijn geldig in zowel de originele array als de kopie, de twee arrays zullen
bevatten identieke waarden. Voor eventuele indices die geldig zijn in de kopie
Maar niet het origineel, de kopie bevat null. Dergelijke indices zullen
bestaan ​​als en alleen als de opgegeven lengte groter is dan die van de
Originele array. De resulterende array is van precies dezelfde klas als
de originele array.

2770
2771    public static <T,U> T[] More ...copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2772        T[] copy = ((Object)newType == (Object)Object[].class)
2773            ? (T[]) new Object[newLength]
2774            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
2775        System.arraycopy(original, 0, copy, 0,
2776                         Math.min(original.length, newLength));
2777        return copy;
2778    }

of Arrays.copyOfRange()zal ook de kunst doen:

public static <T> T[] copyOfRange(T[] original, int from, int to)

Kopieert het opgegeven bereik van de opgegeven array in een nieuwe array.
De eerste index van het bereik (van) moet tussen nul liggen en
Original.Lengte, inclusief. De waarde bij origineel [van] is geplaatst
het initiële element van de kopie (tenzij van == origineel.lengte of
van == naar). Waarden van volgende elementen in de originele array zijn
in de volgende elementen in de kopie geplaatst. De laatste index van de
bereik (naar), dat groter moet zijn dan of gelijk aan van, kan zijn
groter dan origineel.length, in welk geval null in alles wordt geplaatst
Elementen van de kopie waarvan de index groter is dan of gelijk aan
Origineel.Lengte – van. De lengte van de geretourneerde array zal zijn –
van. De resulterende array is van precies dezelfde klas als het origineel
array.

3035    public static <T,U> T[] More ...copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
3036        int newLength = to - from;
3037        if (newLength < 0)
3038            throw new IllegalArgumentException(from + " > " + to);
3039        T[] copy = ((Object)newType == (Object)Object[].class)
3040            ? (T[]) new Object[newLength]
3041            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
3042        System.arraycopy(original, from, copy, 0,
3043                         Math.min(original.length - from, newLength));
3044        return copy;
3045    }

Zoals je kunt zien, zijn beide slechts wrapper-functies over System.arraycopymet defensieve logica dat wat je probeert te doen geldig is.

System.arraycopyis de absoluut snelste manier om arrays te kopiëren.


Antwoord 11

Ik had een soortgelijk probleem met 2D-arrays en eindigde hier.
Ik kopieerde de hoofdarray en veranderde de waarden van de binnenste arrays en was verrast toen de waarden in beide kopieën veranderden. In principe waren beide kopieën onafhankelijk, maar bevatten ze verwijzingen naar dezelfde binnenste arrays en ik moest een reeks kopieën van de binnenste arrays maken om te krijgen wat ik wilde.

Dit wordt soms een diepe kopie genoemd. Dezelfde term “diepe kopie” kan ook een heel andere en aantoonbaar complexere betekenis hebben, wat verwarrend kan zijn, vooral voor iemand die niet uitzoekt waarom hun gekopieerde arrays zich niet gedragen zoals zou moeten. Het is waarschijnlijk niet het probleem van de OP, maar ik hoop dat het toch nuttig kan zijn.

Other episodes