4

I am programming a game and almost have the save-file system complete. I have two Vectors (one holds the name of the savegame, one holds the sessionID).

At launch, the program will read in data from a file and add that information to the Vectors. Then another method is called to check if the files shown in the Vector acctualy exist. If not, they will be removed from the Vectors. At the end, the Vectors are printed to and rewrite the file.

The problem I'm having is the for loop isn't checking every item in the Vector, because Vector.size() is decreasing when items are removed.Is there a better way to form the for loop, or is there a workaround I can use?

private static void slistCleanup() throws IOException {

          private static Vector<String> saveNames = new Vector<String>();
          private static Vector<Integer> sessionIDs = new Vector<Integer>();

    Scanner slistReader = new Scanner(new FileReader(sessionList));
    File tempSave;
    String path;
    int run = 1;
    String tempName = " ";
    int tempID = 0;

    for (int x = 0; x < saveNames.size(); x++) {

        path = currentDir + "\\saves\\" + sessionIDs.elementAt(x) + ".sav";
        tempSave = new File(path);

        System.out.println("-----------------------"); //debug
        System.out.println("current pass: " + run);
        System.out.println("tempSave Path: " + tempSave.getAbsolutePath()); //debug
        System.out.println("tempSave exists: " + tempSave.exists()); //debug
        System.out.println("-----------------------"); //debug
        run++; //debug

        if (!tempSave.exists()) {

            saveNames.remove(x);
            sessionIDs.remove(x);
        }
    }

    for (int x = 0; x < saveNames.size(); x++) {

        System.out.println(saveNames.elementAt(x));
        System.out.println(sessionIDs.elementAt(x));
    }

    slistReader.close();
}

If you need more code, let me know.

Aaron
  • 992
  • 3
  • 15
  • 33
  • 3
    Use an iterator and its remove method. http://www.java-examples.com/iterate-through-elements-java-vector-using-iterator-example – Fildor Apr 30 '13 at 15:16
  • possible duplicate of [Looping through and arraylist and removing elements at specified index](http://stackoverflow.com/questions/9313572/looping-through-and-arraylist-and-removing-elements-at-specified-index) – Sergey Kalinichenko Apr 30 '13 at 15:19
  • Maybe you should be using ArrayList. See http://stackoverflow.com/questions/1386275/why-is-java-vector-class-considered-obsolete-or-deprecated – fglez May 08 '13 at 09:12
  • I know I can use ArrayLists, but I'm doing this for a final project in a programming class. The teacher doesn't want us using things he hasn't taught us. Otherwise, I'd be using them. – Aaron May 08 '13 at 20:44

8 Answers8

12

Loop backwards:

for (int x = saveNames.size()-1; x >= 0; x--)
Vincent van der Weele
  • 12,927
  • 1
  • 33
  • 61
  • 1
    +1 Bingo! This code pattern is a common problem, and looping the index from last to first is the solution. – Bohemian Apr 30 '13 at 15:19
  • @Bohemian That's also a very common question on Stack Overflow :) – Sergey Kalinichenko Apr 30 '13 at 15:20
  • @dasblinkenlight I've thought for some time that there should be archetype code for certain recurrent problems, but perhaps that's what textbooks are for. PS I've seconded your close vote :) – Bohemian Apr 30 '13 at 15:23
  • 1
    @Bohemian I remember my teacher showing this 'trick' long time ago :-) until then, I was always decreasing the index upon deletion... I felt so bad not coming up with this idea myself, but it's reassuring to see I wasn't the only one ;-) – Vincent van der Weele Apr 30 '13 at 15:26
3

One way that would require few changes to your existing code would be to traverse the vector in the reverse direction.

for (int x = saveNames.size() - 1; x >= 0; x--) {
   ...
}
Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
2

Always loop backwards through an object when you are removing items from it, so:

for (int x = saveNames.size()-1; x >=0; x--) {

That way the removed items don't cause you a problem.

The reason for the problem is that you are starting at x=0; you delete x=0 (so x=1 is the new x=0, x=2 is the new x=1 etc) but you move on to x=1, skipping one.

On the other hand if you start at saveNames.size()-1: You start at (for example) 9, delete it, 9 is now empty but we move on to 8 anyway. 8 is unaffected because its before 9

Richard Tingle
  • 16,906
  • 5
  • 52
  • 77
2

As Fildor noted in the comments, you can do this with iterators

Iterator namesItr = saveNames.iterator();
Iterator sessionItr = sessionIDs.iterator();
while(namesItr.hasNext() && sessionItr.hasNext()) {
    Object currentName = namesItr.next();
    Object currentSession = sessionItr.next();
    if (!tempSave.exists()) {
        namesItr.remove();
        sessionItr.remove();
    }
}
Zim-Zam O'Pootertoot
  • 17,888
  • 4
  • 41
  • 69
0

If you are having trouble because you're deleting items from the array as your looping over it, you can make a new array before the loop and put items you're keeping into it. After the loop is done, the new array will only contain items you're keeping, and you can set the original array to the new array you created.

shieldgenerator7
  • 1,507
  • 17
  • 22
0

You can just add the indexes you want to remove, and the going from last to first remove them. Or you can also use

x--;

inside your loop when you remove a element.

Luis Tellez
  • 2,785
  • 1
  • 20
  • 28
0

Best and simple way to remove items via loops in my opinion is:

  1. scan the items using for loop and add the itemsToDelete list the items you want to delete.
  2. list.removeAll(itemsToDelete)
john Smith
  • 1,565
  • 7
  • 34
  • 54
0

The simplest thing to do is just take out x++.

Explanation: When you remove saveNames.remove(x) and x=0 then what was in index 1 moves to index 0. X is still 0 and it'll now remove the 2nd item which is now at index 0. Once all the items are removed saveNames.size() will be 0, x is no longer less than saveNames.size() so the loop will break.

Sid
  • 4,893
  • 14
  • 55
  • 110