Why do I need to copy an array to use a method on it?
When you use Array(arrayLength)
to create an array, you will have:
The array does not actually contain any values, not evena new JavaScript array with its length property set to that number (Note: this implies an array of arrayLength empty slots, not slots with actual undefined values).
undefined
values - it simply has a length
property.When you spread an iterable object with a length
property into an array, spread syntax accesses each index and sets the value at that index in the new array. For example:
const arr1 = [];arr1.length = 4;// arr1 does not actually have any index properties:console.log('1' in arr1);
const arr2 = [...arr1];console.log(arr2);console.log('2' in arr2);
Why clone() is the best way for copying arrays?
I would like to make some points about why clone()
is the fastest way to copy an array than System.arraycopy(..)
or others:
1. clone()
doesn't have to do the typechecking before copying a source array to the destination one as provided here. It just simple allocates new memory space and assigns the objects to it. On the other hand, System.arraycopy(..)
checks for the type and then copies an array.
2. clone()
also breaks the optimization to eliminate redundant zeroing. As you know, every allocated array in Java must be initialized with 0s
or respective default values. However, JIT can avoid zeroing this array if it sees that the array is filled right after creation. That makes it definitely faster compared to changing the copy values with existing 0s
or respective default values. While using System.arraycopy(..)
spends significant amount of time clearing and copying the initialized array. To do so I have performed some of the benchmark tests.
@BenchmarkMode(Mode.Throughput)
@Fork(1)
@State(Scope.Thread)
@Warmup(iterations = 10, time = 1, batchSize = 1000)
@Measurement(iterations = 10, time = 1, batchSize = 1000)
public class BenchmarkTests {
@Param({"1000","100","10","5", "1"})
private int size;
private int[] original;
@Setup
public void setup() {
original = new int[size];
for (int i = 0; i < size; i++) {
original[i] = i;
}
}
@Benchmark
public int[] SystemArrayCopy() {
final int length = size;
int[] destination = new int[length];
System.arraycopy(original, 0, destination, 0, length);
return destination;
}
@Benchmark
public int[] arrayClone() {
return original.clone();
}
}
Output:Benchmark (size) Mode Cnt Score Error Units
ArrayCopy.SystemArrayCopy 1 thrpt 10 26324.251 ± 1532.265 ops/s
ArrayCopy.SystemArrayCopy 5 thrpt 10 26435.562 ± 2537.114 ops/s
ArrayCopy.SystemArrayCopy 10 thrpt 10 27262.200 ± 2145.334 ops/s
ArrayCopy.SystemArrayCopy 100 thrpt 10 10524.117 ± 474.325 ops/s
ArrayCopy.SystemArrayCopy 1000 thrpt 10 984.213 ± 121.934 ops/s
ArrayCopy.arrayClone 1 thrpt 10 55832.672 ± 4521.112 ops/s
ArrayCopy.arrayClone 5 thrpt 10 48174.496 ± 2728.928 ops/s
ArrayCopy.arrayClone 10 thrpt 10 46267.482 ± 4641.747 ops/s
ArrayCopy.arrayClone 100 thrpt 10 19837.480 ± 364.156 ops/s
ArrayCopy.arrayClone 1000 thrpt 10 1841.145 ± 110.322 ops/s
According to the outputs I am getting that clone
is almost twice fast from System.arraycopy(..)
3. Also, using manual copying method like clone()
results into faster ouput because it doesn't have to make any VM calls (unlike System.arraycopy()
).
Is it necessary to deep copy an array in java?
You are not breaking OOP principals. However, you are breaking principals of functional programming. Functional programming views leaking of access as losing of control.
Whether or not you want to practice functional programming is up to you, Java doesn't take a stance in that matter.
You may want to consider if it's important not to leak access for this particular class. If you find it important not to leak access then make this class immutable.
You can also guard the instance variables. In this scenario any possible changes to the variables must be handled by the instance class. However, the instance could be modified from separate contexts and result in loss of control. For this reason functional programming only allows immutable classes.
Copy array by value
Use this:
let oldArray = [1, 2, 3, 4, 5];
let newArray = oldArray.slice();
console.log({newArray});
Is there a function to copy an array in C/C++?
Since C++11, you can copy arrays directly with std::array
:
std::array<int,4> A = {10,20,30,40};
std::array<int,4> B = A; //copy array A into array B
Here is the documentation about std::array Clone method for Java arrays
When the clone
method is invoked upon an array, it returns a reference to a new array which contains (or references) the same elements as the source array.
So in your example, int[] a
is a separate object instance created on the heap and int[] b
is a separate object instance created on the heap. (Remember all arrays are objects).
int[] a = {1,2,3};
int[] b = a.clone();
System.out.println(a == b ? "Same Instance":"Different Instance");
//Outputs different instance
If were to modify int[] b
the changes would not be reflected on int[] a
since the two are separate object instances. b[0] = 5;
System.out.println(a[0]);
System.out.println(b[0]);
//Outputs: 1
// 5
This becomes slightly more complicated when the source array contains objects. The clone
method will return a reference to a new array, which references the same objects as the source array.So if we have the class Dog
...
class Dog{
private String name;
public Dog(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and I create and populate an array of type Dog
... Dog[] myDogs = new Dog[4];
myDogs[0] = new Dog("Wolf");
myDogs[1] = new Dog("Pepper");
myDogs[2] = new Dog("Bullet");
myDogs[3] = new Dog("Sadie");
then clone dog... Dog[] myDogsClone = myDogs.clone();
the arrays refer to the same elements... System.out.println(myDogs[0] == myDogsClone[0] ? "Same":"Different");
System.out.println(myDogs[1] == myDogsClone[1] ? "Same":"Different");
System.out.println(myDogs[2] == myDogsClone[2] ? "Same":"Different");
System.out.println(myDogs[3] == myDogsClone[3] ? "Same":"Different");
//Outputs Same (4 Times)
This means if we modify an object accessed through the cloned array, the changes will be reflected when we access the same object in the source array, since they point to the same reference. myDogsClone[0].setName("Ruff");
System.out.println(myDogs[0].getName());
//Outputs Ruff
However, changes to the array itself will only affect that array. myDogsClone[1] = new Dog("Spot");
System.out.println(myDogsClone[1].getName());
System.out.println(myDogs[1].getName());
//Outputs Spot
// Pepper
If you generally understand how object references work, it is easy to understand how arrays of objects are impacted by cloning and modifications. To gain further insight into references and primitives I would suggest reading this excellent article.Gist of Source Code
Write a generic method to copy an array
You can use the concept of reflection to write a generic copy method that can determine type at runtime. In a nutshell, reflection is the ability to inspect classes, interfaces, fields and methods at runtime without knowing the names of classes, methods etc at compile time.
java.lang.Reflect together with java.lang.Class comprise the Java Reflection API. This method uses both of those classes and some of their methods to make a generic arrayCopy
method that will find out the type for us.
More info: What is reflection and why is it useful?
Syntax that may be unfamiliar
Class<?>
is using a wildcard operator ?
which basically says that we can have a Class
object of unknown type - a generic version of class Class
.<T>
is a generic operator that stands for raw typeArray
The Array class provides static methods to dynamically create and access Java arrays. i.e. This class contains methods that allow you to set and query the values of array elements, determine the length of the array, and create new instances of arrays. We are going to use Array.newInstance()
Methods from reflection API
getClass ()
- returns an array containing Class objects representing all public classes and interfaces that are members of the represented class object.getComponentType()
- returns the class representing the component type (what type i.e. int, , etc) of the array.newInstance()
- Gets a new instance of an array.private <T> T[] arrayCopy(T[] original) {
//get the class type of the original array we passed in and determine the type, store in arrayType
Class<?> arrayType = original.getClass().getComponentType();
//declare array, cast to (T[]) that was determined using reflection, use java.lang.reflect to create a new instance of an Array(of arrayType variable, and the same length as the original
T[] copy = (T[])java.lang.reflect.Array.newInstance(arrayType, original.length);
//Use System and arraycopy to copy the array
System.arraycopy(original, 0, copy, 0, original.length);
return copy;
}
Related Topics
How to Create an Auto-Complete Combobox
Rendering to Js with Jinja Produces Invalid Number Rather Than String
Why Are Exceptions Used for Rejecting Promises in Js
Check If an Object Implements an Interface at Runtime with Typescript
JavaScript Property with Three Dots (...)
Typeerror: Cannot Read Property 'Setstate' of Undefined
Wait Till a Function with Animations Is Finished Until Running Another Function
What Exactly Can Cause an "Hierarchy_Request_Err: Dom Exception 3"-Error
Render Object Properties in React
Why Is 'This' Undefined Inside Class Method When Using Promises
Convert CSV Data into JSON Format Using JavaScript
What Is the JavaScript Mime Type for the Type Attribute of a Script Tag
How to Make a Directive Update Ng-Model on Jquery on Event
Add Two Functions to Window.Onload