Рейтинг темы:
  • 0 Голос(ов) - 0 в среднем
  • 1
  • 2
  • 3
  • 4
  • 5
LinkedHashMap в эффекте
#1
При onStart() эффекта, в LinkedHashMap добавляет ключ-значение.
При onExit() эффекта, ключ-значение оттуда удаляется.

Словлю ли я Exception?, если onStart() по времени, вызовется одновременно с onExit() и карта, попробует добавить и удалить ключ-значение? Что вообще здесь происходит?

Может стоит использовать в таких случаях ConcurrentHashMap?
Ответ
#2
ConcurrentModificationException можно словить лишь в том случае, если во время перебора forEach, Iterator, удалить, добавить, либо еще сделать какую либо операцию по изменению элементов. Она приведет к ошибке.

P.S. Зачем нужна именно эта мапа ?) Для более ясного ответа, нужно знать - мапа работает на 1-го игрока, либо глобально на эффект ?
Smile
Ответ
#3
Mangol Написал:ConcurrentModificationException можно словить лишь в том случае, если во время перебора forEach, Iterator, удалить, добавить, либо еще сделать какую либо операцию по изменению элементов. Она приведет к ошибке.

P.S. Зачем нужна именно эта мапа ?) Для более ясного ответа, нужно знать - мапа работает на 1-го игрока, либо глобально на эффект ?

Мапа работает на одного игрока (один игрок управляет своей мапой) и содержит в себе данные на других (на ком лежит эффект). Накладывая эффект на очередную жертву, мапа обновляется и удаляется в зависимости от максимального окл-ва наложений эффекта:
Например, если эффект можно наложить лишь на 3 цели - одним кастером. При наложении на 4-ую, из мапы убирается 1 товарищ (и эффект с него тоже снимается) и добавляется другой.
Ответ
#4
finfan;422163 Написал:Словлю ли я Exception?, если onStart() по времени, вызовется одновременно с onExit() и карта, попробует добавить и удалить ключ-значение? Что вообще здесь происходит?
Нет, не словишь.
Если нечего удалять вернет null, как и в случае putIfAbsent, etc...
Как подметил Mangol ConcurrentModificationException - мы можем выхватить, только если удаляем напрямую из коллекции - во время работы итератора. Нужно использовать метод итератора remove(), чтобы было корректно.
Ответ
#5
Anikey Написал:Нет, не словишь.
Если нечего удалять вернет null, как и в случае putIfAbsent, etc...
Как подметил Mangol ConcurrentModificationException - мы можем выхватить, только если удаляем напрямую из коллекции - во время работы итератора. Нужно использовать метод итератора remove(), чтобы было корректно.

remove(); Итератора не спасет, все равно получим ConcurrentModificationException.
П.1 Не только удаляем, при любом добавлении либо удалении, получим ConcurrentModificationException.
На сколько я помню там есть проверка.
int mod=correctMod;
if(mod != correctMod)
привет ConcurrentModificationException;

Добавлено через 10 минут
finfan Написал:Мапа работает на одного игрока (один игрок управляет своей мапой) и содержит в себе данные на других (на ком лежит эффект). Накладывая эффект на очередную жертву, мапа обновляется и удаляется в зависимости от максимального окл-ва наложений эффекта:
Например, если эффект можно наложить лишь на 3 цели - одним кастером. При наложении на 4-ую, из мапы убирается 1 товарищ (и эффект с него тоже снимается) и добавляется другой.

А вообще.... Если боишься что влетит 2 потока, и что то не правильно добавится - удалиться. Используй ConcurrentHashMap<>();

Ну если на крайний случай map = HashMap<>();
//write code;
synchronized(map) // mutex
{
//write code;
}
//write code;
Smile
Ответ
#6
Если мапка не используется в каких либо итераторах, то можешь смело добавлять и тереть в ней сколько влезет.
Если же задействована в итераторе (не важно по ключам, значениям или парам), тогда уже нужен пакет concurency, либо синхронизация.
Вообще любое изменяемое хранилище, к которому могут получить доступ несколько потоков по дефолту должно быть конкурентным.
Ответ
#7
Mangol,
PHP код:
<?php 
final LinkedHashMap<Object, Object> linked = new LinkedHashMap<>();
linked.put("1", "1");
linked.put("2", "2");
linked.put("3", "3");

Следующие выражения выбьют ошибку:
Java 8:
PHP код:
<?php 
linked
.entrySet().stream().filter((i) -> ("3".equals(i.getKey()))).forEachOrdered((i) -> {
linked.remove(i.getKey());
});
Ниже 8 версии:
PHP код:
<?php 
for (Entry<Object, Object> i : linked.entrySet()) {
if (
"3".equals(i.getKey())) {
linked.remove(i.getKey());
}
}
А вот это решение отработает правильно и без ошибок:
PHP код:
<?php 
final Iterator<Entry<Object, Object>> i = linked.entrySet().iterator();
while (
i.hasNext()) {
if (
"3".equals(i.next().getKey())) {
i.remove();
}
}
Ответ
#8
Anikey Написал:Mangol,
PHP код:
<?php 
final LinkedHashMap<Object, Object> linked = new LinkedHashMap<>();
linked.put("1", "1");
linked.put("2", "2");
linked.put("3", "3");

Следующие выражения выбьют ошибку:
Java 8:
PHP код:
<?php 
linked
.entrySet().stream().filter((i) -> ("3".equals(i.getKey()))).forEachOrdered((i) -> {
linked.remove(i.getKey());
});
Ниже 8 версии:
PHP код:
<?php 
for (Entry<Object, Object> i : linked.entrySet()) {
if (
"3".equals(i.getKey())) {
linked.remove(i.getKey());
}
}
А вот это решение отработает правильно и без ошибок:
PHP код:
<?php 
[COLOR="red"]final Iterator<Entry<Object, Object>> i = linked.entrySet().iterator();
while (
i.hasNext()) {
if (
"3".equals(i.next().getKey())) {
i.remove();
}
}[/
COLOR]

if ("2".equals(i.next().getKey())) {
i.remove();
}

Сделай 2-ое удаление :redlol:
Smile
Ответ
#9
Mangol;422176 Написал:Сделай 2-ое удаление
Даже в разном порядке:
PHP код:
<?php 
final Iterator<Entry<Object, Object>> i = linked.entrySet().iterator();
while (
i.hasNext()) {
switch((String)
i.next().getKey()) {
case
"2":
case
"1":
i.remove();
break;
}
}
Ответ
#10
Smile
Ответ


Перейти к форуму:


Пользователи, просматривающие эту тему: 1 Гость(ей)