简体   繁体   English

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

[英]Check if Object exists in ArrayList in Java

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: 这是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 . 我想检查是否已经有一个名为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. 之前,我只是使用HashMap添加了teamname和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,则用户将收到一条消息,说明他输入的命令的正确用法。

Java's List<T> has a boolean contains(Object) method, which is handy for situations when you wish to avoid duplicates: Java的List<T>有一个boolean contains(Object)方法,当你想避免重复时,它很方便:

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

MCWarTeam class must implement equals in order for this to work. MCWarTeam类必须实现equals才能使其正常工作。 When you override equals , you must also override hashCode . 覆盖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 Object with the same teamname already exists, but not care about the joinkey ? 我只是想检查一个具有相同teamnameObject是否已经存在,但是不关心joinkey

If joinkey is 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. 如果joinkey不是影响相等性的对象状态的一部分,那么将它作为字段作为对象的一部分通常不是一个好主意。 For example, if joinkey is something transient which you use to "connect" teams to other things, making a HashMap<String,MCWarTeam> , using joinkey as the key to the map, and removing joinkey from MCWarTeam should be a good idea. 例如,如果joinkey是你用的东西瞬态队“连接”到其他事情,制作HashMap<String,MCWarTeam>使用joinkey为重点,以地图和删除joinkeyMCWarTeam应该是一个不错的主意。

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 MCWarTeam objects: 根据描述和对其他答案的评论,不使用List似乎是个好主意,而是将数据存储在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 MCWarTeam object based on team name, eg for accessing the joinKey attribute, is easy: 基于团队名称检索MCWarTeam对象(例如,用于访问joinKey属性)很容易:

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

Note that using this approach, you shouldn't implement equals or hashCode in MCWarTeam , because you aren't gonna need it ; 请注意,使用这种方法,您不应该在MCWarTeam实现equalshashCode ,因为您不需要它 ; as your map keys are team names, containsKey operates on String objects which already have well-defined equals and hashCode semantics. 由于您的映射键是团队名称, containsKey对已经具有明确定义的equalshashCode语义的String对象进行操作。

If you implement MCWarTeam equals method properly, then contains should tell you if the object exists. 如果正确实现MCWarTeam equals方法,那么contains应告诉您对象是否存在。

 boolean exists = teamlist.contains(member);

And as @Eran mentioned a HashSet would give you O(1) lookup where list contains is O(n) , the only thing is that HashSet doesn't allow duplicates. 并且正如@Eran提到的, HashSet会给你O(1)查找,其中list containsO(n) ,唯一的是HashSet不允许重复。 And Yes, use the actual type rather than Object 是的,使用实际类型而不是Object

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

In order to search for an MCWarTeam instance in the ArrayList, you'll first have to override equals in order to define what it means for two MCWarTeam instances to be equal to each other. 为了在ArrayList中搜索MCWarTeam实例,您首先必须重写equals ,以便定义两个MCWarTeam实例彼此相等的MCWarTeam Then you can use indexOf(team) or contains to determine whether a instance is in the List . 然后,您可以使用indexOf(team)contains来确定实例是否在List

However, such a search would take linear time, so a HashSet may be better for your needs (for that purpose you'll need to override both equals and hashCode , and you'll be able to find if an object is in the Set in constant time). 但是,这样的搜索需要线性时间,因此HashSet可能更适合您的需要(为此您需要覆盖equalshashCode ,并且您将能够找到对象是否在Set中恒定时间)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM