How to make reference to a reference in Java? - java

I am trying to remove an element from Array through a customized Iterator and I need to remove an element from my array. I know it's not very practical to use array, but I have some restrictions for some reasons.
Problem is I can't create an another array with the removed element and change the reference. Because I don't have the real reference in customized Iterator Class. I need the change the real reference. Let me explain this better in code:
public class Iterator<E>
{
private E[] buffer; // underlying buffer.
private int idx; // location of iterator in buffer.
private E last_element; // last element returned by this iterator.
public Iterator(E[] arr)
{
buffer = arr;
idx = 0;
}
/**
* Removes from the underlying collection the last element returned
* by this iterator.
*/
public void remove()
{
...
}
}
I can create a copy of buffer with removing the specified element and change the buffer reference to that. But I want this remove to effect the real array. So I
actually need to change the arr[].
Again I know this whole use of array is senseless while having the Collection hierarchy but I need a way to this in this manner. A reference to a reference is not a good terminology in this case, but I had an implementation for this in C++, and looking something for like a pointer to pointer.
Thank you in advance.

It is already the case in your example ...
Setting buffer to arr, allows to create a copy of the reference, to the same Array in the heap, containing the same references of all elements.
BUT the fact is you should not use array this way, if you want to remove element.
You simply should use a List of the same kind of element.
Change your implementation, to use List<E> instead of arrays, and you will be able to call the remove method on it, with effect on original passed instance of list.

If you want a "pointer of a pointer" I see two ways : the first one is to create an array with only one element or the second one would be to create your own wrapper class containing the element.
I will give an example of the first way:
public class Iterator<E>
{
private E[][] pointerToPointer;
private E[] buffer; // underlying buffer.
private int idx; // location of iterator in buffer.
private E last_element; // last element returned by this iterator.
public Iterator(E[][] pointerToPointer)
{
this.pointerToPointer = pointerToPointer;
buffer = pointerToPointer[0];
idx = 0;
}
/**
* Removes from the underlying collection the last element returned
* by this iterator.
*/
public void remove()
{
// create your new array (let's call it newArr)
...
buffer = newArr;
pointerToPointer[0] = buffer;
}
}
Then when you call your iterator, you have to create a singleton array:
Integer[] arr = ...
Integer[][] pointerToPointer = {arr};
Iterator<Integer> it = new Iterator<>(new Integer[][]{pointerToPointer});
//use your iterator, including remove() method
...
arr = pointerToPointer[0]; //this gets the modified array
Anyways, what is preventing you to add a method to your Iterator class that returns the field buffer?

Java is pass-by-value and not pass-by-reference, meaning; you are copying data, and letting the garbage collector (GC) taking care of the rest. So you don't have pointers, which you have in C++.
This is my idea, having one bad sideeffect - the array is fixed and allocated to the array parsed to the constructor (index is removed, but replaced with null):
public void remove(int index) {
#SuppressWarnings("unchecked")
E[] tmp = (E[])new Object[this.buffer.length]; // Can cause issues on some types
int x = 0; // Variable to track tmp's index counter
for(int i = 0; i < this.buffer.length; i++) {
if(i != index) {
x++;
tmp[x] = this.buffer[i];
}
}
this.buffer = tmp;
}

Related

How can I correct my method so that it removes string from array?

I am trying to create a method that searches through the 'data' array to find the parameter 'elt'. If it exists, the method deletes it. I cannot figure out how to delete the string "elt". Below is what I have so far.
public class Bag<T> implements Iterable<T> {
private final int MAXLEN = 3;
private int size;
private T[] data; // array
public T remove(T elt) {
for (T word : data) {
if (word == "elt")
data = data.remove(word);
}
}
}
The error I get is "Cannot remove(T) on the array type T[].
Can someone tell me how I can properly remove the string "elt" from the array?
data is an array so you cannot remove it in the sense you are trying to do.
You have a few options:
Set the element to null
(1) and move the other elements down
Use a Collection (such as ArrayList) - then you can remove as you'd like
Option (3) would be the simplest. If you are required to use an array, (1) would look something like:
for (int i=0; i<data.length; i++) {
if ("elt".equals(data[i]) {
data[i] = null;
}
}
You can't "remove" a value from an array: you cannot change the number of elements in the array once it has been created.
You can, however, change the value of an element, e.g. setting it to null. In order to do this, you'd need the index of the element, so you can't use an enhanced for loop.
If you want a variable-size container, use a mutable List, e.g. ArrayList. You could then simply use list.remove("elt"), no explicit loop required.
Aside: use "elt".equals(word) instead of word == "elt".

Select subarray without copying into new buffer?

I have float[] array of length 100. Is there a way I can select (pseudocode):
x = array[10:19];
To get elements 10,11,12,...,19 without copying over into another buffer? I'm in a mobile application where I don't want to waste space or time doing this. I'd rather just reference the pointers the system uses for array.
The most efficient way to do this would be to use System.arrayCopy(), which is much faster and more efficient than copying manually using a loop. It will require another array, but any approach you use (beyond just passing the original array around with a couple of ints representing the offset to use) will do this, and it's relatively cheap - the memory consuming bit is usually the objects that it's referencing rather than the array itself, and they are not copied.
No, there is no API to do that. The closest solution to this would be building your own class that wraps an existing array, and does the re-indexing:
class SubArray {
private final float[] data;
private final int offset;
private final int length;
public SubArray(float[] data, int offset, int length) {
this.data = data;
this.offset = offset;
this.length = length;
}
public float get(int index) {
if (index >= length) throw ...
return data[index + offset];
}
public void set(int index, float value) {
if (index >= length) throw ...
data[index + offset] = value;
}
}
If the result that you need is a new object that behaves like an array in all respects, including the indexing operator, you would need to make a copy.
(Update) Precondition: You should store the data in a Float[] instead of a float[], the performance-hit should be minimal.
You can use: Arrays.asList(array).subList(10, 20).
The Arrays.asList(array) does the following:
Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray(). The returned list is serializable and implements RandomAccess.
Source
And then .subList(10, 20) returns you a List.
Then if you really want to work with arrays in the end, you could take the following lines:
List<Float> subList = Arrays.asList((Float[])array).subList(10, 20);
Float[] subArray = subList.toArray(new Float[subList.size()]);
(Update) Changed Arrays.asList(array) to Arrays.asList((Float[])array) such that it is correct now.
From documentation:
Returns an array containing all of the elements in this list in proper sequence (from first to last element); the runtime type of the returned array is that of the specified array. If the list fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list.
If the list fits in the specified array with room to spare (i.e., the array has more elements than the list), the element in the array immediately following the end of the list is set to null. (This is useful in determining the length of the list only if the caller knows that the list does not contain any null elements.)
Like the toArray() method, this method acts as bridge between array-based and collection-based APIs. Further, this method allows precise control over the runtime type of the output array, and may, under certain circumstances, be used to save allocation costs.
Suppose x is a list known to contain only strings. The following code can be used to dump the list into a newly allocated array of String:
Source
This should ensure that no data is wasted, the only thing to be careful about could be autoboxing.
UPDATE: Changed my answer such that it now is correct under a precondition.
What is the problem of using a simple for loop? Objects are in java called by reference.
So, executing copying the array does not copy the objects.
float[] subarray = new float[10];
for(int i = 10, j = 0; i < 19; i++, j++) {
subarray[j] = x[i];
}
The array[0] is a reference to the object of x[0].
edit: This only applies for objects, and i don't know if it also applies to a float

Finalize first element of an array

Say, I have some class which holds an array of integers in it.
Integer[] numbers;
Also, I have some simple constructor which initializes my array:
public Program()
{
numbers = new Integer[11];
numbers[0] = null;
}
As you can see, I have an array of 11 elements.
The point is that I will never ever change the first one with index 0.
Is there a way to finalize the first element of my array, so it can't be changed?
Like with final variables.
No, you cannot do that with an array. In fact, inability to make array elements read-only is a major drawback of using arrays in situations when data could be modified externally.
The only approach to protect elements of your array is to encapsulate the array in a class that would check elements and indexes before performing modifications:
public class ArrayWithFixedFirst {
private final Integer[] numbers = new Integer[11];
public Integer get(int index) {
return numbers[index];
}
public void set(int index, Integer value) {
if (index == 0) throw new IllegalArgumentException();
numbers[index] = value;
}
}
I don't believe there is a way to specify that the first element of an array cannot be re-assigned.
I think your best bet would be to create a wrapper class for the array, and then ignore any attempts to re-assign the first element.
Through encapsulation, you can allow/disallow the array modification.
public void updateArray(int position,int value){
if(position > 0 && position < numbers.length){
numbers[position] = value;
}
}
You can not force an array to be unmodifiable. An alternative is using Collections.unmodifiableList. But the whole list will therefore be unmodifiable.
Intriguing question, but I'm going to have to say no. Java arrays will not allow you to finalize just one element. You could possibly get the same functionality by writing a custom wrapper, but that begs the question, why? I don't know what application you're going for, but I would recommend wrapping a ten element array and decrementing your index by one, and returning null for the zero'th index
I don't know why you'd do it, but something like this:
class NoFirstArray extends ArrayList {
public NoFirstArray(int size,Object initialValue) {
super(size);
super.set(0,initialValue);
}
public void set(Integer i, Object value) {
if(i == 0) throw RuntimeException();
super.set(i,value);
}
public void remove(int i) {
if(i == 0) throw RuntimeException();
super.remove(i);
}
}

Pass zero-sized array, save allocation?

In this code sample from page 114 of The Well-Grounded Java Developer, the last line:
Update[] updates = lu.toArray(new Update[0]);
contains the note: Pass zero-sized array, save allocation
List<Update> lu = new ArrayList<Update>();
String text = "";
final Update.Builder ub = new Update.Builder();
final Author a = new Author("Tallulah");
for (int i=0; i<256; i++) {
text = text + "X";
long now = System.currentTimeMillis();
lu.add(ub.author(a).updateText(text).createTime(now).build());
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
Collections.shuffle(lu);
Update[] updates = lu.toArray(new Update[0]);
What allocation is this saving, exactly?
The javadoc for List#toArray(T[] a) mentions:
If the list fits in the specified array, it is returned therein.
Otherwise, a new array is allocated with the runtime type of the
specified array and the size of this list.
Which is what I remembered: if the array you pass to toArray(T[] a) can't fit everything in the list, a new array is allocated. Plainly, there are 256 elements in the list, which cannot fit in an array of size 0, therefore a new array must be allocated inside the method, right?
So is that note incorrect? Or is there something else it means?
Plainly, there are 256 elements in the list, which cannot fit in an array of size 0, therefore a new array must be allocated inside the method, right?
yes.
You can use
private static final Update NO_UPDATES = { }
lu.toArray(NO_UPDATES);
however this will should only help if you expect the list to be typically 0 length.
Generally, I would the same approach as fge
lu.toArray(new Update[lu.size()]);
In your specific case you know the size in advance so you can do
Update[] updates = new Update[256];
String text = "";
final Update.Builder ub = new Update.Builder();
final Author a = new Author("Tallulah");
long now = System.currentTimeMillis();
for (int i=0; i<updates.length; i++)
updates[i] = ub.author(a).updateText(text += 'X').createTime(now++).build();
Collections.shuffle(Arrays.asList(updates));
Going off of #Andreas comment on the question, I think it is a typo, and should say:
Pass zero-sized array, safe allocation.
Because if you passed nothing to the method, you'll end up calling the List#toArray() no-argument overload!
This would return an Object[] (though it would contain nothing but Update instances) and would require changing the type of the updates variable, so the last line would become:
Object[] updates = lu.toArray();
And then every time you wanted to iterate over and use the elements in that array, you'd have to cast them to Update.
Supplying the array calls the List#toArray(T[] a) method, which returns a <T> T[]. This array is reified to know it is an array of Update instances.
So supplying an empty array of Updates results in an Update[] coming back from the toArray call, not an Object[]. This is a much more type-safe allocation! The word "save" in the note must be a typo!
...this consumed way too much mental effort. Will post link to this in the book's forums so they can correct it.
It saves allocation, comparing to toArray(new Update[255]) or toArray(new Update[1000])

How to 'remove' an Object from a Java array (can't use Collections)

As a sample, I am developing a simple MySortedSet in java which implements SortedSet interface. It is backed up with a simple array which is E[] array.
I have several questions regarding that:
This is the class: (I am not writing entire code, instead of related parts)
public class MySortedSet<E> implements SortedSet<E>, Iterator<E> {
private E[] array;
private Comparator<? super E> _comparator;
private int size = 0;
private int capacity;
#SuppressWarnings("unchecked")
public MySortedSet() {
this.capacity = 10;
this.array = (E[]) new Object[this.capacity];
// this.array = Array.newInstance(Class<E> var,int size);
// We have to get Class<E> from outside caller.
}
}
Since it accepts all sort of type from primitive to reference types etc. I am not really sure when removing an item, assigning null is a good way in place of the removed item. Since Java initializes primitive types with 0. So null only works for reference types.
Below is probably very bad design:
#Override
public boolean remove(Object o) {
int indexOfElement = this.find(o);
boolean removed = false;
if (indexOfElement != -1) {
this.array[indexOfElement] = null;
removed = true;
}
return removed;
}
Can someone tell me what the best way is to remove an element from an array?
Edit:
Honestly what I am thinking to remove an element from an simple array is like copy the entire array without the removed item into a whole new array but I am not sure how efficient it would be in terms of performance and etc.
It kinda depends on the context of how you want to use your array. For example, if you are going to be iterating over the array and using the contents of it for standard methods like Arrays.sort(), they might generate NullPointerExceptions if you have null values in your array.
If you really want to remove items from an array in a safe way, I'd suggest changing your array to an ArrayList like this...
ArrayList<Object> list = new ArrayList<Object>();
list.add(object);
list.remove(object);
As this will actually remove the item from the list completely - no nulls or anything will remain, and performing methods like length() will return a real value.
For instances when I have used an array, I set the value to null, and ensure that all iterations over the array check that value != null before I try to query it. After setting the nulls for the removed items, I usually loop over the array and manually sort all the nulls to the end of the array, and then do System.arraycopy() to resize the array. This will leave you with a new array of the correct size, with all items in it except for the removed ones. However, I suggest this only if you really must use an array, as it is slower and introduces much greater potential for errors and NullPointerExceptions.
Alternatively, if you're not worried about sort-order, you can simple move the last item in the array over the top of the item you want to remove, and keep a count of the real array size. For example...
Object[] array = new Object[20];
int realSize = 15; // real number of items in the array
public void remove(int arrayIndex){
array[arrayIndex] = array[realSize-1];
realSize--;
}
This method removes an item in the array by 'replacing' it with the item in the last position of the array - its very quick and pretty to implement, if you don't care about sort order.

Categories