将项目存储在Arr [0]中时,如何查找大小为2的数组哈希集中是否存在某个项目?

时间:2019-04-08 22:03:18

标签: java arrays oop testing hashset

我正在尝试为uni的家庭作业创建一个Locker类和一个Long Term Storage类。 他们两个都应该能够存储由我们的老师制作的具有体积和类型的Item对象。 (虽然每个储物柜的存储单元数量有限,而长期存储的设置数量为1000个单元。) 我正在尝试决定如何以最佳方式实现存储。 我考虑过只创建一个数组,因为我通常说1000个项目的顶部并不多,但是我想编写最好的,效率最高的代码,并且对其顺序并不重要。 我们只是了解了HashSets,所以我考虑过创建一个HashSet,这会使我的程序的运行变得更好。 问题是我需要保持每种存储的项目数量的计数,并且集合不允许重复。 因此,我想到了可能要创建一个长度为2的数组HashSet,以跟踪项目的类型及其在存储中的数量。

我不太确定实现这种存储的最佳方法是什么,也许我走的是绝对错误的方法。在我看来,当我要从1000种中查找特定种类的项目时,简单数组不是很有效。(如果长期存储中存储了1000种不同类型和数量为1的不同项目)

一个额外的问题:在本练习中,我应该使用TDD方法(测试驱动开发),并且不确定如何正确实现测试代码。帮助将不胜感激。 (应该与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 :(得分:0)

tl; dr

考虑使用HashMap代替HashSet。具体来说,考虑

HashMap<KeyType, Object[]>,或者甚至更好

HashMap<KeyType, ItemWrapper>

其中KeyType是Item类中的String,Integer或某种其他类型的唯一标识符,而ItemWrapper是用于存储相关数据的简单类。

HashMap可能比HashSet更合适

您说您不想使用数组,因为您希望使用标识符(而不是添加顺序)快速检索。您还希望将商品“映射”到数量计数。 HashMap允许您将键与值相关联,以便快速查找。

我们将从一个过于简单的实现开始,然后使其变得更好。我还将展示如何按照您的要求使用大小为2的数组,即使这不是最佳方法。

我们将改进的基本实现

在一个过于简单的实现中,您的密钥可能是您的Item,而您的值可能是数量。例如,

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

(请注意,此代码依赖于autoboxing and unboxing,但如果愿意,也可以不编写它。此外,您可以调整哈希图的初始容量。初始容量为1400,负载因子为.75, HashMap中大约有1050个项目时,将调整大小。)

麻烦的是,然后您将需要已经拥有Item对象才能查找该项目,这在大多数情况下可能不切实际。 (或者,至少,您需要从hashCode()得到的结果相同并且对于equals()返回true的东西)。您可以在Item类中为@OverrideshashCode()添加equals()。但是,如果为您提供了Item类,则不允许您更改(或不希望更改),并且hashCodes()equals()不能满足您的快速需求抬头?在这种情况下,您将必须具有不同的键,例如项目ID或唯一的描述符(例如,如果在程序中将所有“铅笔”项目都视为相同的字符串,则字符串将起作用)。

更鲁棒的方法

为了使您的梦想与HashMap一起工作,您需要一种独特的方式来标识Item对象-我们将以此为键。对于下面的示例代码,我假定标识符是字符串。您还需要一种将物料与数量关联的方法。

我建议不要使用Object [],而是将Item包装在一个新的简单类中,该类可以同时跟踪Item及其数量。例如:

class ItemWrapper {
    Item item;
    int quantity;
}

(我简化了示例,但您可以根据需要将成员设为私有,添加getter / setter等)。

这样,您的代码更具可读性,并且需要更少的强制转换。然后,将其与类似以下代码的代码一起使用:

        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的现有内容找到不错的答案。