为了账号安全,请及时绑定邮箱和手机立即绑定

当项目存储在Arr[0]中时,我如何确定项目是否存在于大小为2的数组的哈希集中?

当项目存储在Arr[0]中时,我如何确定项目是否存在于大小为2的数组的哈希集中?

陪伴而非守候 2022-09-28 15:28:29
我正在尝试为大学的家庭作业创建一个储物柜类和一个长期存储类。他们都应该能够存储一个由我们的老师制作的具有体积和类型的 Item 对象。(而每个储物柜的存储单元数量有限,长期存储的固定数量为1000个单元。我正在尝试决定如何以最佳方式实现存储。我想过创建一个Arrae,因为我知道一般来说,1000个项目的顶部并不多,但我想写出我能写出最好和最有效的代码,并且对它们的顺序并不重要。我们刚刚了解了哈希集,所以我考虑过创建一个哈希集,这使我的程序的运行时变得更好。问题是我需要计算每种类型存储的项目数量,并且集不允许重复。因此,我想也许可以创建一个长度为2的数组哈希集,以跟踪一种类型的项目及其在存储中的数量。我真的不确定实现这种存储的最佳方法是什么,也许我选择了绝对错误的方式。在我看来,当我想从1000中找到一种特定类型的项目时,简单的数组不是很有效。(如果长期存储中存储了1000个不同类型和体积为1的不同项目)。一个额外的问题:在这个练习中,我应该使用TDD方法(测试驱动开发),我不确定如何正确实现测试代码。帮助将不胜感激。(应该与 J 单元和断言一起使用)。我的代码开头的示例: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 回答

?
慕妹3146593

TA贡献1820条经验 获得超9个赞

博士

请考虑使用哈希映射而不是哈希集。具体来说,考虑


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


HashMap<KeyType, ItemWrapper>


其中,KeyType 是项类中的字符串、整数或某种其他类型的唯一标识符,而 ItemWrapper 是用于存储相关数据的简单类。


哈希映射可能比哈希集更适合于此

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


我们将从一个过于简单的实现开始,然后让它变得更好。我还将展示如何像您要求的那样使用大小为 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;

        }

(请注意,此代码依赖于自动装箱和取消装箱,但如果您愿意,可以在没有它的情况下编写。此外,您还可以调整哈希图的初始容量。初始容量为 1400,负载系数为 .75,一旦 HashMap 中出现大约 1050 个项目,它将调整大小。


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


更强大的方法

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


我建议不要使用 Object [],而是将 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,或者如何实际编写用于测试的代码?无论哪种方式,您都可以通过搜索堆栈溢出的现有内容找到很好的答案。


查看完整回答
反对 回复 2022-09-28
  • 1 回答
  • 0 关注
  • 117 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号