检查 Java 中的 ArrayList 中是否存在对象

Check if Object exists in ArrayList in Java

我有以下对象列表:

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

我正在向列表中添加对象,如下所示:

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

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

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

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

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

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

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

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

 boolean exists = teamlist.contains(member);

正如@Eran 提到的那样,HashSet 会给你 O(1) 查找,其中 list containsO(n),唯一的问题是 HashSet 没有不允许重复。 是的,使用实际类型而不是 Object

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

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

但是,这样的搜索需要线性时间,因此 HashSet 可能更适合您的需求(为此您需要覆盖 equalshashCode , 你将能够在常数时间内找到一个对象是否在 Set 中。

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

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

MCWarTeam class 必须实施 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 Object with the same teamname already exists, but not care about the joinkey?

如果 joinkey 不是影响相等性的对象状态的一部分,将其作为字段作为对象的一部分通常不是一个好主意。例如,如果 joinkey 是暂时的东西,你用它来 "connect" 团队做其他事情,制作 HashMap<String,MCWarTeam>,使用 joinkey 作为地图的键,并删除 joinkey 来自 MCWarTeam 应该是个好主意。

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

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

你可以添加一个团队,检查是否已经存在同名的团队,像这样:

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
}

根据团队名称检索 MCWarTeam 对象,例如要访问 joinKey 属性,很简单:

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

请注意,使用此方法时,您不应在 MCWarTeam 中实现 equalshashCode,因为 you aren't gonna need it; as your map keys are team names, containsKeyString 对象进行操作具有明确定义的 equalshashCode 语义。