2016-03-05 164 views
1

我的Minecraft插件有问题。我想添加播放器的对象到列表中。在此之前,我想检查玩家是否已经存在于我的列表中。比较列表中对象的属性

下面的例子:

public class Player{ 

    public String playerName; 
    public int Count = 0; 

    public Player(String name){ 

     playerName = name; 
    } 
} 

这里主要类:

public class mainClass{ 
    List<Player> = PlayerList; 
    [...] 
    if(!(*An object with attribute examplename in List exist*)){ 
     Player p = new Player("eamplename") 
     PlayerList.Add(p); 
    } 
} 
+0

'Add'应是'add'。案件事宜 –

+0

谢谢,我知道。不幸的是我使用Java和C#并且总是这样做是错误的:) – Snaff

回答

2

我建议两种方法来解决你的问题。第一个是坚持使用List的方法。

List<Foo> list = new ArrayList<Foo>(); 

    boolean hasMyItem = false; 
    String newName = "hello world"; 

    for (Foo foo : list)  // iterate over each item in the list 
    { 
     if (foo.name.equals(newName)) 
     { 
      hasMyItem = true; 
      break;   // get out of for loop 
     } 
    } 

    if (!hasMyItem) 
    { 
     list.add(new Foo(newName)); 
    } 
    else 
    { 
     // the player is already in the list ... 
    } 

在这个代码片段中,我们遍历列表中的所有项目,直到我们发现玩家已经存在。如果您的列表中不存在此类播放器,它将以hasMyItem的值为false退出,在这种情况下,您会将新播放器添加到列表中。

迭代列表中的所有项目是一种常用的方法,它绝对是一件好事。但是,您可能会考虑使用另一个名为Map<Key, Value>的数据结构。 MapKeyValue相关联,并将它们像列表一样存储在Map中。

你可以认为Map<Key, Value>作为标签项目。 Key是每个项目的标签。假设你的桌子上有一堆笔记本,并且你想找到一个数学笔记。如果您知道数学笔记的独特标签,例如封面上的一些文本或图像,您可以毫不费力地找到它。在你的例子中,Key将成为用户名,Value将成为玩家。

Map有什么好处?它提供了一种简单的方法来查找您拥有的Key值。如果您使用Map,上述代码可以更简化。

Map<String, Foo> map = new HashMap<String, Foo>(); 

    Foo f1 = new Foo("name1"); 
    Foo f2 = new Foo("name2"); 
    Foo f3 = new Foo("name3"); 

    map.put("name1", f1); 
    map.put("name2", f2); 
    map.put("name3", f3); 

    // will return true and this if statement will be executed 
    if (map.containsKey("name1")) 
    { 
     // will be executed 
    } 

    // will return false because you don't have and this if statement will not be executed 
    if (map.containsKey("some new name")) 
    { 
     // will not be executed 
    } 

有由Map<K,V>提供其他有用的方法,其可以被发现here

作为一个附注,每当你可以声明每个班级成员为private,而不是default(这是你什么时候不指定任何内容)或public。关于为什么你应该这样做有很多讨论,但基本上是为了保护你自己的代码不受其他人的伤害。你可以很容易地搜索,但这里有一些链接。 Link1Link2

我希望这可以给你一些很好的起点。

+0

Hay Matthias,谢谢你的回答。我尝试了第一个版本,它的工作原理!谢谢。地图听起来很有趣,但是Value可以是一个具有许多属性的类?如果可以,我会加注你的帖子:( – Snaff

+0

是的值可以是一个具有许多属性的类,只要定义Map playersMap = new HashMap <>();这里你的关键字是name,值是Player。 java可以有很多属性,并且避免在使用For:each进行迭代时修改List。(http://stackoverflow.com/questions/9806421/concurrentmodificationexception-when-adding-inside-a-foreach-loop-in-arraylist) –

+0

是的,'Key'和'Value'部分都可以是任何'Class',甚至可以使用'Interface'当你声明你的'Map'时,你可以指定你想在每个'Key '和'Value',我试图暗示这样一个事实,即可以通过在地图声明中放置一个任意的类名“Foo”来将自己的类放入“Value”部分中(注意第一行)。 – BrokenBacon

0

由于有人指出,我使用的Set是不正确的,我已经决定在另一种方法(仍在使用重载equals法)

public class Player{ 
    public String playerName; 
    public int Count = 0; 
    public Player(String name){ 
     playerName = name; 
    } 
    public boolean equals(Player p){ 
     if(this==p) return true; 
     if(this.playerName.equals(p.playerName) return true; 
     return false; 
} 

而且

public class mainClass{ 
    ArrayList playerList; 
    public static void main(String[] args){ 
     playerList = new ArrayList<Player>(); 
     Player p = new Player("eamplename"); 
     checkList(p); 
    } 
    //check Player object against list and add if not exist 
    //if desired, the returned boolean can confirm whether or not 
    //player was successfully added 
    public static boolean checkList(Player player){ 
     for(Player p : playerList){ 
      if(p.equals(player)) return false; 
     } 
     playerList.add(player); 
     return true; 
} 
+0

谢谢你的回答:)我已经找到了解决方案,但你的想法是惊人的。也许我会尝试这一点,当我不得不改变一些东西。谢谢Calvin – Snaff

+0

'Set'是一个抽象接口,只有实现这个接口的特定类才能被实例化。例如'static Set playerList = new HashSet <>()'是有效的。如果要覆盖从java.lang.Object继承的默认'equals'方法,则覆盖方法的参数必须相同,在本例中为Object而不是Player,以便其他类型的对象可以也要进行比较。当前的equals方法被编译器认为是一种不同的方法,在添加到Set时不会在'e1.equals(e2)'操作中调用。 –

+0

@AdrianSohn我怀疑我的答案可能有些问题。谢谢你指出。我会坚持我现在知道的,并用不同的方法修改我的答案。 –