tl; dr
Рассмотрите возможность использования HashMap вместо HashSet.В частности, рассмотрим
HashMap<KeyType, Object[]>
или, что еще лучше,
HashMap<KeyType, ItemWrapper>
, где KeyType - это String, Integer или некоторый другой тип уникального идентификатора вваш класс Item, а ItemWrapper - простой класс для хранения связанных данных.
HashMap может быть более подходящим для этого, чем HashSet
Вы говорите, что не хотите использовать массивы, потому что вы хотите быстропоиск с использованием идентификатора, отличного от порядка, в котором он был добавлен.Вы также хотите «сопоставить» свои товары с количеством.HashMap позволит вам связать ключ со значением для быстрого поиска.
Мы начнем с чрезмерно простой реализации, а затем сделаем ее лучше.Я также покажу, как вместо этого вы можете использовать массивы размера 2, как вы просите, хотя это и не самый лучший подход.
Базовая реализация, которую мы улучшим на
В слишком простойреализации, ваш ключ может быть вашим товаром, а ваша ценность - количеством.Например,
HashMap<Item, Integer> myHashMap = new HashMap<Item, Integer>(1400);
public int addItem(Item item, int n) {
//...
int currentCount = myHashMap.getOrDefault(item, 0);
myHashMap.put(item, n + currentCount);
//...
}
public int quantityOf(Item item) {
return myHashMap.getOrDefault(item, 0);
}
public boolean isInLocker(Item item) {
return myHashMap.containsKey(item);
//or return this.quantityOf(item) > 0;
}
(Обратите внимание, что этот код использует автобокс и распаковку , но может быть записан без него, если вы предпочитаете. Кроме того, вы можете настроить начальную емкость хэш-карты.при начальной емкости 1400 и коэффициенте загрузки 0,75 он изменит свой размер, как только в HashMap окажется около 1050 элементов.)
Проблема в том, что вам потребуется, чтобы объект Item уже был в порядкеискать этот пункт, который не может быть практичным в большинстве ситуаций.(Или, по крайней мере, вам нужно что-то с тем же результатом от hashCode()
, и это вернуло true для equals()
).При необходимости вы можете добавить @Overrides
для hashCode()
и equals()
в классе Item.Однако что, если класс Item предоставлен для вас, вы не можете его изменить (или не хотите), а hashCodes()
и equals()
не удовлетворяют вашим требованиям для быстрого поиска?В этом случае вам понадобится другой ключ, например, идентификатор элемента или уникальный дескриптор (например, строка будет работать, если все «карандашные» элементы будут обрабатываться одинаково в вашей программе).
Более надежный подход
Чтобы ваша мечта о быстром поиске работала с HashMap, вам нужен уникальный способ идентификации объектов Item - мы будем использовать его в качестве ключа.Для примера кода ниже, я предполагаю, что идентификатор является строкой.Вам также нужен способ связать Элемент с количеством.
Вместо использования Объекта [], я бы рекомендовал обернуть Элемент в новый простой класс, который отслеживает как элемент, так и его количество.,Например:
class ItemWrapper {
Item item;
int quantity;
}
(Я сохранил простой пример, но вы можете сделать членов приватными, добавить получателей / установщиков и т. Д., В зависимости от ситуации.)
Таким образом, ваш код болеечитается и требует меньше бросков.Затем вы использовали бы его с кодом, подобным следующему:
HashMap<String, ItemWrapper> myHashMap = new HashMap<String, ItemWrapper>(1400);
public int addItem(Item item, int n) {
//...
ItemWrapper wrappedItem = myHashMap.get(item.uniqueID);
if (wrappedItem == null) {
wrappedItem = new ItemWrapper(item, n);
}
else {
wrappedItem.quantity += n;
}
myHashMap.put(item.uniqueID, wrappedItem);
//...
}
public int quantityOf(String itemID) {
ItemWrapper wrappedItem = myHashMap.get(itemID);
return wrappedItem == null ? 0 : wrappedItem.quantity;
}
public boolean isInLocker(String itemID) {
return myHashMap.containsKey(itemID);
//or return this.quantityOf(itemID) > 0;
}
Прямой ответ на ваш вопрос с использованием массивов (не лучший подход)
В своем вопросе вы задали вопрос о массиверазмера 2. Вышеупомянутый подход - моя рекомендация, но если вы должны использовать массивы, вы можете сделать что-то вроде следующего кода:
HashMap<Item, Object[]> myHashMap = new HashMap<Item, Object[]>(1400);
public int addItem(Item item, int n) {
//...
Object[] itemBundle = myHashMap.get(item.uniqueID);
if (itemBundle == null) {
itemBundle = new Object[2];
itemBundle[0] = item;
itemBundle[1] = new Integer(n);
}
else {
itemBundle[2] = new Integer((Integer)itemBundle[2] + n);
}
myHashMap.put(item.uniqueID, itemBundle);
//...
}
public int quantityOf(String itemID) {
return myHashMap.getOrDefault(itemID, 0);
}
public boolean isInLocker(String itemID) {
return myHashMap.containsKey(itemID);
//or return this.quantityOf(itemID) > 0;
}
TDD
Ваш«дополнительный вопрос» о разработке через тестирование, вероятно, лучше всего исследовать как отдельный вопрос.И вы спрашиваете о том, как концептуально подходить к TDD или как на самом деле написать код для тестов?В любом случае, вы можете найти отличные ответы, выполнив поиск по существующему контенту StackOverflow.