Reference (not copy) a subrange of a one-dimensional array? - java

Suppose I have the following method signature
int f (int[] values)
and I call it like this:
int[] myValues = {1,2,3,4,5}
f (myvalues)
then, since arrays are objects, and objects are reference types, f receives a reference to the ints, and can change their value so the caller can see the changes.
Now how can I then call f in a way that it receives a reference to the array elements 2,3,4 (i.e. subrange from index 1 to 3 inclusive) without copying myValues?
Something like
f ((int[]) myvalues[1])
which of course does not compile (and would leave open which size the array would have) but might transport the idea I am looking for?
In other languages, I could use pointer arithmetics to calculate the address of myValues[2], and treat it a the beginning of an array of integer, and pass an explicit count parameter. (Quite type-unsafe, of course.)
Can I do this in Java without copying the three elements' values to an intermediate array?
Sub-question: Are the array elements, being value types, stored at consecutive addresses at all, or is the array composed of elements that are references to integers? Could it be the question does not make sense because even if the answer to the latter was "yes", I could not build on that since that would be an implementation detail that a Java source must not build upon it? It even cannot -- there is no semantics for it, right?
Edit: Stupid index error

You can use List instead of an array.
int[] myValues = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
List<Integer> myValuesList = Arrays.asList(myValues);
// change the argument of function to List
doSomething(List<Integer> input);
// and then just give the function a range of the myValues.
// This List is still backed by your array myValues, it just
// a view of the original array.
doSomething(myValuesList.subList(2,3));

You cannot return a range/subset of items in arrays (also Collection) without creating a new instance of the container.
I cannot answer the second without guessing, but IF the JVM wants to allocate 2 regions of memory for one array, it can do it without you knowing.

In C/C++ this would be terribly easy to do with a bit of pointer arithmetic, but in Java, I am not so sure it is possible.
The best you could do is use the copyOfRange method although that makes a deep copy.

Related

Pass array by reference from a certain index on

In c, you can pass an array by reference from a certain index (say i) on simply by passing the address of the i-th element.
Now I was wondering if & how I can create a similar structure to work in Java.
I'm currently implementing an inplace radix-4 fft in java for which I'm making a recursive call on only parts of the initial data array.
So say I have a data array a= [1,2,3,4,5,6,7,8], I want to make 4 calls, each receiving a 4th of a as a parameter such that I can perform in-place modifications to a.
It cannot be done in Java with a 1-dimensional array directly.
You can do it with a multi-dimensional array.
For example:
int[][] a = {{1,2},{3,4},{5,6},{7,8}};
Now you can pass a[i] to your method, which can modify its elements.
Or you can create a List view of the array using Arrays.asList(). Then you can use subList() to pass parts of that List to your method, and modify these parts. These modifications will be reflected in the original array.
For example:
public static void changeSubList(List<Integer> list) {
list.set (0, 150);
}
public static void main (java.lang.String[] args)
{
Integer[] array = {1,2,3,4,5,6,7,8};
List<Integer> list = Arrays.asList (array);
changeSubList(list.subList (0, 2));
changeSubList(list.subList (2, 4));
changeSubList(list.subList (4, 6));
changeSubList(list.subList (6, 8));
System.out.println (Arrays.toString (array));
}
Output:
[150, 2, 150, 4, 150, 6, 150, 8]
The only issue is that you can't use an array of primitives.
Have a method that takes an array and start and end index as parameters. This is a pretty common idiom, but of course it expects the method to behave nicely and not read outside of its allowed indices.
It's simple, performant and pretty much the only realistic way in Java. All you have to worry about is buggy methods corrupting the array, but that shouldn't happen right?
You can't really do that "out of the box.
You could create an" array view" class that only gives access to a specific range.
But you can't create sub arrays without allocating memory and copying entries.

Array becoming null when List.toArray is used

I'm having an issue where I'm trying to populate an Array with values from a list, then replace the old values with the new ones upon each call of the method. The code below works once, then the next attempt it gives no errors until the new array variable is used , as the array which should have been populated with list data just is full of null values. If anyone has any suggestions much appreciated.
Integer[] stockFF2 =new Integer[ordersBFList.size()];
Integer[] ordersFF2 =new Integer[stockBFList.size()];
stockFFList.toArray(stockFF2);
ordersFFList.toArray(ordersFF2);
I think you have got the sizes wrong (orderFF2 and stockFF2 are using the sizes of each other's lists). I suspect one of the arrays is populated properly - one with the larger array - while the other allocates and returns a new array with the elements you want keeping the passed in array as it was because it is too short.
The toArray() method makes a fresh array and copies the contents of the list into it.
Try
Integer[] stockFF2 = stockBFList.toArray();
Integer[] ordersFF2 = ordersBFList.toArray();
If you want to reuse these arrays (seldom worthwhile), then replace their values with:
stockFF2 = stockBFList.toArray(stockFF2);
ordersFF2 = ordersBFList.toArray(ordersFF2);
It's unsafe to ignore the return value. If the source Collections get larger, the return value is another fresh array.

How to add an element at the end of an array?

I want to know how to add or append a new element to the end of an array. Is any simple way to add the element at the end? I know how to use a StringBuffer but I don't know how to use it to add an element in an array. I prefer it without an ArrayList or list. I wonder if the StringBuffer will work on integers.
You can not add an element to an array, since arrays, in Java, are fixed-length. However, you could build a new array from the existing one using Arrays.copyOf(array, size) :
public static void main(String[] args) {
int[] array = new int[] {1, 2, 3};
System.out.println(Arrays.toString(array));
array = Arrays.copyOf(array, array.length + 1); //create new array from old array and allocate one more element
array[array.length - 1] = 4;
System.out.println(Arrays.toString(array));
}
I would still recommend to drop working with an array and use a List.
Arrays in Java have a fixed length that cannot be changed. So Java provides classes that allow you to maintain lists of variable length.
Generally, there is the List<T> interface, which represents a list of instances of the class T. The easiest and most widely used implementation is the ArrayList. Here is an example:
List<String> words = new ArrayList<String>();
words.add("Hello");
words.add("World");
words.add("!");
List.add() simply appends an element to the list and you can get the size of a list using List.size().
To clarify the terminology right: arrays are fixed length structures (and the length of an existing cannot be altered) the expression add at the end is meaningless (by itself).
What you can do is create a new array one element larger and fill in the new element in the last slot:
public static int[] append(int[] array, int value) {
int[] result = Arrays.copyOf(array, array.length + 1);
result[result.length - 1] = value;
return result;
}
This quickly gets inefficient, as each time append is called a new array is created and the old array contents is copied over.
One way to drastically reduce the overhead is to create a larger array and keep track of up to which index it is actually filled. Adding an element becomes as simple a filling the next index and incrementing the index. If the array fills up completely, a new array is created with more free space.
And guess what ArrayList does: exactly that. So when a dynamically sized array is needed, ArrayList is a good choice. Don't reinvent the wheel.
The OP says, for unknown reasons, "I prefer it without an arraylist or list."
If the type you are referring to is a primitive (you mention integers, but you don't say if you mean int or Integer), then you can use one of the NIO Buffer classes like java.nio.IntBuffer. These act a lot like StringBuffer does - they act as buffers for a list of the primitive type (buffers exist for all the primitives but not for Objects), and you can wrap a buffer around an array and/or extract an array from a buffer.
Note that the javadocs say, "The capacity of a buffer is never negative and never changes." It's still just a wrapper around an array, but one that's nicer to work with. The only way to effectively expand a buffer is to allocate() a larger one and use put() to dump the old buffer into the new one.
If it's not a primitive, you should probably just use List, or come up with a compelling reason why you can't or won't, and maybe somebody will help you work around it.
As many others pointed out if you are trying to add a new element at the end of list then something like, array[array.length-1]=x; should do. But this will replace the existing element.
For something like continuous addition to the array. You can keep track of the index and go on adding elements till you reach end and have the function that does the addition return you the next index, which in turn will tell you how many more elements can fit in the array.
Of course in both the cases the size of array will be predefined. Vector can be your other option since you do not want arraylist, which will allow you all the same features and functions and additionally will take care of incrementing the size.
Coming to the part where you want StringBuffer to array. I believe what you are looking for is the getChars(int srcBegin, int srcEnd,char[] dst,int dstBegin) method. Look into it that might solve your doubts. Again I would like to point out that after managing to get an array out of it, you can still only replace the last existing element(character in this case).
one-liner with streams
Stream.concat(Arrays.stream( array ), Stream.of( newElement )).toArray();

Use of 'new' for arrays in Java

I've been undertaking some basic tutorials. One of which has asked me to set up an array to hold the following string values:
Beyonce (f)
David Bowie (m)
Elvis Costello (m)
Madonna (f)
Elton John (m)
Charles Aznavour (m)
Write a program to loop round, count how many are male vocalists and how many are female, and display my answer in the console.
I managed to complete it, but the way I set up my array was different to the answer provided.
Mine is as follows:
String names[] = {"Beyonce (f)", "David Bowie (m)", "Elvis Costello (m)", "Madonna (f)", "Elton John (m)", "Charles Aznavour (m)"};
And the provided answer is as such:
String[] singers = new String[6];
singers[0] = "Beyonce (f)";
singers[1] = "David Bowie (m)";
singers[2] = "Elvis Costello (m)";
singers[3] = "Madonna (f)";
singers[4] = "Elton John (m)";
singers[5] = "Charles Aznavour (m)";
Should I be creating a "new" array? If so, why? And what is the difference between the two?
Your answer is equivalent but more readable and less error-prone because you don't need any "magic numbers" for each array element with the "fear" of accessing an element out of the array definition and therefore creating an IndexOutOfBoundsException.
Both are doing the same thing.
First approach is more dynamic. You are telling java compiler that those elements will create an array. Compiler knows in compilation time their length, so it creates an array to fit them all.
In your second attepmt, you are first creating an array with length of 6. And then put in every slot one object.
When to use them:
If you know from the start what elements will be in the array, use first aproach - it is cleaner, shorter
But if there is some sort of logic that determined who should be placed in each slot, then second would be better. Like, when you want to create a 10 size array, but you will fill it during the runtime.
First aproach is also safer, because compiler created the array based on input length. Adding new element in code will change array size. In the second aproach you would have to change size manually, or ArrayOutOfBoundException will be thrown when adding singers[6].
But if you don't know the length of array (you will fill list in runtime), then you must use List or other dynamic structure (Set, List)
Both are valid ways to initialize an array.
Your way of initializing the array can only be done in the same expression that defines the array variable, though it can later be done in a similar way :
String[] names = null;
names = new String[] {"Beyonce (f)", "David Bowie (m)", "Elvis Costello (m)", "Madonna (f)", "Elton John (m)", "Charles Aznavour (m)"};
The provided answer explicitly creates an array of Strings, specifies the number of Strings that this array can store, and assigns values to the indices of the array.
Both solutions are correct. The first one uses an array initializer, the second one first instantiates the array and then populates it with values. One could argue that the first solution is more robust, since in the second solution the length of the array must be explicitly given before the entries are provided and it is possible to use indices beond the capacity of the array, which will be only detected at runtime.
A new array can be created with the new operator followed by the array element type and the array size between the [ ] characters - this is called the Array Creation Expression. Or when you declare a variable, you can also use an array literal which is called Array Initializers (but this cannot be used to assign a value to an array later on just when it is declared).
When you write
String names[] = {"A", "B", "C"};
It is just a short form and is equivalent to
String[] names = new String[] {"A", "B", "C"};
Note that to indicate that an array of the specified type is to be declared, both String[] names and String names[] forms can be used and they are equivalent, altough:
String names[], names2; // Only names is an array, names2 is just a String
While
String[] names, names2; // Both names and names2 are arrays!
It is recommended to use the second form to avoid confusion and accidents if later you add more variable names to the declaration.
Let's take a closer look of what happens in the 2 cases:
// "Slow" filling
String[] names = new String[3]; // Filled with null values by default
names[0] = "A"; // Explicit index, index range check!
names[1] = "B"; // Explicit index, index range check!
names[2] = "C"; // Explicit index, index range check!
// "Fast" filling at creation time, implicit indices and array length,
// No index checks!
String[] names = {"A", "B", "C"};
Advantages of creating and initializing the array in one step
There are several advantages of creating and initializing an array in one step:
Doing so is less error-prone: the compiler will determine the length of the array, and also the compiler will initialize the elements of the array based on the list you provide. No such thing as using a wrong index value or getting an ArrayIndexOutOfBoundsException.
It will be faster because the JVM (Java Virtual Machine) will not initialize the array with null values.
It will be faster because you don't have to specify explicit index values and the JVM does not have to work with them. Also the JVM does not have to check if indices are in the valid range (that is 0..length-1).
Less maintenance/overhead when later you want to add another element in the middle of the array, you just have to insert it where you want it. Would you have initialized your array the other way, you would have to update all subsequent indices.
The Java source code will be shorter, more compact and also the compiled byte code will be shorter.
You can read more about arrays in the Java Language Specification: Chapter 10. Arrays
The 'new' operator in java is responsible for the creation of new object or we can say instance of a class.
Actually, it dynamically allocates memory in the heap with the reference we define pointed from the stack.

Is there a quick way to create an array of return codes from another array?

Suppose I have an array of objects from the MyClass class:
MyClass myClassArray[] = {
new MyClass(0, 1),
new MyClass(2, 3),
new MyClass(4, 5),
new MyClass(6, 7)
};
Here, the MyClass constructor fills in two fields, which we shall call field1 and field2. Suppose now that I want to fill in an array containing the value of field1 from each object in myClassArray (so the array will contain the values 0, 2, 4, 6). The following does not work:
field1Array = myClassArray.getField1();
Is there a quick 1-line way to fill in the new array using return codes from methods belonging to objects in the original array? Obviously, I can do this using a for loop, but I'd rather make use of the features of the language, if they exist.
You will need to loop unless you are using Java 8+ which adds lambda expressions to the language, in which case you can map your array to a new array:
int[] field1Array = Arrays
.stream(myClassArray)
.mapToInt(MyClass::getField1)
.toArray();
This is admittedly a theoretical answer since Java 8 will not be officially released until Q1 next year.
Currently there are no other language features than a plain old and simple for loop.
With Java 8 there may be lambda expressions and perhaps some helper method for Collection which will do what you want. But Java 8 is not yet released.
No, as far as I know, in Java, there is no way to call a method on every element of the array, apart from using a loop.
int[] field1 = new int[myClassArray.size()];
for(int i = 0; i < myClassArray.size(); i++){
field1[i] = myClassArray[i].getField1();
}
Your approach has to use a loop (while, here for), because you can't run through an array without one. Sure you can handle each element of the array one by one. But this would be a nightmare for a fair size of elements in the array.

Categories