Как узнать, существует ли элемент в Hashset массивов размера 2, когда элементы хранятся в Arr [0]? - PullRequest
0 голосов
/ 09 апреля 2019

Я пытаюсь создать класс Locker и класс Long Term Storage для домашней работы в универе.Они оба должны иметь возможность хранить объект Item, который уже был создан нашими учителями, который имеет объем и тип.(В то время как каждый Locker имеет ограниченное количество единиц хранения, а долговременное хранилище имеет установленный объем 1000 единиц.) Я пытаюсь решить, как реализовать хранилище наилучшим образом.Я думал просто о создании массива, потому что я знаю, что в общем случае топы из 1000 предметов - это немного, но я хочу написать лучший и наиболее эффективный код, какой только могу, и для их порядка нет значения.Мы только что узнали о HashSets, и поэтому я подумал о том, возможно, создать HashSet, который сделает время выполнения моей программы намного лучше.Проблема в том, что мне нужно вести подсчет количества предметов, хранящихся в каждом виде, а наборы не допускают дублирования.И поэтому я подумал о создании HashSet из массивов длиной 2, которые отслеживают тип элемента и его количество в хранилище.

Я не совсем уверен, каков наилучший способ реализовать такое хранилищеи возможно я иду с абсолютно неправильным путем.Мне просто кажется, что простые массивы не очень эффективны, когда я хочу найти конкретный тип элемента из 1000. (в случае, если 1000 различных элементов другого типа и объема 1 хранятся в долговременном хранилище).

Дополнительный вопрос: в этом упражнении я должен работать с методом TDD (Test Driven Development) и не уверен, как правильно реализовать код тестирования.помощь будет оценена.(Предполагается работать с JUnit и Asserts).

Пример запуска моего кода:


import oop.ex3.spaceship.*;

import java.lang.reflect.Array;
import java.util.*;

public class Locker {

    private static final int TOO_MANY_ITEMS = -1;
    private static final int WORKED_WELL = 0;
    private static final int MOVED_TO_LONG_TERM = 1;

    private final int capacity;
    private int currentLoad;
    private HashSet<Item> itemsStored;

    public Locker(int capacity){
        this.capacity = capacity;
        this.currentLoad = 0;
        itemsStored = new HashSet<>();
    }

    public int addItem(Item item, int n){
        if (currentLoad + n*item.getVolume() < capacity){


        }
        else{
            return this.TOO_MANY_ITEMS;
        }
        return 0;
    }

1 Ответ

0 голосов
/ 09 апреля 2019

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...