ArrayList accessing an element that should have been deleted
I'm using Java for a data mining project and am having an odd issue with an ArrayList.
The ArrayList (availAttribs) contains the names of all the attributes not yet used in the current branch of a decision tree. At the beginning of the loop an attribute is chosen and the index of that attribute in the ArrayList is stored in chosenAttribute. The logic is performed then the item is removed from the list and another is chosen.
The program wasn't behaving as expected so I used a for each loop to display the current contents of the ArrayList before each attribute selection so I could check the contents.
This is what I got:
availAttribs contains ...
-Color
-size
-act
-age
Chose attribute #1: size
availAttribs contains ...
-Color
-act
-age
Chose attribute #1: size
The attributes are being chosen at random:
for(String s : availAttribs) {
System.out.println(" -" + s);
}
chosenAttribute = random.nex开发者_如何学PythontInt(availAttribs.size() - 1);
System.out.println(" Chose attribute #" + chosenAttribute + ": " +
trainSet.attribute(chosenAttribute).name());
// other stuff here
availAttribs.remove(chosenAttribute);
All of that is within a while loop checking for the exit condition. I would think that if an item wasn't successfully removed that it would show up when I iterated through the list and printed each element but apparently it can still access them.
Edit: random was declared outside the while loop:
Random random = new Random(System.currentTimeMillis() );
ArrayList.remove(Obj) removes the first (lowest index) object that obeys obj.equals(Obj). You're calling remove on the index:
availAttribs.remove(chosenAttribute);
should be
availAttribs.remove(availAttribs.get(chosenAttribute));
i.e. the value of the element at index i rather than i;
I figured out the answer while trying to explain part of the code in response to a comment. chosenAtrribute is the index in respect to the ArrayList and because of the way I populate the ArrayList it corresponds to the indexes that the data structure I'm using internally assigns to each attributes. When I remove an item from the ArrayList all the ones after it slide forward and they're no longer in sync.
Since my debugging statement is grabbing the name from the data structure and not from the ArrayList itself its displaying the wrong name while the arraylist is behaving as expected.
Not sure why I didn't notice that sooner.
My guess - you are calling List.remove(...)
on an Integer object, not an int primitive. What is the type of the chosenAttribute
variable?
Calling remove(...) with an object hits the remove(object) method, for example:
Integer chosenAttribute = ...
availAttribs.remove(chosenAttribute);
will loop forever, however:
int chosenAttribute = ...
availAttribs.remove(chosenAttribute);
terminates as expected.
You can get the int primitive for the index and call List.remove(int)
, or you can get the object at the index and call List.remove(object)
. Either should work.
精彩评论