检查 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 contains
是 O(n)
,唯一的问题是 HashSet
没有不允许重复。
是的,使用实际类型而不是 Object
List<MCWarTeam> teamlist = new ArrayList<>();
为了在 ArrayList 中搜索 MCWarTeam
实例,您首先必须覆盖 equals
以定义两个 MCWarTeam
实例的含义彼此相等。然后你可以使用indexOf(team)
或contains
来判断一个实例是否在List
.
但是,这样的搜索需要线性时间,因此 HashSet
可能更适合您的需求(为此您需要覆盖 equals
和 hashCode
, 你将能够在常数时间内找到一个对象是否在 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
中实现 equals
或 hashCode
,因为 you aren't gonna need it; as your map keys are team names, containsKey
对 String
对象进行操作具有明确定义的 equals
和 hashCode
语义。
我有以下对象列表:
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 contains
是 O(n)
,唯一的问题是 HashSet
没有不允许重复。
是的,使用实际类型而不是 Object
List<MCWarTeam> teamlist = new ArrayList<>();
为了在 ArrayList 中搜索 MCWarTeam
实例,您首先必须覆盖 equals
以定义两个 MCWarTeam
实例的含义彼此相等。然后你可以使用indexOf(team)
或contains
来判断一个实例是否在List
.
但是,这样的搜索需要线性时间,因此 HashSet
可能更适合您的需求(为此您需要覆盖 equals
和 hashCode
, 你将能够在常数时间内找到一个对象是否在 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 sameteamname
already exists, but not care about thejoinkey
?
如果 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
中实现 equals
或 hashCode
,因为 you aren't gonna need it; as your map keys are team names, containsKey
对 String
对象进行操作具有明确定义的 equals
和 hashCode
语义。