检查Java的ArrayList中是否存在Object



我有以下对象列表:

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

我将对象添加到列表中,像这样:

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

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

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

我想检查是否已经有一个名为teamname的团队。或者,是否有更好的方法来存储对象?以前,我只是使用HashMap来添加teamname和joinkey,它工作得很好,但我认为使用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;
    }

基本上,如果返回false,用户将得到一条消息,解释他输入的命令的正确用法。

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

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

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

我只是想检查是否已经存在具有相同teamnameObject,但不关心joinkey ?

如果joinkey不是影响相等性的对象状态的一部分,那么将其保留为对象的一部分作为字段通常不是一个好主意。例如,如果joinkey是你用来"连接"团队与其他事物的临时物品,那么制作HashMap<String,MCWarTeam>,使用joinkey作为地图的关键,并从MCWarTeam中删除joinkey应该是一个好主意。

根据描述和您对其他答案的评论,不使用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,因为你不需要它;因为你的map键是团队名,所以containsKeyString对象进行操作,而equalshashCode的语义已经很好地定义了。

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

然而,这样的搜索将花费线性时间,因此HashSet可能更适合您的需求(为此,您需要覆盖equalshashCode,并且您将能够在常数时间内找到对象是否在Set中)。

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

 boolean exists = teamlist.contains(member);

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

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

最新更新