I decided that the easiest way to solve the lag issue with collision detection was to break the game field up into a grid of 100x100 boxes. Whenever a new target was created, I would associate it with the appropriate box. Thus, each projectile only has to be checked against the targets in it's box.
I implemented this with a quick class that I called the GridManager. I was able to reuse my existing collision detection code with only a reordering of the loops (I was looping through the targets first, with the projectiles being checked within) and a call to the GridManager to get the appropriate, smaller lists to search through.
I anticipated that there would be some flaws in my quickie algorithm, and I was not disappointed. As expected, there were some targets near the edges of the boxes that were not being checked for collisions. I will need to check the current box, plus the boxes next to it if the position of the projectile plus the radius of the targets would place it near the edge.
I also was using the position by default, which is just the upper left corner of the sprite I am using. I think I will need to store this using the center of the objects to get more accurate results. Most of the objects already can return their centers. I just need to make sure that they are being used instead of position.