Reputation: 109
I have a collection of objects that I need an Iterator over that can go through the objects in order (both forward and back) but can also go to any object when given the index of that object (which represents the lesson number of an assignment).
However, The index for each Object needs to be specifically predefined, in order, and there is no guarantee that my list of objects will have sequential indexes (I could have the indexes 0, 1, 6, 9 for example).
I currently have an ArrayList() which I am instantiating with the largestIndex I expect to be possible as the initial capacity, but I keep getting ArrayIndexOutOfBounds exception whenever I try to use the add(index, Object) method on my ArrayList
my code looks like this:
int largestIndex = unindexedAssignments.get(unindexedAssignments.size() - 1).getAssignmentID();
//index of 0 is ignored so add +1 to make sure we have enough space
assignments = new ArrayList<>(largestIndex + 1);
System.out.println("LargestIndex: " + (largestIndex + 1));
//populate assignments List
for(Assignment assignment : unindexedAssignments) {
//add the assignment to the list such that the index == the lesson number
System.out.println("adding assignment with index of " + assignment.getAssignmentID());
assignments.add(assignment.getAssignmentID(), assignment);
}
and the console spits out something like this (windows cmdpromt does not support copy/paste >_<):
largestIndex: 3
adding assignment with index of 1
java.lang.IndexOutOfBoundsException: Index 1, Size: 0
at java.util.ArrayList.rangeCheckForAdd(Unkown Source)
at java.util.ArrayList.add(Unknown Source)
(the rest of the stack trace pointing to the section of code I gave above ...)
I don't why the Size == 0 when I created what should have been an ArrayList with size 4?
A related question: am I misusing an ArrayList (and it's ListIterator) when there is a better default Java collection to use for this circumstance? The desired end-result is that my object has an Iterator object which is able to traverse back and forth and goto a specific location (right now I would just create a new ListIterator at the given index if it exist)
Upvotes: 2
Views: 1252
Reputation: 361879
List
s do not support sparse indices. If you want to add to an index that's past the end of the list, you have to create all of the intermediate indices as well.
Use a SortedMap
. Maps are perfect for when you have non-contiguous indices. You can look up any assignment by its lesson number, and you can iterate over all the key-value pairs in order.
SortedMap<Integer, Assignment> assignments = new TreeMap<>();
for (Assignment assignment: unindexedAssignments) {
assignments.put(assignment.getAssignmentID(), assignment);
}
You could also use Java 8 streaming syntax as an alternative to an explicit loop.
Map<Integer, Assignment> assignments = unindexedAssignments.stream()
.collect(Collectors.toMap(
a -> a.getAssignmentID(), // keys
a -> a, // values
(a, b) -> throw new IllegalStateException("duplicate lesson number"),
// what to do if two items have the same key
TreeMap::new // map class constructor
));
Upvotes: 3