2015-10-25 2 views
3

У меня есть следующий список предметов:Проверьте объект существует в ArrayList в 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, чтобы добавить имя команды и joinkey, и это сработало отлично, но, используя объекты, вместо этого было бы лучшим способом сделать это.

Вот важный код для обработчика событий:

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

В принципе, если она возвращает ложь, то пользователь получит сообщение, описывающее правильное использование команды он вошел.

+0

Вы переопределяете 'equals' в MCWarTeam? Если это так, просто используйте 'List.contains'. –

+0

Вы, вероятно, хотите ввести список в '' вместо' '. Также я не знаю, как вы поняли, что «ArrayList» как-то по своей сути лучше, чем «HashMap», но я надеюсь, что вы основывали это на чем-то реальном, а не просто на ощупь. – Kayaman

+0

Трудно ли прочитать [спецификацию] (http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html)? –

ответ

2

Основываясь на описании и комментариях к другим ответам, это кажется хорошей идеей, чтобы не использовать 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(); 

Обратите внимание, что с помощью этого подхода, вы не должны осуществлять equals или hashCode в MCWarTeam, потому что you aren't gonna need it; поскольку ваши ключи карты являются именами команд, containsKey работает на String объектах, которые уже имеют четко определенные equals и hashCode семантики.

+0

Это действительно кажется лучшим способом, который я видел для этого. Я попробую, когда я буду дома, спасибо –

+0

Я получаю странную ошибку здесь. В функции я добавляю команды с командой teamlist.put (teamname, newTeam); '. Теперь каждый раз, когда я проверяю, существует ли запись, через 'teamlist.containsKey (teamname)', он выглядит пустым. Никаких результатов не появляется, когда я позволяю ему работать через цикл, но когда я запускаю тот же цикл после добавления элемента, появляются все добавленные элементы. EDIT: это когда я вызываю/createteam и/jointeam после друг друга. Http://prntscr.com/8vpdnk –

+0

Трудно сказать, что может происходить там, не видя кода.Не могли бы вы изменить свой вопрос и опубликовать код, в котором вы добавляете команды/проверяете записи? –

2

Если вы применили метод MCWarTeamequals, то contains должен сообщить вам, существует ли объект.

boolean exists = teamlist.contains(member); 

И как @Eran упомянул HashSet даст вам O(1) поиск где list contains является O(n), единственное, что HashSet не допускает дубликатов. И да, использовать фактический тип, а не Object

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

«Set» может быть непрактичным для OP, потому что хотя 'contains' работает хорошо, единственный способ для _retrieve_ элементов - итерация; нет метода 'get'. По этой причине лучшим вариантом будет «Карта ». –

2

Для того, чтобы найти для MCWarTeam например, в ArrayList, вы должны сначала переопределить equals для того, чтобы определить, что это означает, что в течение двух MCWarTeam экземпляров в быть равными друг другу. Затем вы можете использовать indexOf(team) или contains, чтобы определить, находится ли экземпляр в List.

Однако, такой поиск будет принимать линейное время, так HashSet может быть лучше для ваших нужд (для этой цели вам необходимо переопределить как equals и hashCode, и вы сможете найти, если объект является в Set в постоянное время).

6

в Java List<T> имеет метод, который удобен для ситуаций, когда вы хотите, чтобы избежать дубликатов:

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

Я просто смотрю, чтобы проверить, если Object с тем же teamname уже существует, но не заботиться о joinkey?

Если joinkey не является частью состояния вашего объекта, который влияет на равенство, то, как правило, не очень хорошая идея, чтобы сохранить его как часть объекта в поле. Например, если joinkey - это нечто переходное, которое вы используете для «соединения» команд с другими вещами, делая HashMap<String,MCWarTeam>, используя joinkey в качестве ключа к карте, и удаление joinkey из MCWarTeam должно быть хорошей идеей.

+0

joinkey - это что-то вроде пароля, который пользователь должен будет ввести, чтобы стать частью команды, но я вижу, как это имя может вводить в заблуждение. Можете ли вы мне объяснить, как 'MCWarTeam other = (MCWarTeam) obj; return teamname.equals (other.teamname); ' работает, чтобы увидеть, есть ли в списке объект с тем же именем? –

+0

@MartinHoffmann 'teamlist.contains (newTeam)' метод вызывает метод equals (Object) 'под капотом, сравнивая' newTeam' с тем, что уже есть в списке. – dasblinkenlight

+0

Как я могу получить строку 'joinkey' из' teamname'? Я попробовал следующее: 'String teamKey = teamlist.get (teamlist.indexOf (teamname)). GetJoinKey();' и попытался использовать тестовый MCWar-объект с тем же именем вместо 'teamname' в' indexOf() ' , но это тоже не сработало, мне тоже нужно @Overwrite 'indexOf()'? –

Смежные вопросы