Почему нельзя отдавать ссылку на внутреннее хранилище
Есть задание написать потоко безопасное хранилище . Сказали , что нельзя отдавать ссылку на хранилище .Почему нельзя ? и почему тут лучше использовать hashmap ?
@ThreadSafe
public class UserStorage {
private List<SimpleUser> storage = new ArrayList<>();
public UserStorage(List<SimpleUser> storage) {
this.storage = storage;
}
public List<SimpleUser> getStorage() {
return storage;
}
public synchronized boolean add(SimpleUser user) {
return this.storage.add(user);
}
public synchronized boolean update(int id, SimpleUser user) {
boolean result = false;
for (int i = 0; i < this.storage.size(); i++) {
if (this.storage.get(i).getId() == id) {
this.storage.remove(i);
this.storage.add(i, user);
result = true;
break;
}
}
return result;
}
public synchronized boolean delete(SimpleUser user) {
return this.storage.remove(user);
}
public synchronized boolean transfer(int fromId, int toId, int amount) {
boolean result = false;
SimpleUser fromUser = storage.stream().filter(x -> x.getId() == fromId)
.findFirst().orElse(new SimpleUser(0, 0));
SimpleUser toUser = storage.stream().filter(x -> x.getId() == toId)
.findFirst().orElse(new SimpleUser(0, 0));
if (fromUser.getAmount() >= amount) {
toUser.setAmount(toUser.getAmount() + amount);
fromUser.setAmount(fromUser.getAmount() - amount);
result = true;
}
return result;
}
}
public class SimpleUser {
private final int id;
private int amount;
public SimpleUser(int id, int amount) {
this.id = id;
this.amount = amount;
}
public int getId() {
return id;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
@Override
public String toString() {
return "SimpleUser{" + "id=" + id + ", amount=" + amount + '}';
}
}
Ответы (1 шт):
Отдавать ссылку на хранилище нельзя, потому что это даст возможность пользователю выполнять операции непосредственно над хранилищем, обходя всю написанную Вами синхронизацию, что может привести даже к развалу (неконсистентному состоянию) хранилища. Доступ на чтение тоже надо синхронизировать, то есть для чтения надо писать отдельный метод, возвращающий либо отдельный элемент, либо потокобезопасную копию всего хранилища.
Для ответа на вопрос, что "лучше" использовать, надо знать, как к данным будут обращаться. Если id уникален, и получать данные будут по нему -- да, HashMap предпочтительнее, поиск по нему гораздо быстрее полного перебора.