java - 不允许数组列表中的对象重复

标签 java arraylist

我目前正在用 Java 开发一款家庭恩怨游戏。我有一个名为 questions 的对象问题的数组列表,它存储在整个游戏中使用的随机问题。我试图以某种方式填充数组列表以确保没有重复项,但是它不起作用并且我收到了重复项。

初始化为字段的是我的问题数组列表:

private ArrayList<Question> questions = new ArrayList<>();

这是我目前正在尝试的:

//Populates questions list
        for(int i=0; i<15; i++)
        {
           Question q = new Question();
           //makes sure there are no duplicates
            if(!questions.contains(q))
                questions.add(q); //not working for some reason cry

           System.out.println(q.getQuestion());
        }

当我打印出问题时,我仍然得到重复的问题:

Name something you would see on the Jerry Springer show:
Name something that would get you thrown out of most bars:
What accent might an American pretend to have in order to sound more attractive:
Name a breed of dog that might be used as a guard dog:
Name a place where a child might get seperated from its parents:
Name something you would see on the Jerry Springer show:
Name something that would get you thrown out of most bars:
Name a place where a child might get seperated from its parents:
Name something for which you need a warranty:
Name a game that would be inappropriate at a company party:
Name something for which you need a warranty:
Name a place where a child might get seperated from its parents:
Name an activity that could be rained out:
Name something for which you need a warranty:
Name something that would get you thrown out of most bars:

我确实重写了我的问题类中的 equals 方法,但它并没有解决问题。这是我的问题类:

/**
 * Question proposed to players to guess one of the answers on the board
 *
 * Each question has 5 possible answers
 *
 * The top answer to each question is stored at Answers(0) and is worth the most
 * The last answer is stored at Answers(4) and is worth the least
 *
 *
 * @author Stefan Gligorevic
 */
import java.util.ArrayList;
import java.util.Random;
import java.lang.String;
import java.lang.Object;

public class Question {

    private ArrayList<Answer> answers;
    private String question;

    /**** MIGHT HAVE TO INITIALIZE ANSWERS TO AN ARRAY LIST WITH NO SIZE SO ADD CAN WORK ****/
    //constructors
    public Question(){
        answers = new ArrayList<>();
        question=getRandomQuestion();
    }

    //makes a random question with a set of answers
    public String getRandomQuestion() {
        String ask = "";

        Random rand = new Random();
        int n = 1 + rand.nextInt(10);

        switch (n)
        {
            case 1:
                ask="Name a place where a child might get seperated from its parents:";
                answers.add(new Answer("Mall", 38));
                answers.add(new Answer("Park", 23));
                answers.add(new Answer("Zoo", 16));
                answers.add(new Answer("Theme Park", 16));
                answers.add(new Answer("Airport", 5));
                break;
            case 2:
                ask="Name something for which you need a warranty:";
                answers.add(new Answer("Car", 54));
                answers.add(new Answer("TV", 23));
                answers.add(new Answer("Watch", 8));
                answers.add(new Answer("Computers", 4));
                answers.add(new Answer("Appliance", 3));
                break;
            case 3:
                ask="Name a fruit you can buy dried:";
                answers.add(new Answer("Grape", 22));
                answers.add(new Answer("Banana", 21));
                answers.add(new Answer("Apricot", 21));
                answers.add(new Answer("Prune", 17));
                answers.add(new Answer("Apple", 15));
                break;
            case 4:
                ask="Name an activity that could be rained out:";
                answers.add(new Answer("Sports Event", 45));
                answers.add(new Answer("Picnic", 34));
                answers.add(new Answer("Wedding", 10));
                answers.add(new Answer("Concert", 7));
                answers.add(new Answer("Barbecue", 3));
                break;
            case 5:
                ask="What accent might an American pretend to have in order to sound more attractive:";
                answers.add(new Answer("French", 61));
                answers.add(new Answer("British", 18));
                answers.add(new Answer("Italian", 8));
                answers.add(new Answer("Spanish", 8));
                answers.add(new Answer("Australian", 3));
                break;
            case 6:
                ask="Name a sport that might be played at a family reunion:";
                answers.add(new Answer("Football", 54));
                answers.add(new Answer("Baseball", 21));
                answers.add(new Answer("Horseshoe", 8));
                answers.add(new Answer("Frisbee", 7));
                answers.add(new Answer("Basketball", 6));
                break;
            case 7:
                ask="Name a game that would be inappropriate at a company party:";
                answers.add(new Answer("Spin the Bottle", 41));
                answers.add(new Answer("Strip Poker", 32));
                answers.add(new Answer("Twister", 11));
                answers.add(new Answer("Truth or Dare", 11));
                answers.add(new Answer("Beer Pong", 3));
                break;
            case 8:
                ask="Name something that would get you thrown out of most bars:";
                answers.add(new Answer("Getting in a fight", 45));
                answers.add(new Answer("Drinking too much", 29));
                answers.add(new Answer("Not Paying", 6));
                answers.add(new Answer("Stripping", 5));
                answers.add(new Answer("Being underage", 3));
                break;
            case 9:
                ask="Name something you would see on the Jerry Springer show:";
                answers.add(new Answer("Fighting", 56));
                answers.add(new Answer("Nudity", 22));
                answers.add(new Answer("Security", 6));
                answers.add(new Answer("Jerry Springer", 4));
                answers.add(new Answer("Chairs Thrown", 3));
                break;
            case 10:
                ask="Name a breed of dog that might be used as a guard dog:";
                answers.add(new Answer("German Shepard", 36));
                answers.add(new Answer("Pit Bull", 23));
                answers.add(new Answer("Doberman Pinscher", 20));
                answers.add(new Answer("Rottweiler", 8));
                answers.add(new Answer("Bulldog", 5));
                break;
            default:
                //won't reach this hehe
        } //end switch
        return ask;
    }

    @Override
    public boolean equals(Object obj)
    {
        if(obj == null)
            return false;

        if(!Question.class.isAssignableFrom(obj.getClass()))
            return false;

        final Question q = (Question) obj;

        if(q.getQuestion() == null || this.getQuestion() == null)
            return false;

        if(!this.getQuestion().equalsIgnoreCase(q.getQuestion()))
            return false;

        return true;
    }

    //getters and setters
    public String getQuestion() { return question; }
    public ArrayList<Answer> getAnswers() { return answers; }

    //returns answer at given index
    public Answer answerAt(int index) { return answers.get(index); }
    //returns String of answer at specified index
    public String getAnswerAt(int index) { return answers.get(index).getAnswer(); }
    //returns point value of answer at specified index
    public int getAnswerPoints(int index) { return answers.get(index).getValue(); }

    //returns the points earned for this question
    //points are the point values of all the answers that have been found
    public int pointsEarned() {
        int points=0;
        for (int i=0; i<answers.size(); i++)
        {
            if(answers.get(i).isFound())
                points += answers.get(i).getValue();
        }
        return points;
    }

    //Sets a particular answer's value
    public void setAnswerVal(int index, int val) { answers.get(index).setValue(val); }

    //Add a multiplier to each answer's value for the question
    public void addMultiplier(int multiplier)
    {
        for(int i=0; i<answers.size(); i++)
        {
            int val = answers.get(i).getValue();
            answers.get(i).setValue(multiplier * val);
        }
    }

    //returns string of each answer
    public String topAnswer() { return answers.get(0).getAnswer(); }
    public String Answer2() { return answers.get(1).getAnswer(); }
    public String Answer3() { return answers.get(2).getAnswer(); }
    public String Answer4() { return answers.get(3).getAnswer(); }
    public String lastAnswer() { return answers.get(4).getAnswer(); }

    //returns values of each answer
    public int topAnswerVal() { return answers.get(0).getValue(); }
    public int Answer2Val() { return answers.get(1).getValue(); }
    public int Answer3Val() { return answers.get(2).getValue(); }
    public int Answer4Val() { return answers.get(3).getValue(); }
    public int lastAnswerVal() { return answers.get(4).getValue(); }

}

我不明白为什么它不起作用:(非常感谢帮助!

最佳答案

您重写的 equals 方法逻辑很好。只是你正在做sysout在错误的地方让你相信逻辑不起作用。不要在添加问题的 for 循环内打印问题,而是在该循环外部打印它。像下面这样修改你的逻辑,你会得到预期的结果

    for(int i=0; i<15; i++)
    {
        Question q = new Question();
        //makes sure there are no duplicates
        if(!questions.contains(q))
            questions.add(q); //not working for some reason cry
    }
    for (Question question : questions) {
        System.out.println(question.getQuestion());
    }

请注意,每当您覆盖 equals 时方法,您应该覆盖 hashCode以及。因为如果你不这样做,那么 Object 中的默认实现将使用类。因此,即使根据 equals() 方法它们相等,它们也可能具有不同的哈希码。您正在使用Arraylist ,所以您在这里不会遇到问题,但会遇到一些集合,例如 HashSet, HashMap它同时使用 equalshashcode用于添加和检索对象。这可能会给您带来意想不到的结果。因此,请始终一致地覆盖它们。 Link

public int hashCode(){
    return question.hashCode();
    }

此外,如果您的平等逻辑基于 String question只是,我建议您要么将您的 Question类工具Comparable或创建一个 Comparator为您Question类,而不是使用 ArrayList要保存问题列表,请使用 Set(TreeSet)这样 1)您不必担心实现 equals 和 hashcode 方法,2)您不必总是检查添加新问题。下面是代码片段

实现Comparable<Question>

@Override
public int compareTo(Question question) {
    return this.getQuestion().compareTo(question.getQuestion());
}

Set 添加问题

Set<Question> questions = new TreeSet<>();
    for(int i=0; i<15; i++)
    {
        questions.add(new Question());
    }
    for (Question question : questions) {
        System.out.println(question.getQuestion());
    }

关于java - 不允许数组列表中的对象重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59597019/

相关文章:

java - 在 ArrayList 的 ArrayList 中查找唯一的 Arraylist

java - 如何对 ArrayList<CustomObject> 中的元素进行分组

java - 如何在java中创建动态二维矩阵?

java - 按降序或升序排列日期的 ArrayList

java - 通过 REST 发送包含加密数据的字节数组

java - VAO绘图错误索引

java - 如何将 Integer 包装器类传递给 java 中的方法?

java - java中的用户脚本输入

java - 如何从命令行编译/运行 netbeans 项目?

java - 比较自定义 ArrayList 中的日期