简体   繁体   English

是否有地图支持的列表?

[英]Is there a list backed by a Map?

I have 100k items in a list that is displayed in a Swing TreeList. 我在Swing TreeList中显示的列表中有100k项。 See AutoFilterTreeTableDemo in the jide-demo https://www.jidesoft.com/products/download.htm 请参阅jide-demo https://www.jidesoft.com/products/download.htm中的 AutoFilterTreeTableDemo

When filtering it takes a long time to expand the nodes. 过滤时,需要很长时间来扩展节点。

On profiling, Vector.indexOf() was taking ~20 seconds. 分析时,Vector.indexOf()大约需要20秒。 I switched it to an ArrayList and it took ~5 seconds. 我将其切换到ArrayList,大约花了5秒钟。

I then cached the List as Map<Row, Integer> where the Integer is the index in the list. 然后,我将列表缓存为Map<Row, Integer> ,其中Integer是列表中的索引。 This reduced the filtering to ~0.2s. 这样可以将过滤时间减少到〜0.2s。

However, if I add a row somewhere in the middle I have to rebuild the map as the indexes of the list will have changed. 但是,如果在中间的某处添加一行,则必须重新构建地图,因为列表的索引将发生更改。

Is there a data structure that uses a map to back the index of the list? 是否存在使用映射来支持列表索引的数据结构? Or do I have to manage this by myself? 还是我必须自己解决这个问题?

Alternatively, is there a normal List that has very fast indexOf times? 另外,是否有一个具有非常快速indexOf时间的普通List? I don't mind sacrificing the insertion/deletion times slightly at the expense of this. 我不介意在这个费用略有牺牲插入/缺失倍。

A third option is if there is a more optimal filterable Swing grid that I could use. 第三种选择是,如果我可以使用更优化的可过滤Swing网格。

EDIT: Code snippet: 编辑:代码段:

    private Map<Row, Integer> rowLookup = new ConcurrentHashMap<Row, Integer>();

    @Override
    public int getRowIndex(Row row) {
        if(rowLookup.isEmpty()) {
            List<Row> existingRows = getRows();
            for(int i = 0; i < existingRows.size(); i++) {
                Row mappingRow = existingRows.get(i);
                rowLookup.put(mappingRow, i);
            }
        }
        if(row == null) {
            return -1;
        } else {
            Integer lineNumber = rowLookup.get(row);
            if(lineNumber == null) {
                lineNumber = -1;
            }
            return lineNumber;
        }
    }

I think you're probably close to the optimal solution as it is. 我认为您可能正接近最佳解决方案。 You have two contradictory needs: 您有两个矛盾的需求:

  1. You want to be able to randomly insert items 您希望能够随机插入项目
  2. You want to be able to access these items based on a fixed index 您希望能够基于固定索引访问这些项目

Typically for (1) you would use something like either a Map or Linked List 通常对于(1),您将使用诸如Map或Linked List之类的东西

For (2) you would use an Array 对于(2),您将使用数组

The reason (1) conflicts with (2) is that when you do (1) you have to update every subsequent item such that its index is updated. 原因(1)与(2)冲突是,当您执行(1)时,必须更新每个后续项,以便其索引被更新。 I don't think you'll find a general purpose data structure that does this because it can't be done efficiently. 我认为您不会找到通用的数据结构来执行此操作,因为它无法高效完成。

I think if I were you, apart from restructuring the problem, which I guess isn't possible right now, I would do what you are doing. 我想,如果我是您,除了解决问题(我认为现在不可能)之外,我会做您正在做的事情。

However rather than considering the map as being integral, you should use it as a cache. 但是,您不应将地图视为完整的地图,而应将其用作缓存。

When you do the lookup, and another check to ensure that the index matches, and if it doesn't clear the entry from the map; 当您执行查找时,再次检查以确保索引匹配,以及是否未从地图中清除条目; find the correct value; 找到正确的值; then update the Map eg 然后更新地图,例如

public int getRowIndex(Row row) {

    Integer index = rowLookup.get(mappingRow);

    List<Row> existingRows = getRows();

    if (index != null) {

        int i = index.intValue();

        if (i < existingRows.size() && row == existingRows.get(i)) {
            return i;
        }

        rowLookup.remove(i);
    }

    /* Otherwise we'll have to look it up the slow way */
    int i = existingRows.indexOf(row);
    rowLookup.put(row, i);
    return i;
}

Sorry haven't tried compiling this it's meant to be illustrative only 对不起,您还没有尝试编译,仅供参考。

You may want to pair this with another function running periodically that rebuilds the cache in its entirety. 您可能希望将其与另一个定期运行的功能配对,以重新构建整个缓存。

Not exactly what you are looking for but it could be considered as an alternative solution to your problem: org.apache.commons.collections.list.TreeList The indexOf method does not outperforms the ArrayList implementation but for your use case I think it'll be acceptable. 并非完全符合您的期望,但可以考虑将其作为您问题的替代解决方案: org.apache.commons.collections.list.TreeList indexOf方法的性能并不优于ArrayList实现,但是对于您的用例,我认为它将可以接受。

This list implementation utilises a tree structure internally to ensure that all insertions and removals are O(log n). 此列表实现在内部利用树结构来确保所有插入和删除均为O(log n)。

The below table was obtained from their documentation as a measure of their performance in comparison to other List implementations. 下表是从其文档中获取的,以作为与其他List实现相比其性能的度量。 Downside is it consumes slightly more memory: 缺点是会消耗更多的内存:

 *              get  add  insert  iterate  remove
 * TreeList       3    5       1       2       1
 * ArrayList      1    1      40       1      40
 * LinkedList  5800    1     350       2     325

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM