我在Swing TreeList中显示的列表中有100k项。请参阅jide-demo https://www.jidesoft.com/products/download.htm
中的AutoFilterTreeTableDemo过滤时,需要很长时间才能扩展节点。
在分析时,Vector.indexOf()需要大约20秒。我把它切换到了ArrayList,花了大约5秒钟。
然后我将List缓存为Map<Row, Integer>
,其中Integer是列表中的索引。这将滤波减少到~0.2s。
但是,如果我在中间某处添加一行,我必须重建地图,因为列表的索引会发生变化。
是否有使用地图来支持列表索引的数据结构?或者我必须自己管理这个?
或者,是否有正常的List具有非常快的indexOf次?我不介意牺牲插入/删除时间轻微而牺牲了这一点。
第三种选择是如果我可以使用更优化的可过滤Swing网格。
编辑:代码段:
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;
}
}
答案 0 :(得分:0)
我认为你可能接近最佳解决方案。你有两个相互矛盾的需求:
通常对于(1)你会使用像地图或链接列表
这样的东西对于(2),您将使用数组
与(2)冲突的原因是当你做(1)时你必须更新每个后续项目,以便更新其索引。我认为你不会找到这样做的通用数据结构,因为它无法有效地完成。
我想如果我是你,除了重组问题,我想现在不可能,我会做你正在做的事。
然而,不应将地图视为整体,而应将其用作缓存。
执行查找时,另一项检查以确保索引匹配,以及它是否未清除映射中的条目;找到正确的价值;然后更新地图,例如
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;
}
很抱歉没有尝试过编译,这只是说明性的
您可能希望将其与另一个定期运行的功能配对,以完全重建缓存。
答案 1 :(得分:0)
不完全符合您的要求,但可以将其视为您问题的替代解决方案:org.apache.commons.collections.list.TreeList indexOf方法并不优于ArrayList实现,但对于您的用例,我认为它是可以接受的。
此列表实现在内部使用树结构,以确保所有插入和删除都是O(log n)。
下表是从他们的文档中获得的,作为与其他List实现相比的性能指标。下行是消耗更多的内存:
* get add insert iterate remove
* TreeList 3 5 1 2 1
* ArrayList 1 1 40 1 40
* LinkedList 5800 1 350 2 325