2013-04-03 122 views
0

我正在阅读一些使用Guava表的代码,偶尔会抛出ConcurrentModificationException--我明白这是因为我遍历Table的列并在同一个循环中修改表。有没有一种干净/高效的方法来解决这个问题?我可以做一张桌子吗?在放弃之前删除并期望它能够正常工作?番石榴表ConcurrentModificationException

final Set<Optional<SimpleWorkDataValue>> columnKeys = table.columnKeySet(); 
for (final SimpleWorkDataValue timeSeriesValue : timeSeriesValues) { 
    final Optional<SimpleWorkDataValue> rowKey = Optional.of(timeSeriesValue); 
    for (final Optional<SimpleWorkDataValue> columnKey : columnKeys) { 
     if (!table.contains(rowKey, columnKey)) { 
      table.put(rowKey, columnKey, ResultSet.EMPTY); 
     } 
    } 
} 
+0

显而易见的解决方案是使用一个临时表,然后'table.putAll(温度);' - 不知道你是否能找到比这更有效的东西。 – assylias 2013-04-03 23:39:46

+0

你可以发布这个答案,所以我可以upvote。我会尝试一下。另外它会有帮助,看看它在一个片段 – 2013-04-03 23:42:13

回答

4

根据行,列和单元涉及您的嵌套循环的典型执行计数,你可能对节省内存通过分解出这被隐含在这行代码在这里实例化的Iterator:

for (final Optional<SimpleWorkDataValue> columnKey : columnKeys) { 

因为这可迭代不会在整个过程发生变化,你可以列键复制到一个列表我n个开始,然后遍历,在代替内环:

final List<Optional<SimpleWorkDataValue>> columnKeyList = 
     ImmutableList.copyOf(table.columnKeySet()); 
    for (final SimpleWorkDataValue timeSeriesValue : timeSeriesValues) { 
     final Optional<SimpleWorkDataValue> rowKey = Optional.of(timeSeriesValue); 
     for (final Optional<SimpleWorkDataValue> columnKey : columnKeyList) { 
      if (!table.contains(rowKey, columnKey)) { 
       table.put(rowKey, columnKey, ResultSet.EMPTY); 
      } 
     } 
    } 

,当然,这应该消除所有ConcurrentModificationExceptions

+0

这是一个好主意。 – assylias 2013-04-04 00:02:38

+0

很棒的回答。你能详细说明为什么这会消除并发修改异常吗?我是不是在迭代它的同时更新表格? – 2013-04-04 00:02:44

+0

@AmirAfghani'columnKeyList'是columnKeySet的一个副本,所以在技术上你不再在columnKeySet上迭代。 – assylias 2013-04-04 00:03:24

1

要精心围绕我的评论:

//a temporary table 
Table<Optional<SimpleWorkDataValue>, Optional<SimpleWorkDataValue>, Object> temp = 
    HashBasedTable.create(); 

for (final SimpleWorkDataValue timeSeriesValue : timeSeriesValues) { 
    final Optional<SimpleWorkDataValue> rowKey = Optional.of(timeSeriesValue); 
    for (final Optional<SimpleWorkDataValue> columnKey : columnKeys) { 
     if (!table.contains(rowKey, columnKey)) { 
//here add to temp instead of table 
      temp.put(rowKey, columnKey, ResultSet.EMPTY); 
     } 
    } 
} 

//after loop, put everyting back into table 
table.putAll(temp);