I have a function called resolveClash, which I send an array
(in this case - combinsFinal) with 2 or more objects in it of type ModuleLecturerStudentCombination (this is my own class). Essentially what the resolveClash function does is it puts the array into an arraylist, removes the first element/object in the array and then returns the list. However, when I inspect the state of the returned value in debug mode (eclipse), it shows that a null value has been added onto the end of the arraylist.
I have looked up "removing objects correctly" etc, however, everything I have tried so far doesn't get rid of the null. The null appears after I perform the remove. I have thoroughly checked that there is not a null being passed in etc. This is a problem because when I use this and iterate through it later, it picks up a null and gives me a nullpointerexception error. Could someone please let me know what I am doing wrong or point me in the right direction?
Thanks in advance!
picture displaying problem
resolveClash(combinsFinal);
public ArrayList <ModuleLecturerStudentCombination> resolveClash(ModuleLecturerStudentCombination[] combinationArr){
ArrayList<ModuleLecturerStudentCombination> copyCombinationList = new ArrayList<ModuleLecturerStudentCombination>(Arrays.asList(combinationArr));
copyCombinationList.remove(0);
return copyCombinationList;
}
...when I inspect the state of the returned value in debug mode, it shows that a null value has been added onto the end of the arraylist
This is the normal way it works. The data within the ArrayList is stored in an array, which then is wrapped in the class to behave in the way a list does. If you add elements and the array is to small it will create a bigger one and copy the objects.
However if you remove some, it wont create a new shorter array, but simply leave some free spots at the end, but only give you access to the first ones that should be their. In the Debug mode you should also see a variable called size which tells you which part of the array is still part of the list.
In your case the ArrayList method toArray(T []) is not returning a new array. From the documentation:
[...] 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 collection is set to null. [...]
The array combinsFinal has greater size than the list so the result is returned directly into it with an additional null. In this case no new array with the correct size is created.
To avoid this, since you cannot change the size of an array, you could create a new one with the same size of the list, then this would work correctly:
combinsFinal = new ModuleLecturerStudentCombination[temp.size()];
temp.toArray(combinsFinal);
or alternatively just pass an array with no size so the method will be forced to create and return a new array with the correct size:
combinsFinal = temp.toArray(new ModuleLecturerStudentCombination[0]);
Related
When I tried self-answering this question, I could only find other questions regarding removing items from an array so that items past the removed object get moved down 1 in the index.
In the code below, I have two arrays that hold the class SomeObject (with a name property): SomeObject_ONE and SomeObject_TWO.
Below I put an object "some-object" in the first array, and then set the second array to equal the object in the first array. I can still change the properties of the object in the first array by changing the properties of the object in the second array (the 3rd indent.)
However, when I try setting the object in the second array to null, it doesn't set the first array to null, rather it only removes the index for the object in the second array (4th indent).
Is there anyway to delete an object in an array rather than removing its array index?
Thanks.
SomeObject[] ObjectArray_ONE = new SomeObject[10];
SomeObject[] ObjectArray_TWO = new SomeObject[10];
ObjectArray_ONE[0] = new SomeObject();
ObjectArray_TWO[0] = ObjectArray_ONE[0];
System.out.println(ObjectArray_ONE[0].name+" outputs default name");
ObjectArray_TWO[0].name = "Name changed from OA2";
System.out.println(ObjectArray_ONE[0].name+" outputs Name changed from OA2");
System.out.println("Should not be null : "+ObjectArray_ONE[0]);
ObjectArray_TWO[0] = null;
System.out.println("Should be null : "+ObjectArray_ONE[0]);
ObjectArray_ONE[0] = null;
System.out.println("Only now is it really null: "+ObjectArray_ONE[0]);
This is a Pass by Reference vs Pass by Value.
Java is pass by value, and in this case the value is a reference. It's a subtle distinction. What it means here is that if you change the object being referenced in one place, it will change everywhere. But it will not change the reference. If I set the reference to be equal to something else, the original object is unchanged.
The reason for this is exactly what Max said. Its the same reason that if you set one of your method parameters to null (inside the method) it won't affect the caller.
If you want you can store an array of wrapper classes of that object and then calling the setter of the wrapper class... Not exactly neat though.
PS. Don't capitalise variable names... it confuses people.
I've been learning how to program with java and I haven't got any clear explanation about the difference of LinkedList's toArray(T[] a) and toArray() method. The second one simply returns all of the elements within the LinkedList object as an array, right? But, what about the first one?
EDIT :
I mean, I read the documentation from oracle, it says :
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.
I don't understand the meaning of the sentences displayed in bold.
Suppose you've a List<String>, and you want to convert it to String[]. Let's see the working of two methods:
List<String> source = new LinkedList<String>();
// Fill in some data
Object[] array1 = source.toArray();
String[] array2 = source.toArray(new String[source.size()]);
See the difference? The first one simply creates an Object[], because it doesn't know the type of the type parameter <T>, while the second one just fills up the String[] you passed (which is what you want). You would almost always need to use the 2nd method.
There are two differences :
The first returns T[] while the second returns Object[]
The first accepts an array as an argument, and if this array is large enough, it uses this array to store the elements of the Collection, instead of creating a new one.
Problem with gui application where array of objects been passed to the constructor, however when new round is initialised, it modifies somehow const_AnimalFamily array, where I want to make it unchanged at each round, however final cannot be used here. Other class initialises this class, however here is my main. Any suggestions? Thank you!
why its been changed each time I modify animalFamily, const_AnimalFamily being affected even if I did not do anything to it?
Your code is much too large for being analyzed. But as you declared two arrays assigning their references to fields, I simply assume that you once assign one field to the other.
And indeed you have the line:
animalFamily = const_AnimalFamily;
I futher assume that you want to copy all contents from const_AnimalFamily to animalFamily. But this is not the case.
In Java, such assignments simply assign the reference to the variable (or the field). That means, both fields now refer to the same array. Actually, the array that was referred to by the field const_AnimalFamily before, is now obsolete and cannot be used anymore.
If you now access some array content, for example
animalFamily[0] = ...
and afterards read from
... = const_AnimalFamily[0]
you will get the same object that you previously wrote into the array.
Solution: If you really wanted to copy the array, do the following:
animalFamily = Arrays.copyOf(const_AnimalFamily, const_AnimalFamily.length);
Another (better) solution would be to use collections.
It's right as per your observation "Problem with gui application where array of objects been passed to the constructor, however when new round is initialised, it modifies somehow const_AnimalFamily array, where I want to make it unchanged at each round".
See this your code:
public AnimalGUI(Animal[] temp) {
System.out.println("INSIDE CONSTRUCTOR");
const_AnimalFamily = temp;
You are changing the reference of const_AnimalFamily to temp. So now whenever you modify temp (from wherever it was passed) you are going to go through same changes in your constant array.
I would suggest you do something like:
You do a deep copy of your temp array rather than changing the reference.
OR
when you pass temp array, you pass the cloned (Arrays.copyOf) version of array rather than raw array.
So I just discovered that Java allows us to create arrays of size 0. Does that mean that the array is both empty and full at the same time? I figured this out while working on an array based implementation of a priority queue. Would it be right to say that it is empty and full at the same time when calling methods checking for this? Or should I not allow the creation of an array of size 0? Thanks.
Java arrays have no definition of full or of empty. Consider
int[] foo = {0};
int[] bar = new int[1];
Is foo full because it has a value assigned to its only position?
Is bar empty because it has no values assigned?
Both arrays are the same, they both have one value stored and in both cases the contain the value 0.
Full implies you can't add any more items, you can never add new items to java arrays, just replace existing items, so either all arrays are full or full does not make sense for a java array. I say it is the second.
I want to make a hash table class in java where I store the key,value pairs in an ArrayList of Linked List's. I do this by declaring
ArrayList<LinkedList<T>> storage = new ArrayList();
I then want to create a linkList object that I can use to then create a new linked list inside of each index of the arrayList. I do this by declaring:
LinkedList<T> list = new LinkedList<T>();
Then I have my add function set up to add elements to the first index of the LinkedList that is inside the Hashed key index of the arrayList as such:
public void add(K key, T value){
int arrayListIndex = (key.hashCode()) % this.initialCapacity;
System.out.println(arrayListIndex); //This tells us where we access the Array List;
if (hashBrown.get(arrayListIndex) == null){
hashBrown.add(arrayListIndex, list);
hashBrown.get(arrayListIndex).addFirst(value);
}
}
Everytime I run this code I receive an error where my index is 7 and my size is 0. This causes an error:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 7, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:571)
at java.util.ArrayList.get(ArrayList.java:349)
at FastHashtable.add(FastHashtable.java:72)
at FastHashtable.main(FastHashtable.java:145)
I am unable to track down where this index out of bounds error is coming from can anyone offer advice. I am fairly new at working with ArrayLists which makes me think my original declaration of the arrayList is incorrect.
You are confusing an ArrayLists capacity with its size. From the Oracle Java documentation:
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.
Instead, you should be looking at creating a plain array (e.g. Object[] a = new Object[maxSize]) in which you can actually assign objects (linked lists in this case) at arbitrary index values. If you only want to store linked lists, create a LinkedList<T>[] array.
You cannot add to a list at index 7 if there are 0 elements in it. You can only add at the end (with the add method without index) or at a position that is no larger than the current list's size().
When the list is empty and you add something at index 7, what do you expect the list to contain at the first position then, and what at index 6? (I once created a subclass of list to fill everything up to the index with null when the addition index is larger than the list size, but this behaviour is not universal enough to be part of List's semantics.
[edit in response to comment here and to praseodym's answer]
You could simply fill the (array) list with nulls replace those with a linked list when the respective position is first accessed. (Be sure to use set and not add, though, which is probably what you want above as well.)
Alternatively, you could create an array of the desired size (that will be full of nulls by default) and "wrap" it into a (non-resizable) list via Arrays.asList. You have to ignore an "unchecked conversion" warning then, however (not that you could avoid warnings when using an array). Also, I suggest you read "Program to an interface, not an implementation".