Getting an IndexOutOfBounds Exception in my Android App - java

This code tracks what missiles players buy and sets the most recent 3 at the top of the list of missile options for players to easily buy them again. After players purchase missiles, the game crashes, but only if they purchase certain ones or purchase a certain amount.
Process: com.apps.fast.counterforcetest, PID: 16063
java.lang.IndexOutOfBoundsException: Index: 5, Size: 3
at java.util.LinkedList.checkElementIndex(LinkedList.java:555)
at java.util.LinkedList.remove(LinkedList.java:525)
at com.apps.fast.launch.components.ClientDefs.SetMissilePreferred(ClientDefs.java:199)
at com.apps.fast.launch.launchviews.PurchaseLaunchableView$1$1.onClick(PurchaseLaunchableView.java:198)
Here is the code the error points to in CLientDefs.java:199
public static void SetMissilePreferred(int lMissile) {
// Set a purchased missile to go to the top of the preferred list.
if (MissilePreferences == null)
MissilePreferences = new LinkedList<>();
if (MissilePreferences.contains(lMissile))
MissilePreferences.remove(lMissile); //<---- Line 199
MissilePreferences.push(lMissile);
if (MissilePreferences.size() > PREFERENCE_LIST_SIZE)
MissilePreferences.removeLast();
}
MissilePreferences is a List of Integers.

There's a bit of a mixup going on here:
if (MissilePreferences.contains(lMissile))
MissilePreferences.remove(lMissile);
lMissile is an int, right? Representing an ID? So when you call contains, you're checking if that ID exists in MissilePreferences. You want to know if the List contains that int.
Here's the method signature for contains:
public boolean contains(Object o)
It doesn't take a primitive like an int, it takes an Object - so your int is being autoboxed into an Integer - which makes sense because a List can't contain primitives either, only objects. MissilePreferences is a list of Integers.
So that's all fine, it converts your int to an Integer and tells you if it exists in the list of Integers, perfect! But then you call remove with that original int. And there are two versions of that method that take a parameter:
public boolean remove(Object o)
Removes the first occurrence of the specified element from this list, if it is present.
public E remove(int index)
Removes the element at the specified position in this list.
Those do two very different things. The Object version removes the first instance of that object from the list. The int version treats the int as an index and removes whatever is in that position.
When you use contains, you're treating your int as an element in the list you want to find, and it's automatically converted to an Integer. And you want to do the same with remove - but there's a different version of that method that takes the int you're providing directly. It won't autobox that and call the other method, obviously! You'd have to do it yourself:
Integer missileId = new Integer(lMissile);
// explicitly passing an Integer object to both - only crucial for #remove
if (MissilePreferences.contains(missileId))
MissilePreferences.remove(missileId);
That's what you have to watch out for - outside of arrays and some special classes you might run into elsewhere, collection objects don't contain primitives, so you often want to explicitly work with the Object wrapper versions they contain. Especially important for ints because of situations like this!
That said, you could just do this:
MissilePreferences.remove(new Integer(lMissile));
No need to use contains - you can just call remove and it'll remove the first matching object if it has one. It returns true if it removed anything, in case you need to check that

Try debugging the code so that you know what are the elements in the list and what element is being removed. I am still confused as to how can you get an index out of bounds exception when you are just accessing the element from the list by its value.

Related

removing object from arraylist leaves null

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]);

Return a fully-allocated array of pairs with other misc. info in Java

I have to write a method that traverses a huge object's contents which are spread across machines and need to return this:
starting index in the object's struct(ex: if it has 10 pieces/blocks I can return piece/block 3-7)
offset within the first piece
list/array of pair < id of each piece, size of each piece > (not map - I've been clearly told not to use Map or Map.Entry)
Quoting exact words, I'm required to return fully-allocated array corresponding to the block range.
Thought #1: The starting index and offset are to be returned once, the option to create a class with
index
offset
id
size
and returning an array of this will be providing redundant information plus, adding 8 bytes every entry is huge waste of memory.
Thought #2: I could create a data class with (id and size) and return another class with array of this smaller class + index & offset, but in this case the existence of my data class will be just to contain values which doesn't seem v. prudent.
Thought #3:I've heard multiple times that people resort to arrays when need to return pairs. I don't know how to do that?
You have to create, basically, a data structure. There is a single way to do that in Java: use classes.
Your first thought is wrong: you must return a single index, and a single offset, and multiple pairs. It's thus wrong to put all the fields in a single class, since the cardinality of the fields is not the same. In particular, if there is 0 pair to return, you would be very embarrassed.
Your second thought maps exactly to what you must return. Except I would use a collection (List or Set) instead of an array:
public class Result {
private int index;
private int offset;
private Set<Piece> pieces;
...
}
public class Piece {
private String id;
private int size;
...
}
Why use a collection rather than a Piece[] array: because there's a good chance that you don't know the number of pieces before the traversal. Because a List or Set has many useful methods that an array doesn't have. Because a Set<Piece> clearly says that there are no duplicate elements, which is not the case with an array of Piece.
The third thought consists in using an Object[] containing 2 elements (or an int[] of two elements, if both the ID and the size are of type int, for example), to hold the information about a Piece. But that is ugly and unreadable: it's not obvious at all what the array contains, in which order, and what their type is. And you can't add any useful method like you could with a Piece class.
Java is an OO language. Use classes and objects. Use encapsulation.

Adding a element of Generic type <T> to an arrayList of LinkedList's

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".

Assignment Help: List Constructors & Exceptions

I am currently taking a class away from school and my professor is not helpful, so I was wondering if anyone can give me pointers on what to do. The instructions were given to me as follows:
You can create your own list class (MyList) which will be able to hold any number of items up to the actual size of the array. Your class will maintain a counter of the actual number of items stored in the array. The array will be of type Object so that your array can contain any Object or subclass of Object. Your class should provide the following methods:
void append(Object o) – appends the object onto the end of the list. Throws a ListFullException if the list is full.
Object at(int index) – returns the object at the indicated position or throws an ArrayIndexOutOfBoundsException if the index is not valid.
void remove(int index) – remove the element at the index and moves elements after it down to fill the empty space. Throws ArrayIndexOutOfBoundsException if the index is not valid and ListEmptyException if the list is empty and there is nothing to remove.
MyList(int size) – constructor which takes the size to make the array.
You can use ArrayList in underlying implementation of your MyList class.
In the constructor, use the passed size to initialize the arraylist like:
arrayList=new ArrayList<Object>(size);
In the append method, you can simply add the passed object to the arrayList(after placing size checks and throwing your ListFullException):
arrayList.add(obj);
Similarly use ArrayList's remove and get methods for remove and objectAt functionality respectively.

Adding an element to an ArrayList in the correct postition

I have a custom ArrayList interface that extends the Comparable class and is in ascending order. The class I'm working on is implementing this interface.
My problem is I need to edit the add method so that it will add an element to the ArrayList, have the List stay ordered, and make sure there are no duplicates.
It would be easy to do all this in separate methods, but that's out the question. I need the one method to do it all, so that when the method is called, (as long as it isn't a duplicate) the element is added in the correct position.
On top of that, to check the position of the index to insert the method to, I must use the compareTo() method inherited from the Comparable class. Only problem is I have to implement my own compareTo() method in the class I'm working on. I've looked all over, and I'm confused on how to go about that for this certain class.
Here's my code so far:
public void add(E item) throws IndexOutOfBoundsException {
if (contains(item)) {
throw new IllegalArgumentException("This is a duplicate!");
}
//here is where I need the implementation to add the item to the array, in order
}
Then here is my compareTo() method:
public int compareTo(E item) {
if () {
return -1;
}
else if () {
return 1;
}
else {
return 0;
}
}
One way to do this is to first check if
myArrayList.contains(item)
and then if not, just insert and re-sort your array:
myArrayList.add(item);
Collections.sort(myArrayList);
Note that in general, if you want to maintain a sorted set without duplicates, there are better data structures than ArrayList.
What about a TreeSet? It seems to have the behaviour you're looking for.
You don't give that much information. If what you truly are implementing is an ArrayList like data structure, then you first need to see if the array is large enough to add a new item. If not, you need to create a new array. In the first case, you need to find the location to enter the new element, shift everything from that position on down one, and then add the element. For the second case, you can "merge" the old list with the new element (that is, keep adding from the old list until the location where the new element should go comes up, add the new element, and continue). Another question I have: where is the compareTo(Object o) being put? If you are putting in the ArrayList class, that's rather pointless since you don't really want to compare arrays. If it's in the class being stored in the ArrayList, you want to return -1 if the this object comes before the object passed in, a -1 if the this object comes after, and 0 if they are equal. If you can choose your data structure, you might want to consider a linked list: they are very easy to add to and remove from.
If you are extending the ArrayList class, then this is super (pun intended) easy. In your add method, you have to determine the location to add the element, then call the super.add(int loc) method
Adding an element in the right position is the same as failing to do binary search and recording the last position you compared.
Check out the documentation for Arrays.binarySearch. Hopefully this will give enough information to implement it. Your implementation of comparable should just be the same as you would use for sorting. Here's the relevant excerpt from the documentation:
index of the search key, if it is contained in the array; otherwise, (-(insertion point) - 1). The insertion point is defined as the point at which the key would be inserted into the array: the index of the first element greater than the key, or a.length if all elements in the array are less than the specified key. Note that this guarantees that the return value will be >= 0 if and only if the key is found.

Categories

Resources