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

Posted

技术标签:

【中文标题】检查Java中的ArrayList中是不是存在Object【英文标题】:Check if Object exists in ArrayList in Java检查Java中的ArrayList中是否存在Object 【发布时间】:2016-01-24 13:56:47 【问题描述】:

我有以下对象列表:

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 来添加团队名称和 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,用户将收到一条消息,说明他输入的命令的正确用法。

【问题讨论】:

你在 MCWarTeam 中覆盖 equals 吗?如果是这样,只需使用List.contains 您可能还想将列表键入&lt;MCWarTeam&gt; 而不是&lt;Object&gt;。另外我不知道您是如何认为ArrayList 本质上比HashMap 更好的,但我希望您基于真实的东西而不是直觉。 看specification有那么难吗? 【参考方案1】:

Java 的 List&lt;T&gt; 有一个 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&lt;String,MCWarTeam&gt;,使用joinkey 作为地图的键,并从MCWarTeam 中删除joinkey 应该是好主意。

【讨论】:

joinkey 类似于用户必须输入才能成为团队成员的密码,但我知道这个名称可能会产生误导。你能向我解释一下MCWarTeam other = (MCWarTeam)obj; return teamname.equals(other.teamname); 是如何查看列表中是否已经存在同名对象的吗? @MartinHoffmann teamlist.contains(newTeam) 方法在后台调用 equals(Object) 方法,将 newTeam 与列表中已有的进行比较。 如何从teamname 获取字符串joinkey?我尝试了以下方法:String teamKey = teamlist.get(teamlist.indexOf(teamname)).getJoinKey(); 并尝试在indexOf() 中使用具有相同名称的测试 MCWar 对象代替 teamname,但这也不起作用,我是否也必须 @Overwrite indexOf() ?【参考方案2】:

根据描述和您对其他答案的 cmets,最好不要使用 List,而是将您的数据存储在 Map&lt;String, MCWarTeam&gt; 中,它将团队名称映射到 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;由于您的地图键是团队名称,containsKey 对已经具有明确定义的 equalshashCode 语义的 String 对象进行操作。

【讨论】:

这似乎是我见过的最好的方法。我在家的时候试试,谢谢 我在这里遇到了一个奇怪的错误。在一个函数中,我使用teamlist.put(teamname, newTeam); 添加团队。现在,每次我通过teamlist.containsKey(teamname) 检查条目是否存在时,它都会显示为空。当我让它通过一个循环运行时没有结果显示,但是当我在添加一个元素后运行完全相同的循环时,所有添加的元素都会显示出来。编辑:这是我互相调用 /createteam 和 /jointeam prntscr.com/8vpdnk 如果没有看到代码,很难说那里可能发生什么。您能否编辑您的问题并将代码发布到您添加团队/检查条目的位置? 我做到了,谢谢。上面定义了 HashMap 团队列表。 我注意到的一件事是您将连接键 Strings 与 == 进行比较;你应该改用equals。您可以尝试将比较更改为joinkey.equals(teamKey),看看它是否有任何效果。除此之外,仍然很难说您的实际问题是什么。我不熟悉 Bukkit 或其事件处理框架,但如果事件被异步处理,这里可能还会出现一些计时问题。发布更多代码将有助于跟踪问题。另外,请在所有ifs 和elses 中使用大括号( )(即使是包含单个语句的)。【参考方案3】:

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

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

【讨论】:

【参考方案4】:

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

 boolean exists = teamlist.contains(member);

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

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

【讨论】:

Set 对于 OP 来说可能是不切实际的,因为即使 contains 表现良好,检索元素的唯一方法是通过迭代;没有get 方法。出于这个原因,Map&lt;String,MCWarTeam&gt; 可能是最好的选择。

以上是关于检查Java中的ArrayList中是不是存在Object的主要内容,如果未能解决你的问题,请参考以下文章

java 手工实现ArrayList版本2

ArrayList - 如何检查索引是不是存在?

检查arraylist对象是不是存在

java怎么检查句子里的一个词是不是包含在arraylist里

在 Anylogic 中检查墙壁是不是存在

如何检查字符串是不是包含字母表中的所有字母? [复制]