I have an array a which is constantly being updated. Let's say a = [1,2,3,4,5]. I need to make an exact duplicate copy of a and call it b. If a were to change to [6,7,8,9,10], b should still be [1,2,3,4,5]. What is the best way to do this? I tried a for loop like:
for(int i=0; i<5; i++) {
b[i]=a[i];
}
but that doesn't seem to work correctly. Please don't use advanced terms like deep copy, etc., because I do not know what that means.
You can try using System.arraycopy()
int[] src = new int[]{1,2,3,4,5};
int[] dest = new int[5];
System.arraycopy( src, 0, dest, 0, src.length );
But, probably better to use clone() in most cases:
int[] src = ...
int[] dest = src.clone();
you can use
int[] a = new int[]{1,2,3,4,5};
int[] b = a.clone();
as well.
If you want to make a copy of:
int[] a = {1,2,3,4,5};
This is the way to go:
int[] b = Arrays.copyOf(a, a.length);
Arrays.copyOf may be faster than a.clone() on small arrays. Both copy elements equally fast but clone() returns Object so the compiler has to insert an implicit cast to int[]. You can see it in the bytecode, something like this:
ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2
Nice explanation from http://www.journaldev.com/753/how-to-copy-arrays-in-java
Java Array Copy Methods
Object.clone(): Object class provides clone() method and since array
in java is also an Object, you can use this method to achieve full
array copy. This method will not suit you if you want partial copy of
the array.
System.arraycopy(): System class arraycopy() is the best way to do
partial copy of an array. It provides you an easy way to specify the
total number of elements to copy and the source and destination array
index positions. For example System.arraycopy(source, 3, destination,
2, 5) will copy 5 elements from source to destination, beginning from
3rd index of source to 2nd index of destination.
Arrays.copyOf(): If you want to copy first few elements of an array or
full copy of array, you can use this method. Obviously it’s not
versatile like System.arraycopy() but it’s also not confusing and easy
to use.
Arrays.copyOfRange(): If you want few elements of an array to be
copied, where starting index is not 0, you can use this method to copy
partial array.
I have a feeling that all of these "better ways to copy an array" are not really going to solve your problem.
You say
I tried a for loop like [...] but that doesn't seem to be working correctly?
Looking at that loop, there's no obvious reason for it not to work ... unless:
you somehow have the a and b arrays messed up (e.g. a and b refer to the same array), or
your application is multi-threaded and different threads are reading and updating the a array simultaneously.
In either case, alternative ways of doing the copying won't solve the underlying problem.
The fix for the first scenario is obvious. For the second scenario you will have to figure out some way of synchronizing the threads. Atomic array classes don't help because they have no atomic copy constructors or clone methods, but synchronizing using a primitive mutex will do the trick.
(There are hints in your question that lead me to think that this is indeed thread related; e.g. your statement that a is constantly changing.)
You can try using Arrays.copyOf() in Java
int[] a = new int[5]{1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
All solution that call length from array, add your code redundant null checkersconsider example:
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();
}
}
I recommend you not inventing the wheel and use utility class where all necessary checks have already performed. Consider ArrayUtils from apache commons. You code become shorter:
public void someMethod(int[] a) {
int[] b = ArrayUtils.clone(a);
}
Apache commons you can find there
You can also use Arrays.copyOfRange.
Example:
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]
}
This method is similar to Arrays.copyOf, but it's more flexible. Both of them use System.arraycopy under the hood.
See:
https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Arrays.java?av=f
If you must work with raw arrays and not ArrayList then Arrays has what you need. If you look at the source code, these are the absolutely best ways to get a copy of an array. They do have a good bit of defensive programming because the System.arraycopy() method throws lots of unchecked exceptions if you feed it illogical parameters.
You can use either Arrays.copyOf() which will copy from the first to Nth element to the new shorter array.
public static <T> T[] copyOf(T[] original, int newLength)
Copies the specified array, truncating or padding with nulls (if
necessary) so the copy has the specified length. For all indices that
are valid in both the original array and the copy, the two arrays will
contain identical values. For any indices that are valid in the copy
but not the original, the copy will contain null. Such indices will
exist if and only if the specified length is greater than that of the
original array. The resulting array is of exactly the same class as
the original 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 }
or Arrays.copyOfRange() will also do the trick:
public static <T> T[] copyOfRange(T[] original, int from, int to)
Copies the specified range of the specified array into a new array.
The initial index of the range (from) must lie between zero and
original.length, inclusive. The value at original[from] is placed into
the initial element of the copy (unless from == original.length or
from == to). Values from subsequent elements in the original array are
placed into subsequent elements in the copy. The final index of the
range (to), which must be greater than or equal to from, may be
greater than original.length, in which case null is placed in all
elements of the copy whose index is greater than or equal to
original.length - from. The length of the returned array will be to -
from. The resulting array is of exactly the same class as the original
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 }
As you can see, both of these are just wrapper functions over System.arraycopy with defensive logic that what you are trying to do is valid.
System.arraycopy is the absolute fastest way to copy arrays.
For a null-safe copy of an array, you can also use an optional with the Object.clone() method provided in this answer.
int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);
I had a similar problem with 2D arrays and ended here.
I was copying the main array and changing the inner arrays' values and was surprised when the values changed in both copies. Basically both copies were independent but contained references to the same inner arrays and I had to make an array of copies of the inner arrays to get what I wanted.
This is sometimes called a deep copy. The same term "deep copy" can also have a completely different and arguably more complex meaning, which can be confusing, especially to someone not figuring out why their copied arrays don't behave as they should. It probably isn't the OP's problem, but I hope it can still be helpful.
Related
Given an array of size k, with the first n elements assigned a non-null reference, how would I go about returning an array with only the first n elements of size n in Java?
Obviously you could could do a deep copy by creating a new k sized array and then iterate though the initial one n times, transferring the elements at each iteration but then that would be an O(n) operation.
What I thought may be possible from my understanding of how arrays are stored in memory would be to simply change the length property of the array from k to n and then returning the reference of the initial array.
As a pseudo method:
public Foo[] head(Foo[] arr, int n) {
arr.length = n;
return arr;
}
I was wondering if anything can be done to produce this as a constant time operation but I fear that it may be impossible as Java does not support anything like pointer arithmetic.
If this is impossible, what would be the quickest way of providing the same result?
If you must work with raw arrays and not ArrayList then Arrays has what you need. If you look at the source code, these are the absolutely best ways to get a copy of an array. They do have a good bit of defensive programming because the System.arraycopy() method throws lots of unchecked exceptions if you feed it illogical parameters.
You can use either Arrays.copyOf() which will copy from the first to Nth element to the new shorter array.
public static <T> T[] copyOf(T[] original, int newLength)
Copies the specified array, truncating or padding with nulls (if
necessary) so the copy has the specified length. For all indices that
are valid in both the original array and the copy, the two arrays will
contain identical values. For any indices that are valid in the copy
but not the original, the copy will contain null. Such indices will
exist if and only if the specified length is greater than that of the
original array. The resulting array is of exactly the same class as
the original 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 }
or Arrays.copyOfRange() will also do the trick:
public static <T> T[] copyOfRange(T[] original, int from, int to)
Copies the specified range of the specified array into a new array.
The initial index of the range (from) must lie between zero and
original.length, inclusive. The value at original[from] is placed into
the initial element of the copy (unless from == original.length or
from == to). Values from subsequent elements in the original array are
placed into subsequent elements in the copy. The final index of the
range (to), which must be greater than or equal to from, may be
greater than original.length, in which case null is placed in all
elements of the copy whose index is greater than or equal to
original.length - from. The length of the returned array will be to -
from. The resulting array is of exactly the same class as the original
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 }
As you can see, both of these are just wrapper functions over System.arraycopy with defensive logic that what you are trying to do is valid.
System.arraycopy is the absolute fastest way to copy arrays.
You are looking for sublist. (List rather than array)
But, the point is always the same. Save the value of n and the array. You're already done. You can use those for the same thing you'd use a different fake array that pretends to be a different size for, just pretend the array is size n, and use the array.
Though if you must,
List<MyClass> subArray = Arrays.asList(array).subList(index, index2);
Is there an immutable alternative to the primitive arrays in Java? Making a primitive array final doesn't actually prevent one from doing something like
final int[] array = new int[] {0, 1, 2, 3};
array[0] = 42;
I want the elements of the array to be unchangeable.
Not with primitive arrays. You'll need to use a List or some other data structure:
List<Integer> items = Collections.unmodifiableList(Arrays.asList(0,1,2,3));
My recommendation is to not use an array or an unmodifiableList but to use Guava's ImmutableList, which exists for this purpose.
ImmutableList<Integer> values = ImmutableList.of(0, 1, 2, 3);
As others have noted, you can't have immutable arrays in Java.
If you absolutely need a method that returns an array that doesn't influence the original array, then you'd need to clone the array each time:
public int[] getFooArray() {
return fooArray == null ? null : fooArray.clone();
}
Obviously this is rather expensive (as you'll create a full copy each time you call the getter), but if you can't change the interface (to use a List for example) and can't risk the client changing your internals, then it may be necessary.
This technique is called making a defensive copy.
There is one way to make an immutable array in Java:
final String[] IMMUTABLE = new String[0];
Arrays with 0 elements (obviously) cannot be mutated.
This can actually come in handy if you are using the List.toArray method to convert a List to an array. Since even an empty array takes up some memory, you can save that memory allocation by creating a constant empty array, and always passing it to the toArray method. That method will allocate a new array if the array you pass doesn't have enough space, but if it does (the list is empty), it will return the array you passed, allowing you to reuse that array any time you call toArray on an empty List.
final static String[] EMPTY_STRING_ARRAY = new String[0];
List<String> emptyList = new ArrayList<String>();
return emptyList.toArray(EMPTY_STRING_ARRAY); // returns EMPTY_STRING_ARRAY
As of Java 9 you can use List.of(...), JavaDoc.
This method returns an immutable List and is very efficient.
Another one answer
static class ImmutableArray<T> {
private final T[] array;
private ImmutableArray(T[] a){
array = Arrays.copyOf(a, a.length);
}
public static <T> ImmutableArray<T> from(T[] a){
return new ImmutableArray<T>(a);
}
public T get(int index){
return array[index];
}
}
{
final ImmutableArray<String> sample = ImmutableArray.from(new String[]{"a", "b", "c"});
}
Since Guava 22, from package com.google.common.primitives you can use three new classes, which have a lower memory footprint compared to ImmutableList.
ImmutableIntArray
ImmutableLongArray
ImmutableDoubleArray
They also have a builder. Example:
int size = 2;
ImmutableLongArray longArray = ImmutableLongArray.builder(size)
.add(1L)
.add(2L)
.build();
or, if the size is known at compile-time:
ImmutableLongArray longArray = ImmutableLongArray.of(1L, 2L);
This is another way of getting an immutable view of an array for Java primitives.
If you need (for performance reason or to save memory) native 'int' instead of 'java.lang.Integer', then you would probably need to write your own wrapper class. There are various IntArray implementations on the net, but none (I found) was immutable: Koders IntArray, Lucene IntArray. There are probably others.
The of(E... elements) method in Java9 can be used to create immutable list using just a line:
List<Integer> items = List.of(1,2,3,4,5);
The above method returns an immutable list containing an arbitrary number of elements. And adding any integer to this list would result in java.lang.UnsupportedOperationExceptionexception. This method also accepts a single array as an argument.
String[] array = ... ;
List<String[]> list = List.<String[]>of(array);
No, this is not possible. However, one could do something like this:
List<Integer> temp = new ArrayList<Integer>();
temp.add(Integer.valueOf(0));
temp.add(Integer.valueOf(2));
temp.add(Integer.valueOf(3));
temp.add(Integer.valueOf(4));
List<Integer> immutable = Collections.unmodifiableList(temp);
This requires using wrappers, and is a List, not an array, but is the closest you will get.
In some situations, it will be lighter weight to use this static method from Google Guava library: List<Integer> Ints.asList(int... backingArray)
Examples:
List<Integer> x1 = Ints.asList(0, 1, 2, 3)
List<Integer> x1 = Ints.asList(new int[] { 0, 1, 2, 3})
If you want to avoid both mutability and boxing, there is no way out of the box. But you can create a class which holds primitive array inside and provides read-only access to elements via method(s).
Implement java.util.function.IntUnaryOperator:
class ImmutableArray implements IntUnaryOperator {
private final int[] array;
ImmutableArray(int[] array) {
this.array = Arrays.copyOf(array, array.length);
}
#Override
public int applyAsInt(int index) {
return array[index];
}
}
Access the array: array[i] becomes immutableArray.applyAsInt(i).
I benchmarked primitive for loop retrieval with a modulus operation with 100_000_000 elements. The above PrimitiveArray took ~220ms; there was no significant difference with a primitive array. The same op on ArrayList took 480 ms, and the loading process took 21 seconds, depleted my heap space first try, and I had to increase this setting on the JVM. Loading of PrimitiveArray had taken 2 seconds.
iteration
if you want to iterate, implement Iterable and provide
public java.util.PrimitiveIterator.OfInt iterator() { return Arrays.stream(array).iterator(); }
This provides access to int nextInt method.
From PrimitiveIterator you also get method forEachRemaining(PrimitiveConsumer) which is helpful to replace an existing enhanced for loop.
Iterating manually with PrimitiveIterator.OfInt yielded performance of ~300ms.
While it's true that Collections.unmodifiableList() works, sometimes you may have a large library having methods already defined to return arrays (e.g. String[]).
To prevent breaking them, you can actually define auxiliary arrays that will store the values:
public class Test {
private final String[] original;
private final String[] auxiliary;
/** constructor */
public Test(String[] _values) {
original = new String[_values.length];
// Pre-allocated array.
auxiliary = new String[_values.length];
System.arraycopy(_values, 0, original, 0, _values.length);
}
/** Get array values. */
public String[] getValues() {
// No need to call clone() - we pre-allocated auxiliary.
System.arraycopy(original, 0, auxiliary, 0, original.length);
return auxiliary;
}
}
To test:
Test test = new Test(new String[]{"a", "b", "C"});
System.out.println(Arrays.asList(test.getValues()));
String[] values = test.getValues();
values[0] = "foobar";
// At this point, "foobar" exist in "auxiliary" but since we are
// copying "original" to "auxiliary" for each call, the next line
// will print the original values "a", "b", "c".
System.out.println(Arrays.asList(test.getValues()));
Not perfect, but at least you have "pseudo immutable arrays" (from the class perspective) and this will not break related code.
Well.. arrays are useful to pass as constants (if they were) as variants parameters.
My issue is I am trying to reverse an array. The method I have found that apparently works for this is to use
Collections.reverse(Arrays.asList(arrx));
However I want to store it back into an array for future use.
I'm not quite familiar with Collections to begin with, I did go over the documentation for it however in terms of storing this back into an array i'm a little lost.
How would you go about this?
Thanks.
Collections.toArray() is your friend. It has two methods a type safe and a non type safe one (preferred to use type safe).
Integer[] a = new Integer[] {1,2,3};
List<Integer> l = Arrays.asList(a);
Collections.reverse(l);
l.toArray(a);
If possible using Collections instead of arrays is the best practice.
The following consideration is slightly academic, however I felt that it should be pointed out:
Arrays#asList will give you a "view" on the supplied array. The JavaDoc says: "Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.)". Looking at your example:
String[] arrx = {"alpha", "beta", "gamma"};
Collections.reverse(Arrays.asList(arrx));
System.out.println(Arrays.toString(arrx)); // [gamma, beta, alpha]
... this means, that the original array arrx will be reversed. If you just need the reversed array, all is fine. However: If you still need the original array, create a copy before reversing:
String[] arrx = {"alpha", "beta", "gamma"};
List temp = new ArrayList(Arrays.asList(arrx));
Collections.reverse(temp);
Object[] reversedArrx = temp.toArray();
System.out.println(Arrays.toString(arrx)); // [alpha, beta, gamma]
System.out.println(Arrays.toString(reversedArrx)); // [gamma, beta, alpha]
(Generics omitted for brevity).
And what about a for loop ? it would be like:
static void reverse(int[] t){
for(int x=0; x<t.length / 2; x++){
int y = t[x];
t[x] = t[t.length - 1 - x];
t[t.length - 1 - x] = y;
}
}
How would I copy an array say
float arraytobecopied[] = {1.20,2.50,3.60};
to another array that has data in it already say
float newarray[] = {5.20,6.30,4.20};
I want to add the the arraytobecopied to the end of the new array and keep the values in the array. also as a side note this would be an on going process adding to the end of the array every time.
Should i just use a for loop? or is there a better way.
(Can't use Array) already tried:(
This question has been asked here before, You can see this page for the answer. How can I concatenate two arrays in Java?
Use System.arraycopy
public static void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length)
You can't increase the size of the original array. But you could create a new array, copy both source arrays into it, and assign your reference variable to it.
For example, here's a sketch of a simple implementation. (An alternative is to use System.arraycopy().)
float[] newerArray = new float[ newarray.length + arraytobecopied.length ];
for ( int i = 0; i < newarray.length; ++i ) {
newerArray[i] = newarray[i];
}
for ( int i = 0; i < arraytobecopied.length; ++i ) {
newerArray[ newarray.length + i ] = arraytobecopied[i];
}
newarray = newerArray; // Point the reference at the new array
Alternatively, you could use a java.util.ArrayList, which automatically handles growing the internal array. Its toArray() methods make it easy to convert the list to an array when required.
The easiest approach from a programming perspective is to use a List<Float> (if you can use Float values instead of float) or a third-party library such as Apache Commons Collections or Trove that provides dynamic arrays of primitives.
If you need to use a simple array of primitives (and not a wrapper class), you can use a couple of methods in the java.util.Arrays and java.lang.System classes to help:
int len1 = newarray.length;
int len2 = arraytobecopied.length;
float[] result = Arrays.copyOf(newarray, len1 + len2);
System.arraycopy(arraytobecopied, 0, result, len1, len2);
// result now contains the concatenation of newarray and arraytobecopied
Note that you cannot change the length of an array object; you can only reassign the variable to a new array (e.g., newarray = result;).
The easiest can be:
List<Float> floats = new ArrayList(arraytobecopied);
floats.addAll(newarray);
arraytobecopied = floats.toArray(new float[0]);
If you dont want to use anything from java.Util at all.
How about writing one method that updates the destination array with src array. Now when u copy elements make sure that the size is enough in destination array. Otherwise when you create a new array, create it with double size and copy the elements, this may help in avoiding a new array creation everytime and doing iterations to populate the complete array again after resizing.
Somewhat similar to how array list maintains size of array inside it.
As far as I understand we can use java.util.Arrays.copyOf to copy a two dimensional array, but is it safe to use it for defensive copying (assuming elements are immutable)? E.g.
void setValues(Integer[][] arr) {
this.arr = Arrays.copyOf(arr, arr.length);
}
Arrays.copyOf uses System.arraycopy internally, so no, it is not appropriate for making defensive (deep) copies (not for mutable types at least).
No, it's not a deep copy. arr looks like this (mocking up memory addresses):
#0x01 [
#0x10 [1,2],
#0x20 [2,3],
#0x30 [4,5],
]
When you make a copy with Arrays.copyOf, you get a new outer array, so this.arr will be:
#0x02 [
#0x10 [1,2],
#0x20 [2,3],
#0x30 [4,5],
]
If you want to be sure your 2d array won't change, you do this:
this.arr = new Integer[arr.length][];
for (int i = 0; i < arr.length; i++) {
this.arr[i] = Arrays.copyOf(arr[i], arr[i].length);
}
Now this is only safe because Integer is immutable. If it was something more complex, you'd have to work out how to safely copy that, which might involve more copies. Java doesn't provide a free deep-copy for you.
It is not deep copy its shallow copy.
It copies the specified array, truncating or padding with nulls (if necessary) so the copy has the specified length. For all indices that are valid in both the original array and the copy, the two arrays will contain identical values.
2771 public static <T,U> T[] 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 }
Code reference - open jdk 6-b14