虽然标题中有Java,但这可能适用于任何OO语言。 我想知道一些新想法,以改善我正在尝试做的事情的表现。
我有一个不断接收Object []数组的方法。我需要通过多个数组(List或其他)拆分此数组中的Objects,以便我为该方法接收的所有数组的每一列都有一个独立的列表。
示例:
List<List<Object>> column-oriented = new ArrayList<ArrayList<Object>>();
public void newObject(Object[] obj) {
for(int i = 0; i < obj.length; i++) {
column-oriented.get(i).add(obj[i]);
}
}
注意:为简单起见,我省略了对象和东西的初始化。
我上面显示的代码当然很慢。我已经尝试了一些其他的东西,但是想听听一些新的想法。
如果知道它对性能非常敏感,你会怎么做?
修改
我测试了一些东西并发现:
我没有使用ArrayList(或任何其他Collection),而是将Object []数组包装在另一个对象中以存储单个列。如果此数组达到其容量,我创建另一个具有两倍大小的数组,并使用System.copyArray将内容从一个复制到另一个。令人惊讶的是(至少对我而言)使用ArrayList存储内部列的速度更快......
答案 0 :(得分:2)
答案取决于数据和使用情况。你在这些收藏中有多少数据?什么是读/写的比例(添加对象数组)?这会影响内部列表的结构更好以及许多其他可能的优化。
复制数据的最快方法是避免复制。如果您知道调用者代码未对obj
数组进行进一步修改(这是一个重要条件),那么可能的一个技巧就是实现自定义List
类以用作内部列表。在内部,您将存储共享的List<Object[]>
。每次调用我们只是将新数组添加到该列表中。自定义内部列表类将知道它代表哪个列(让它为n
),当它被要求在位置m
处提供项目时,它将转置m
和n
并查询内部结构以获取internalArray.get(m)[n]
。这种实现是不安全的,因为调用者的限制容易被遗忘,但在某些情况下可能会更快(但是,在其他条件下这可能会更慢)。
答案 1 :(得分:0)
使用LinkedList
来实现列列表。它与数据呈线性增长,为O(1)。 (如果使用ArrayList,则必须不时调整内部数组的大小。)
收集值后,您可以将链接列表转换为数组。如果N是从每个列表保持3 * N refs(每个LInkedList具有prevRef / nextRef / itemRef)到仅N refs的行数。
拥有一个用于保存不同列列表的数组会很不错,但当然,这并不是一个很大的改进,只有事先知道列数才能实现。
希望它有所帮助!
编辑测试和理论表明,ArrayList的分摊成本更好,总成本除以处理的项目数量......所以不要按照我的'建议':)
答案 2 :(得分:0)
我会尝试使用LinkedList作为内部列表,因为它应该具有更好的插入性能。也许将Object arra包装到集合中并使用addAll也可能有所帮助。
答案 3 :(得分:0)
由于数组的复制,ArrayList可能很慢(它使用与自编集合类似的方法)。
作为替代解决方案,您可以尝试简单地存储行,并在必要时创建列。这样,列表中内部数组的复制减少到最小。
示例:
//Notice: You can use a LinkedList for rows, as no index based access is used.
List<Object[]> rows =...
List<List<Object>> columns;
public void processColumns() {
columns = new ArrayList<List<Object>>();
for(Object[] aRow : rows){
while (aRow.size() > columns.size()){
//This ensures that the ArrayList is big enough, so no copying is necessary
List<Object> newColumn = new ArrayList<Object>(rows.size())
columns.add(newColumn);
}
for (int i = 0; i < aRow.length; i++){
columns.get(i).add(aRow[i]);
}
}
}
根据列数的不同,外部列表仍然可能在内部复制数组,但普通表包含的行数远多于列数,因此它应该只是一个小数组。