Dave0504
Dave0504

Reputation: 1117

Arraylist toString() method and duplicate values

Below I have posted a snippet of code I have written whilst trying to replicate the game minesweeper in very simplistic terms. I've got a slight query...

The code below generates a pair of co-ordinates, checks to see if the particular co-ordinates are already held in the ArrayList, and if not, adds them to the list, repeating this process until I have a list of ten mine locations. on running the program I have found that the list contains duplicates when it shouldn't...

public class MineSweeper {
    private static ArrayList mines;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        MineSweeper ms = new MineSweeper();

    }

    public MineSweeper(){
        mines = new ArrayList(10);
        generateMines();
        showMines();

    }

    private void generateMines(){
        int x = 0, y = 0, mineCount = 0;
        Random rnd = new Random();  
        StringBuilder str = new StringBuilder();

        while(mineCount != 10)
        {
            x = rnd.nextInt(9) + 1;
            y = rnd.nextInt(9) + 1;
            str.append(x).append(",").append(y);   
            if(!(mines.contains(str.toString())))
            {
                mines.add(str);
                mineCount ++;
            }
            str = new StringBuilder();
        }
    }

    private void showMines(){
        System.out.println(mines.toString());
    }
}

I believed that my if statement would catch any duplicates but was wrong. I eventually solved the problem by changing the if statement to if(!(mines.toString().contains(str)))

Can somebody enlighten me on the difference please?

Upvotes: 1

Views: 383

Answers (4)

chris.currin
chris.currin

Reputation: 151

if we look at your if statement:

mines.contains(str.toString())

mines is an ArrayList of generic type StringBuilder (because it had undefined generic type it automatically uses ArrayList<Object> ). This can be checked if you do this

System.out.println(mines.get(1) instanceof StringBuilder); //print true

str is a StringBuilder object which you have cast to a String. You are thus comparing a StringBuilder object to a String object. It is important to note that contains() uses equals() for comparison.

this can be illustrated with this example:

StringBuilder testStrB = new StringBuilder("test");
System.out.println(testStrB.equals(testStrB.toString())); //print false

in fact, I get the warning that equals() is used on incompatible types.

with your working statement

mines.toString().contains(str)

it seems that contains() accepts a CharSequence, which is a super-interface of StringBuilder. As mines.toString uses contains() of the entire String searching for a CharSequence represented by StringBuilder, it works.

in summary:

your initial (non-working) if statement tried to use (for each element of mines)

StringBuilder.equals(String)

whereas your working if statement used

String.contains(StringBuilder)

which allows StringBuilder to be used as a CharSequence and thus compared.

for interest:

System.out.println(testStrB.toString().equals(testStrB)); //prints false
// (and incompatible types warning)

so a String cannot EQUAL a StringBuilder, but can CONTAIN it. Probably because equals() takes an Object and contains() takes a CharSequence

Upvotes: 0

osundblad
osundblad

Reputation: 2681

ArrayList contains StringBuilder's and in mines.contains(str.toString()) you compare to a String (str.toString) so you compare a StringBuilder with a String thus they are never equal.

You have quite a number of other problems as well, for example mines field is static, Random is not, etc

Upvotes: 0

Mureinik
Mureinik

Reputation: 311428

You are checking if mines contains str.toString(), but adding str, which is a StringBuilder instance. Since all the objects you're adding are StringBuilders, mines can't contain a String.

You should choose which class you're going with, and stick to it. E.g., with Strings:

if (!(mines.contains(str.toString()))) {
    mines.add(str.toString());
    mineCount++;
}

Upvotes: 2

user2884232
user2884232

Reputation: 25

It could be an issue with the "if(!(mines.contains(str.toString())))", i just dont know how the coordinates are saved and accessed by the "ArrayList" object.

Upvotes: 1

Related Questions