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.
Related
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.
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.
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".
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.
I recently found out that there are actually 2 different ArrayList implementations in Java (better late than never I guess...).
So I was wondering why does Arrays.asList(T... a) need to return a list which can not be resized ? If they needed an unmodifiable list why add the set(int index, E element) method then ?
So my general question is why not return the java.util.ArrayList from the Arrays.asList(T... a) method ?
Also what do you gain with the java.util.Arrays.ArrayList implementation ?
You asked:
Also what do you gain with the
java.util.Arrays.ArrayList
implementation ?
It is because the Arrays$ArrayList returned by Arrays.asList is just a view on the original array. So when the original array is changed then the view is changed too.
If one would use an real ArrayList then the elements will be copied, and a change on the orignal array would not infuence the ArrayList.
The reasons to do this are quite simple:
performance: no need to copy anyting
memory efficent: no second array is needed
The javadoc says that asList returns "a fixed-size list backed by the specified array". If you want to resize the array, you have to create a new one and copy the old data. Than the list won't be backed by the same array instance. The stated goal is "This method acts as bridge between array-based and collection-based APIs." and so write-through to the underlying array is a design requirement.
They are two different classes with different behaviours.
The list returned when you called Arrays.asList is a thin wrapper over the array, not a copy. The list returned is fixed size: attempting to call add will throw an UnsupportedOperationException exception.
The java.util.ArrayList on the other hand keeps its own internal copy of the data and is variable sized.
Arrays.asList needs to return a list that cannot be resized -- because the underlying array cannot be resized -- but that is modifiable -- because assignment to elements in the underlying array is allowed.
actually you are able to add elements to the ArrayList with add. method like this :
List<String> l2= new ArrayList<String>(Arrays.asList(array1));
l2.add("blueCheese");
In my opinion you use it to get the features of a List but applying them to an Array .
Two comments:
1, Attempting to shrink the returned array by calling the remove() method of List interface will throw an UnsupportedOperationException. This is because the inner ArrayList class inside of Arrays class extends AbstractList, and the remove() method in AbstractList throws UnsupportedException.
Thus once the List is returned, you can overstore existing elements EITHER in the array OR in the returned List, BUT you are NOT permitted to grow the array or shrink the array.
In response to:
actually you are able to add elements to the ArrayList with add. method like this :
List l2= new ArrayList(Arrays.asList(array1));
l2.add("blueCheese");
The l2 is an independent copy of the list, so List l2 is now decoupled from the original array&List. So blueCheese in in l2, but not in the original array/List that were backed up from each other.
-dbednar