Arraylist toString() 方法和重复值

Arraylist toString() method and duplicate values

下面我发布了一段我在尝试以非常简单的方式复制扫雷游戏时编写的代码。我有一个小问题...

下面的代码生成一对坐标,检查特定坐标是否已经保存在 ArrayList 中,如果没有,将它们添加到列表中,重复此过程直到我有十个矿区的清单。在 运行 该程序上,我发现该列表包含不应该出现的重复...

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());
    }
}

我相信我的 if statement 会捕获任何重复项,但我错了。 我最终通过将 if statement 更改为 if(!(mines.toString().contains(str)))

解决了问题

有人能告诉我区别吗?

这可能是 "if(!(mines.contains(str.toString())))" 的问题,我只是不知道 "ArrayList" 对象如何保存和访问坐标。

您正在检查 mines 是否包含 str.toString(),但添加 str,这是一个 StringBuilder 实例。由于您要添加的所有对象都是 StringBuilder,因此 mines 不能包含 String.

你应该选择你要去的class,并坚持下去。例如,Strings:

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

ArrayList 包含 StringBuilder,在 mines.contains(str.toString()) 中,您与字符串 (str.toString) 进行比较,因此您将 StringBuilder 与字符串进行比较,因此它们永远不相等。

你还有很多其他问题,例如地雷场是静态的,随机不是等等

如果我们查看您的 if 语句:

mines.contains(str.toString())

mines 是泛型 StringBuilderArrayList (因为它有未定义的泛型,它自动使用 ArrayList<Object> )。如果你这样做可以检查

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

str 是您已转换为 StringStringBuilder 对象。因此,您将 StringBuilder 对象与 String 对象进行比较。需要注意的是,contains()使用equals()进行比较。

这可以用这个例子来说明:

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

事实上,我收到了 equals() 用于不兼容类型的警告。

加上你的工作陈述

mines.toString().contains(str)

似乎contains()接受了一个CharSequence,它是StringBuilder的超级接口。由于 mines.toString 使用整个 Stringcontains() 搜索由 StringBuilder 表示的 CharSequence,它有效。

总结:

你的初始(非工作)if 语句试图使用(对于 mines 的每个元素)

StringBuilder.equals(String)

而您的工作 if 语句使用了

String.contains(StringBuilder)

允许 StringBuilder 用作 CharSequence 并进行比较。

兴趣:

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

所以 String 不能等于 StringBuilder,但可以包含它。可能是因为 equals() 需要一个 Objectcontains() 需要一个 CharSequence