java 在Java中检查ArrayList中是否存在Object

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33329294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 21:31:11  来源:igfitidea点击:

Check if Object exists in ArrayList in Java

javaobjectarraylistbukkit

提问by Martin Hoffmann

I have the following List of objects:

我有以下对象列表:

private List<Object> teamlist = new ArrayList<Object>();

And I'm adding objects to the list like so:

我将对象添加到列表中,如下所示:

teamlist.add(new MCWarTeam(args[0], joinkey));

Now the objects in the list have no name, but can be referenced by using the list, right? Before I add a new element to the list, how can I check if an object with a certain attribute already exists? This is the constructor of the Objects:

现在列表中的对象没有名称,但可以通过列表进行引用,对吗?在向列表中添加新元素之前,如何检查具有特定属性的对象是否已存在?这是对象的构造函数:

public MCWarTeam(String teamname, String joinkey){
    this.teamname = teamname;
    this.joinkey = joinkey;
}

I want to check if there already is a team with the name teamname. Alternatively, is there a better way to store the Objects? Before, I just used a HashMap to add the teamname and joinkey and it worked just fine, but figured using Objects instead would be a better way to do it.

我想检查是否已经有一个名为teamname的团队。或者,有没有更好的方法来存储对象?之前,我只是使用 HashMap 来添加团队名称和 joinkey 并且它工作得很好,但我认为使用 Objects 会是一个更好的方法。

Here is the important code for the event handler:

这是事件处理程序的重要代码:

        else if (cmd.getName().equalsIgnoreCase("createTeam")) {
        if (args.length > 0 && args.length < 3) {
            String joinkey = "";
            if (args.length > 1)
                joinkey = args[1];

            String teamname = args[0];

            MCWarTeam newTeam = new MCWarTeam(teamname, joinkey);
            if (!teamlist.containsKey(teamname)) {
                teamlist.put(teamname, newTeam);
                sender.sendMessage("Created new team \"" + teamname + "\" with join key \"" + joinkey + "\" successfully! Teams:");

                sender.sendMessage("All teams:");
                for (String key : teamlist.keySet()) {
                    sender.sendMessage(key);
                }

            } else
                sender.sendMessage("Team already exists!");
            return true;
        }
        return false;
    }

    else if (cmd.getName().equalsIgnoreCase("joinTeam")) {
        if (args.length > 0 && args.length < 3) {
            String joinkey = "";
            if (args.length > 1)
                joinkey = args[1];

            String teamname = args[0];

            if (teamlist.containsKey(teamname)) {
                String teamKey = teamlist.get(teamname).getJoinKey();
                if (joinkey == teamKey) {
                    teamlist.get(teamname).addPlayer(playername);
                    Bukkit.broadcastMessage("MCWar: " + playername + " joined Team \"" + teamname + "\" successfully!");
                } else
                    sender.sendMessage("Join key incorrect!");
            } else {
                sender.sendMessage("Team doesn't exist! Teams:");
                for (String key : teamlist.keySet()) {
                    sender.sendMessage(key);
                }

            }
            return true;
        }
        return false;
    }

Basically, if it returns false, the user will get a message explaining the correct usage of the command he entered.

基本上,如果它返回 false,用户将收到一条消息,说明他输入的命令的正确用法。

采纳答案by Mick Mnemonic

Based on the description and your comments to other answers, it seems like a good idea to not use a List, but instead store your data in a Map<String, MCWarTeam>, which maps team names into MCWarTeamobjects:

根据描述和您对其他答案的评论,不使用 a 似乎是个好主意List,而是将您的数据存储在 a 中Map<String, MCWarTeam>,它将团队名称映射到MCWarTeam对象:

private Map<String, MCWarTeam> teams = new HashMap<>();

You can add a team, checking whether a team with the same name already exists, like this:

您可以添加一个团队,检查是否已经存在同名的团队,如下所示:

String teamName = args[0];

if (!teams.containsKey(teamName)) {
    teams.put(teamName, new MCWarTeam(teamName, joinKey));
} else {
    // do what you want when the team name was already in the map
}

Retrieving an MCWarTeamobject based on team name, e.g. for accessing the joinKeyattribute, is easy:

MCWarTeam根据团队名称检索对象(例如访问joinKey属性)很容易:

String joinKey = teams.get(teamName).getJoinKey();

Note that using this approach, you shouldn't implement equalsor hashCodein MCWarTeam, because you aren't gonna need it; as your map keys are team names, containsKeyoperates on Stringobjects which already have well-defined equalsand hashCodesemantics.

请注意,使用这种方法,您不应该实现equalshashCodein MCWarTeam,因为您不需要它;由于您的地图键是团队名称,因此containsKeyString已经具有明确定义equalshashCode语义的对象进行操作。

回答by dasblinkenlight

Java's List<T>has a boolean contains(Object)method, which is handy for situations when you wish to avoid duplicates:

JavaList<T>有一个boolean contains(Object)方法,它在您希望避免重复的情况下很方便:

if (!teamlist.contains(newTeam)) {
    teamlist.add(newTeam);
} 

MCWarTeamclass must implement equalsin order for this to work. When you override equals, you must also override hashCode.

MCWarTeam类必须实现equals才能使其工作。当您覆盖时equals,您还必须覆盖hashCode

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof MCWarTeam))  {
        return false;
    }
    MCWarTeam other = (MCWarTeam)obj;
    return teamname.equals(other.teamname)
        && joinkey.equals(other.joinkey);
}
@Override
public int hashCode() {
    return 31*teamname.hashCode()+joinkey.hashCode();
}

I'm just looking to check if an Objectwith the same teamnamealready exists, but not care about the joinkey?

我只是想检查是否已经存在Object相同的teamname,但不关心joinkey?

If joinkeyis not part of your object's state that influences equality, it is usually not a good idea to keep it as part of the object as a field. For example, if joinkeyis something transient which you use to "connect" teams to other things, making a HashMap<String,MCWarTeam>, using joinkeyas the key to the map, and removing joinkeyfrom MCWarTeamshould be a good idea.

如果joinkey它不是影响平等的对象状态的一部分,则将其作为对象的一部分作为字段保留通常不是一个好主意。例如,如果joinkey是临时的东西,你用它来将团队“连接”到其他东西,制作HashMap<String,MCWarTeam>,joinkey用作地图的关键,并joinkey从中删除MCWarTeam应该是一个好主意。

回答by Sleiman Jneidi

If you implement MCWarTeamequalsmethod properly, then containsshould tell you if the object exists.

如果你MCWarTeamequals正确地实现了方法,那么contains应该告诉你对象是否存在。

 boolean exists = teamlist.contains(member);

And as @Eran mentioned a HashSetwould give you O(1)lookup where list containsis O(n), the only thing is that HashSetdoesn't allow duplicates. And Yes, use the actual type rather than Object

正如@Eran 提到的, aHashSet会给你O(1)查找 where list containsis O(n),唯一的事情是HashSet不允许重复。是的,使用实际类型而不是Object

List<MCWarTeam> teamlist = new ArrayList<>();

回答by Eran

In order to search for an MCWarTeaminstance in the ArrayList, you'll first have to override equalsin order to define what it means for two MCWarTeaminstances to be equal to each other. Then you can use indexOf(team)or containsto determine whether a instance is in the List.

为了MCWarTeam在 ArrayList 中搜索实例,您首先必须覆盖equals以定义两个MCWarTeam实例彼此相等的含义。然后您可以使用indexOf(team)contains来确定实例是否在List.

However, such a search would take linear time, so a HashSetmay be better for your needs (for that purpose you'll need to override both equalsand hashCode, and you'll be able to find if an object is in the Setin constant time).

但是,这样的搜索需要线性时间,因此 aHashSet可能更适合您的需求(为此,您需要覆盖equalshashCode,并且您将能够找到对象是否Set在恒定时间内)。