Java 存储具有多个查询条件的多个实体时要使用哪些数据结构?

Java 存储具有多个查询条件的多个实体时要使用哪些数据结构?,java,algorithm,data-structures,Java,Algorithm,Data Structures,有一个存储单元,可存储N个项目。最初,这个单元是空的。 该空间以线性方式排列,即一个挨着另一个排列成一条直线。 每个存储空间都有一个数字,一直增加到N 当有人放下他们的包裹时,会为其分配第一个可用空间。包裹也可以取走,在这种情况下,空间变空了。 示例:如果总容量为4。1和2已满,第三个进来的人将被分配空间3。如果1号、2号和3号空间已满,而第二个空间空置,则下一个来的人将被分配空间2 它们丢弃的包有两个唯一的属性,用于立即识别。首先根据内容对其进行颜色编码,然后为其分配唯一标识号(UIN) 我们

有一个存储单元,可存储N个项目。最初,这个单元是空的。 该空间以线性方式排列,即一个挨着另一个排列成一条直线。 每个存储空间都有一个数字,一直增加到N

当有人放下他们的包裹时,会为其分配第一个可用空间。包裹也可以取走,在这种情况下,空间变空了。 示例:如果总容量为4。1和2已满,第三个进来的人将被分配空间3。如果1号、2号和3号空间已满,而第二个空间空置,则下一个来的人将被分配空间2

它们丢弃的包有两个唯一的属性,用于立即识别。首先根据内容对其进行颜色编码,然后为其分配唯一标识号(UIN)

我们需要的是查询系统:

  • 当输入为颜色时,显示与此颜色关联的所有UIN
  • 当输入为“颜色”时,显示放置这些包的所有编号(存储空间编号)
  • 显示具有给定UIN的项目的放置位置,即存储空间号
  • 我想知道如何在这种情况下使用哪些数据结构,以便系统尽可能高效地工作? 我不知道这些操作系统中哪一个最频繁,这意味着我必须针对所有情况进行优化


    请注意,即使查询过程不是直接请求存储空间号,但当从存储中删除项目时,它是通过查询存储空间号来删除的。

    query 3:使用哈希映射,键是UIN,值是object(存储空间号、颜色)(以及包的任何其他信息). 查询、插入或删除的成本为O(1)。空格是O(k),其中k是当前UIN的数量

    查询1和查询2:使用哈希映射+多链接列表

    哈希映射,键是颜色,值是指向该颜色对应UIN的链接列表的指针(或Java中的引用)

    每个链接列表都包含UIN

    对于查询1:询问哈希映射,然后返回相应的链接列表。成本是O(k1),其中k1是查询颜色的UIN数。空间是O(m+k1),其中m是唯一颜色的数目

    对于查询2:执行查询1,然后应用查询3。成本是O(k1),其中k1是查询颜色的UIN数。空间是O(m+k1),其中m是唯一颜色的数目

    插入:给定颜色、数字和UIN,在查询3的哈希映射中插入一个对象(num、color);哈希(颜色)转到相应的链接列表并插入UIN

    删除:给定UIN,向查询3询问颜色,然后让查询1删除链接列表中的UIN。然后在查询3的哈希映射中删除UIN


    好处:要管理存储空间,情况与操作系统中的内存管理相同:

    这有点像家庭作业或糟糕的管理

    不管是哪种方式,我已经决定做一个版本,其中您最关心的是查询速度,但不关心内存或插入和删除的一点额外开销。这并不是说我会疯狂地烧掉内存,或者花很长时间插入和删除,只是我最关注的是查询

    Tl;DR-为了解决您的问题,我使用PriorityQueue、数组、HashMap和ArrayListMultimap(来自guava,一个公共外部库),每一个都可以解决不同的问题

    下面的部分是工作代码,它将遍历一些简单的插入、查询和删除。下一部分实际上不是Java,因为我删掉了大部分导入、类声明等。此外,它引用了另一个名为“Packg”的类。这只是一个简单的数据结构,您应该能够从对它的调用中找出它

    代码下面有解释

    import com.google.common.collect.ArrayListMultimap;
    私有优先队列开放插槽;
    私人包裹;
    地图当前包地图;
    私有ArrayListMultimap currentColorMap;
    私有对象$outsideCall;
    公共CrazyDataStructure(可能的包数){
    $outsideCall=新对象();
    this.currentPackages=新包装千克[可能的包装数量];
    openSlots=new PriorityQueue();
    IntStream.range(0,可能的包数)。forEach(i->openSlots.add(i));//填充openSlots优先级队列
    currentPackageMap=新的HashMap();
    currentColorMap=ArrayListMultimap.create();
    }
    /*
    *args[0]=整数,包的最大值
    */
    公共静态void main(字符串[]args)
    {
    int howManyPackagesPossible=Integer.parseInt(args[0]);
    CrazyDataStructure cds=新的CrazyDataStructure(可能有多少个包);
    CD.addPackage(新包装(12345,“蓝色”);
    CD.addPackage(新包装(12346,“黄色”);
    CD.addPackage(新包装(12347,“橙色”);
    CD.addPackage(新包装(12348,“蓝色”);
    System.out.println(cds.getSlotsForColor(“blue”);//应该是{0,3}的列表
    System.out.println(cds.getSlotForUIN(12346));//应该是1(记住,索引为0)
    System.out.println(cds.getSlotsForColor(“橙色”);//应该是{2}的列表
    System.out.println(cds.removePackage(2));//应该是橙色的
    CD.addPackage(新包装(12349,“绿色”);
    System.out.println(cds.getSlotForUIN(12349));//应该是2,因为它是打开的
    }
    公共内部添加包(Packg Packg)
    {
    同步($outsideCall)
    {
    int result=openSlots.poll();
    包装千克整批(结果);
    currentPackages[结果]=包装千克;
    currentPackageMap.put(packg.getUIN(),packg);
    currentColorMap.put(packg.getColor(),packg);
    返回结果;
    }
    }
    公共包移除包(内部插槽)
    {
    同步($outsideCall)
    {
    如果(currentPackages[slot]==null)
    返回null;
    其他的
    {
    Packg Packg=当前包[插槽];
    当前颜色
    
    import com.google.common.collect.ArrayListMultimap;
    
    private PriorityQueue<Integer> openSlots;
    private Packg[] currentPackages;
    Map<Long, Packg> currentPackageMap;
    private ArrayListMultimap<String, Packg> currentColorMap;
    private Object $outsideCall;
    
    
    public CrazyDataStructure(int howManyPackagesPossible) {
        $outsideCall = new Object();
        this.currentPackages = new Packg[howManyPackagesPossible];
        openSlots = new PriorityQueue<>();
        IntStream.range(0, howManyPackagesPossible).forEach(i -> openSlots.add(i));//populate the open slots priority queue
        currentPackageMap = new HashMap<>();
        currentColorMap = ArrayListMultimap.create();
    }
    
    /*
     * args[0] = integer, maximum # of packages
     */
    public static void main(String[] args)
    {
        int howManyPackagesPossible = Integer.parseInt(args[0]);
        CrazyDataStructure cds = new CrazyDataStructure(howManyPackagesPossible);
        cds.addPackage(new Packg(12345, "blue"));
        cds.addPackage(new Packg(12346, "yellow"));
        cds.addPackage(new Packg(12347, "orange"));
        cds.addPackage(new Packg(12348, "blue"));
        System.out.println(cds.getSlotsForColor("blue"));//should be a list of {0,3}
        System.out.println(cds.getSlotForUIN(12346));//should be 1 (0-indexed, remember)
        System.out.println(cds.getSlotsForColor("orange"));//should be a list of {2}
        System.out.println(cds.removePackage(2));//should be the orange one
        cds.addPackage(new Packg(12349, "green"));
        System.out.println(cds.getSlotForUIN(12349));//should be 2, since that's open
    }
    
    public int addPackage(Packg packg)
    {
        synchronized($outsideCall)
        {
            int result = openSlots.poll();
            packg.setSlot(result);
            currentPackages[result] = packg;
            currentPackageMap.put(packg.getUIN(), packg);
            currentColorMap.put(packg.getColor(), packg);
            return result;
        }
    }
    
    public Packg removePackage(int slot)
    {
        synchronized($outsideCall)
        {
            if(currentPackages[slot] == null)
                return null;
            else
            {
                Packg packg = currentPackages[slot];
                currentColorMap.remove(packg.getColor(), packg);
                currentPackageMap.remove(packg.getUIN());
                currentPackages[slot] = null;
                openSlots.add(slot);//return slot to priority queue
                return packg;
            }
        }
    }
    
    public List<Packg> getUINsForColor(String color)
    {
        synchronized($outsideCall)
        {
            return currentColorMap.get(color);
        }
    }
    
    public List<Integer> getSlotsForColor(String color)
    {
        synchronized($outsideCall)
        {
            return currentColorMap.get(color).stream().map(packg -> packg.getSlot()).collect(Collectors.toList());
        }
    }
    
    public int getSlotForUIN(long uin)
    {
        synchronized($outsideCall)
        {
            if(currentPackageMap.containsKey(uin))
                return currentPackageMap.get(uin).getSlot();
            else
                return -1;
        }
    }
    
    public class SegmentTree
    {
        private int Mid;
        private int[] t;
    
        public SegmentTree(int capacity)
        {
            this.Mid = 1;
            while (Mid <= capacity) Mid *= 2;
            this.t = new int[Mid + Mid];
    
    
            for (int i = Mid; i < this.t.Length; i++) this.t[i] = int.MaxValue;
            for (int i = 1; i <= capacity; i++) this.t[Mid + i] = i;
            for (int i = Mid - 1; i > 0; i--) t[i] = Math.Min(t[i + i], t[i + i + 1]);
        }
    
        public int Capture()
        {
            int answer = this.t[1];
            if (answer == int.MaxValue)
            {
                throw new Exception("Empty space not found.");
            }
    
            this.Update(answer, int.MaxValue);
    
            return answer;
        }
    
        public void Erase(int index)
        {
            this.Update(index, index);
        }
    
        private void Update(int i, int value)
        {
            t[i + Mid] = value;
            for (i = (i + Mid) >> 1; i >= 1; i = (i >> 1))
                t[i] = Math.Min(t[i + i], t[i + i + 1]);
        }
    }
    
        int n = 4;
        var st = new SegmentTree(n);
    
        Console.WriteLine(st.Capture());
        Console.WriteLine(st.Capture());
        Console.WriteLine(st.Capture());
        st.Erase(2);
        Console.WriteLine(st.Capture());
        Console.WriteLine(st.Capture());