Truncate an array without copying it? - java

In Java, is there a way to truncate an array without having to make a copy of it? The common idiom is Arrays.copyOf(foo, n) (where the new array is n elements long). I don't think there is an alternative, but I'm curious as to whether there is a better approach.

An array's length in Java cannot be altered after initialization, so you're forced to make a copy with the new size. Actually, the length parameter of a Java array is declared as final, so it cannot be changed once it's set.
If you need to change an array's size, I'd use an ArrayList.

I was thinking about it some more... and just for kicks, how about something like the below.
Note: This is just a "can it be done?" intellectual exercise in Java hacking. Anybody who attempts to actually use this idea in production code will deserve all the pain that will undoubtedly follow.
public class Foo
{
private static byte[] array = new byte[10];
public static void main(String[] arg) throws Exception
{
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
Field arrayField = Foo.class.getDeclaredField("array");
long ptr = unsafe.staticFieldOffset(arrayField);
// doesn't work... there's gotta be a way though!
unsafe.reallocateMemory(ptr, 5);
System.out.println("New array size is: " + array.length);
}
}

I don't believe so. An array is allocated as a contiguous block of memory, and I can't imagine that there is any way of releasing a part of that block.

Succinctly: No, There isn't, as far as I know. A Java array is a fixed-size data-structure. The only way to "logically" resize it is create a new array and copy the wanted elements into the new array.
Instead: You could (possibly) implement a class which wraps an array into a collection and uses a "size" variable to logically reduce the length of the array without actually copying the values. This an approach has limited utility... The only case I can imagine where it's practical is when you're dealing with a huge array, which just can't be copied because of memory limitations.
Copying an array is relatively inexpensive time-wise... unless you're doing it millions of times, in which case you probably need to think up an algorithm to avoid this, and not waste your time mucking around with a "variable length array".
And of course... you could just use an ArrayList instead. Yes?

Related

Findbugs assigning byte array value through parameter or clone()

so for example I have this constructor
public Example(byte[] bytes) {
this.bytes = bytes;
}
And after running FindBugs, it will say that I should consider cloning it instead... so I tried that and it eliminated the warning.
public Example(byte[] bytes) {
this.bytes = bytes.clone();
}
However, I want to know if there are any implications, or negative side-effects to this kind of change. From my understanding, it also applies to all arrays, not just byte[].
Thanks
The possible bug would be that if you reuse the array in the instance you'll couple it with the calling code, i.e. every change made to the array but outside that class might have side effects.
Example:
char[] chars = new char[]{ 'a', 'b', 'c', ..., 'z' };
Alphabet lower = new Alphabet( chars );
for( int i = 0; i < chars.length; i++ ) {
chars[i] = Character.toUpperCase( chars[i] );
}
Alphabet upper = new Alphabet( chars );
If the array is reused inside Alphabet (i.e. not cloned) you might think that lower deals with lower case characters while it's really using the array whose elements have been replaced with their upper case counter part.
Thus in most cases it is safer to create a copy of the array, e.g. by calling clone() on it (there are other ways as well).
The downside to this are an increased memory usage (of course) and some performance cost for doing the copy - both of which might be negligible for a few small arrays but increase when the size and/or the number of arrays increases.
Another downside might be that the calling code could expect the array to be shared and creating a clone might break that. You'd have to check for that as well.
This is a very generic situation - when you create an object that depends on some "outside" array or list - should that object simply re-use the existing reference; or do you need to create a copy of that input data?!
Re-using means: you don't spend CPU cycles on copy operations; and obviously, you re-use memory as well (one copy of things, instead of two, three, ...)
On the other hand: when you keep references, and somebody else updates that "external" thing ... all your objects that hold that reference might be affected as well.
In that sense: you should balance those two options mainly based on what is "best" from a design point of view. In general, many people nowadays tries to implement immutable classes/objects. Meaning: upon creation, the "content" of an object will never change again; in other words: if you want to go immutable, you have to turn to "defensive copying". But there are lot of things to gain from that.
The idea is to take a defensive copy, so that subsequent updates to the array don't write through to Example object. It also helps with garbage collection as you are not holding on to a reference to the array.
In terms of implications, you are potentially using more memory as you might end up storing the array twice.

Why java allows zero length index(in middle) array?

javac allows below syntax,
int[][][] i = new int[4][0][2];
which has zero length index that prevents access beyond.
1) There is no way to access third dimension. zero length dimension as last dimension(int[][][] i = new int[4][2][0];) looks fine.
2) It is not possible to write an initialiser for a multi-dimensional array with a zero length dimension unless that dimension is the last( for instance int[2][3][0]).
Why java allows such syntax?
Note: this question has nothing to do with int[0]
Because nothing in the multianewarray bytecode instruction prevents you from doing so.
There is really no better answer than that... The fact is that for any X, even if X is a primitive, then X[] is a class, X[][] is a class and so on; and you are free to choose the "dimensions" of the array.
Note how declaring a X[n][] and a X[n][m] array differ: in the first you'll declare a anewarray of X[] whereas in the second you'll declare a multianewarray of X.
Of course, in X[m][n][p], there is no possibility to ever have a "third dimension" (p) if n is 0, but... Well, the programmer knows what he's doing, right?
Just another bizarreness of arrays in the JVM... Think nothing of it except that "it can happen" ;)
I agree with #m0skit0 - I think this is a duplicate questions. However I will give a brief answer anyways.
Basically its an alternative for null. Consider simply, you have a method that returns an array, but it has no value to return. You could return null, but then you have to check for null in your code. On the other hand, you could return a 0 length array. Code such as the follows would automatically be skipped.
for(int p = 0; p < array.length; p++) {
So you can do perfectly acceptable stuff like:
public static final int[][][] EMPTYARRAY = new int[0][0][0];
note also things a much worse than you suppose because this is also legal:
public static final int[] SCREWEDARRAY = new int[-1];
which causes a runtime error:
java.lang.ExceptionInInitializerError
Caused by: java.lang.NegativeArraySizeException
First of all, it's not just in "the middle". You can easily define a one dimensional array just as easily:
int[] a = new int[0];
Second, an array with zero length is a bit like an empty collection. It's a legal data structure which might be returned by a method, but which happens to be empty.

Optimizing Java Array Copy

So for my research group I am attempting to convert some old C++ code to Java and am running into an issue where in the C++ code it does the following:
method(array+i, other parameters)
Now I know that Java does not support pointer arithmetic, so I got around this by copying the subarray from array+i to the end of array into a new array, but this causes the code to run horribly slow (I.e. 100x slower than the C++ version). Is there a way to get around this? I saw someone mention a built-in method on here, but is that any faster?
Not only does your code become slower, it also changes the semantic of what is happening: when you make a call in C++, no array copying is done, so any change the method may apply to the array is happening in the original, not in the throw-away copy.
To achieve the same effect in Java change the signature of your function as follows:
void method(array, offset, other parameters)
Now the caller has to pass the position in the array that the method should consider the "virtual zero" of the array. In other words, instead of writing something like
for (int i = 0 ; i != N ; i++)
...
you would have to write
for (int i = offset ; i != offset+N ; i++)
...
This would preserve the C++ semantic of passing an array to a member function.
The C++ function probably relied on processing from the beginning of the array. In Java it should be configured to run from an offset into the array so the array doesn't need to be copied. Copying the array, even with System.arraycopy, would take a significant amount of time.
It could be defined as a Java method with something like this:
void method(<somearraytype> array, int offset, other parameters)
Then the method would start at the offset into the array, and it would be called something like this:
method(array, i, other parameters);
If you wish to pass a sub-array to a method, an alternative to copying the sub-array into a new array would be to pass the entire array with an additional offset parameter that indicates the first relevant index of the array. This would require changes in the implementation of method, but if performance is an issue, that's probably the most efficient way.
The right way to handle this is to refactor the method, to take signature
method(int[] array, int i, other parameters)
so that you pass the whole array (by reference), and then tell the method where to start its processing from. Then you don't need to do any copying.

About performance (memory or cpu)

this question is about java coding, my question is easy so i'll explain it with a little example :)
I have a String array full of arguments, and i have to check it's length several times, so, it's better to save the amount of arguments (array length) in a variable, or just call the length every single time?, i suppose that storing a variable will consume more memory, and the other way will use more cpu, just want to ask what do you think is better thanks!
Example:
String[] arguments = {"a","b","c"};
int numberOfArguments = arguments.length;
if(numberOfArguments == 1)do whatever
if(numberOfArguments == 2)do whatever
if(numberOfArguments == 3)do whatever
etc
OR
String[] arguments = {"a","b","c"};
if(arguments.length == 1)do whatever
if(arguments.length == 2)do whatever
if(arguments.length == 3)do whatever
EDIT: i know the difference will be really small.. but i'm asking for a LONG PROCESS, think big, a million of "arguments.length", so for that case i think is better to sacrifice a ultra small amount of memory to store the variable which should be better for the cpu than checking the arguments lenght a million of times than checking a variable value which is always the same, what do you think?
This is a premature optimization; do whatever you find more readable/easier to manage. Personally, I prefer to just refer to the length field directly because I see no point in storing it in another variable (unless, perhaps, the length of the array has a different meaning in the context of your program than simply a count of elements - in such a case it might be appropriate to store it in a reasonably named variable). In any case, you can rest assured that there will be no appreciable performance difference between the two.
By the way, array.length might even be faster in some cases (assuming you're able to see any time difference whatsoever) than storing the length in a local variable and using that instead. There's even a bytecode operand reserved specifically for this: be (arraylength), not to mention the optimizations that will be made along the way.
First of all: you can't compare storage with speed, those are different things.
What you can do is determine how much you value each. If you need 100% speed, you will go for the speed option and vice versa.
Usually you want an equal consideration, which brings us to this:
it's up to your own preference. Will you often access that property? Maybe it's interesting to store it in a variable.
See for yourself what you find easier to use: your example has very little influence either way. Retrieving the size of a list is already stored in a variable so there's no looping going on.
The difference in both is creating one extra variable versus getting length of array, the difference will depend on how you are using this code.
If you create a millions instances of this class, then in first approach you will be creating million variable and you can now think of memory being used more in first approach.
Reading length of array is not expensive, so in nutshell it really depend on how is this code being used in your project.
Leaving everything aside, since length is being used multiple times creating a variable is a good practice.
Cheers !!
Object oriented programming saves you having to do long if statements. Calculate the number of arguments once, and create an instance of the specific class for that scenario. Then you can call any method on that instance and it will act in a 'do whatever' manner for that situation.
(forgive my rusty Java...)
public interface Arguments{
void foo();
}
public class OneArgument implements Arguments{
public void foo(){
// do whatever
}
}
public class TwoArguments implements Arguments{
public void foo(){
// do whatever
}
}
public class ThreeArguments implements Arguments{
public void foo(){
// do whatever
}
}
Then you could have a factory method:
public static Arguments create(String[] args){
if(args.length == 1) return new OneArgument();
else if(args.length == 2) return new TwoArguments();
else if(args.length == 3) return new ThreeArguments();
else throw new Exception();
}
Better thought out architecture will most likely yield better performance in the long run.

Preventing allocation for ArrayList iterators in Java

So I am part way through writing my first game on Android and after watching a lengthy presentation on optimising for games, I have been checking my allocations. I have managed to get rid of all in-game allocations apart from ones made my ArrayList when it creates an implicit iterator for the for(Object o : m_arrayList) convention.
There are a fair few of these iterations/allocations since all of my game objects, ai entities etc. are stored in these for their ease of use.
So what are my options?
I could, theoretically specify sensible upperbounds and use arrays, but I like the features of ArrayList such as exists and remove that keep code clean and simple.
Override ArrayList and provide my own implementation of iterator() that returns a class member rather than allocating a new iterator type each time it is used.
I would prefer to go for option 2 for ease of use, but I had a little go at this and ran into problems. Does anyone have an example of what I described in option 2 above? I was having problems inheriting from a generic class, type clashes apparently.
The second question to this then is are there any other options for avoiding these allocations?
And I guess as a bonus question, Does anyone know if ArrayList preallocates a number of memory slots for a certain amount (specified either in the ctor or as some shiftable value) and would never need to do any other allocations so long as you stay within those bounds? Even after a clear()?
Thanks in advance, sorry there is so much there but I think this information could be useful to a lot of people.
Use positional iteration.
for ( int i = 0, n = arrayList.size( ); i < n; ++i )
{
Object val = arrayList.get( i );
}
That's how it was done before Java 5.
For preallocation.
ArrayList arrayList = new ArrayList( numSlots );
or at runtime
arrayList.ensureCapacity( numSlots );
And for a bonus -> http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html
I'll answer the bonus question first: Yes, ArrayList does pre-allocate slots. It has a constructor that takes the desired number of slots as an argument, e.g. new ArrayList<Whatever>(1000). clear does not deallocate any slots.
Returning a shared iterator reference has a few problems. The main problem is that you have no way of knowing when the iterator should be reset to the first element. Consider the following code:
CustomArrayList<Whatever> list = ...
for (Whatever item : list) {
doSomething();
}
for (Whatever item : list) {
doSomethingElse();
}
The CustomArrayList class has no way of knowing that its shared iterator should be reset between the two loops. If you just reset it on every call to iterator(), then you'll have a problem here:
for (Whatever first : list) {
for (Whatever second : list) {
...
}
}
In this case you do not want to reset the iterator between calls.
#Alexander Progrebnyak's answer is probably the best way to iterate over a list without using an Iterator; just make sure you have fast random access (i.e. don't ever use a LinkedList).
I'd also like to point out that you are getting into some pretty heavy micro-optimization here. I'd suggest that you profile your code and find out if allocating iterators is a genuine problem before you invest much time in it. Even in games you should only optimize what needs optimizing, otherwise you can spend many, many days shaving a few milliseconds off a minute-long operation.

Categories

Resources