检查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
。
您可能还想将列表键入<MCWarTeam>
而不是<Object>
。另外我不知道您是如何认为ArrayList
本质上比HashMap
更好的,但我希望您基于真实的东西而不是直觉。
看specification有那么难吗?
【参考方案1】:
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();
我只是想检查具有相同
teamname
的Object
是否已经存在,但不关心joinkey
?
如果joinkey
不是影响相等性的对象状态的一部分,则将其作为字段作为对象的一部分保留通常不是一个好主意。例如,如果joinkey
是临时的,您可以使用它来将团队“连接”到其他事物,则制作HashMap<String,MCWarTeam>
,使用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<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
中实现equals
或hashCode
,因为you aren't gonna need it;由于您的地图键是团队名称,containsKey
对已经具有明确定义的 equals
和 hashCode
语义的 String
对象进行操作。
【讨论】:
这似乎是我见过的最好的方法。我在家的时候试试,谢谢 我在这里遇到了一个奇怪的错误。在一个函数中,我使用teamlist.put(teamname, newTeam);
添加团队。现在,每次我通过teamlist.containsKey(teamname)
检查条目是否存在时,它都会显示为空。当我让它通过一个循环运行时没有结果显示,但是当我在添加一个元素后运行完全相同的循环时,所有添加的元素都会显示出来。编辑:这是我互相调用 /createteam 和 /jointeam prntscr.com/8vpdnk
如果没有看到代码,很难说那里可能发生什么。您能否编辑您的问题并将代码发布到您添加团队/检查条目的位置?
我做到了,谢谢。上面定义了 HashMap 团队列表。
我注意到的一件事是您将连接键 String
s 与 ==
进行比较;你应该改用equals
。您可以尝试将比较更改为joinkey.equals(teamKey)
,看看它是否有任何效果。除此之外,仍然很难说您的实际问题是什么。我不熟悉 Bukkit 或其事件处理框架,但如果事件被异步处理,这里可能还会出现一些计时问题。发布更多代码将有助于跟踪问题。另外,请在所有if
s 和else
s 中使用大括号(
)(即使是包含单个语句的)。【参考方案3】:
为了在 ArrayList 中搜索 MCWarTeam
实例,您首先必须覆盖 equals
以定义两个 MCWarTeam
实例彼此相等的含义。然后可以使用indexOf(team)
或contains
来判断一个实例是否在List
中。
但是,这样的搜索需要线性时间,因此 HashSet
可能更适合您的需求(为此,您需要同时覆盖 equals
和 hashCode
,并且您将能够在恒定时间内查找对象是否在Set
中)。
【讨论】:
【参考方案4】:如果你正确地实现了MCWarTeam
equals
方法,那么contains
应该会告诉你对象是否存在。
boolean exists = teamlist.contains(member);
正如@Eran 提到的,HashSet
会为您提供O(1)
查找,其中list contains
是O(n)
,唯一的问题是HashSet
不允许重复。
是的,使用实际类型而不是Object
List<MCWarTeam> teamlist = new ArrayList<>();
【讨论】:
Set
对于 OP 来说可能是不切实际的,因为即使 contains
表现良好,检索元素的唯一方法是通过迭代;没有get
方法。出于这个原因,Map<String,MCWarTeam>
可能是最好的选择。以上是关于检查Java中的ArrayList中是不是存在Object的主要内容,如果未能解决你的问题,请参考以下文章