如何在Java中一次更改多个引用?

时间:2011-08-28 17:41:33

标签: java performance reference complexity-theory

我有一个包含对象引用的数组。我想将数组中的一些引用更改为另一个对象。目前我使用的循环如下所示:

for (int i = region2.getStartPos(); i <= curPos; i++) {        
    if (regions[i] == region2) {
        regions[i] = region1;
    }
}

我想避免使用for循环,因为它会增加计算复杂性。

有没有办法让region2引用的对象直接等于region1? 例如,我尝试在Region类中编写一个方法,如下所示,但它给了我一个“无法为最终变量赋值”错误。

public void mergeRegions(Region region){
    this = region;
}

这样的事情可能吗?

3 个答案:

答案 0 :(得分:1)

Java中的每个引用都只是内存中某个对象的地址,因此如果没有一些额外的代码,就无法实现所要求的“自动更新”。

想象一下,region1引用内存中的地址0x1001region2引用0x2001。这两个存储器位置保存实际区域数据:

  • 0x1001 x = 0, y = 5, width = 20, height = 30
  • 0x2001 x = 100, y = 200, width = 50, height = 20

如果你能以某种方式告诉0x2001上的对象等于0x1001,那么使用你的mergeRegions方法,Java会尝试这样做吗?

  • 0x1001 x = 0, y = 5, width = 20, height = 30
  • 0x2001 0x1001

但这不起作用,因为Java对象都应该是Region个对象,每个对象都有相同的字段和方法。如果我们在0x2001消灭了Java对象,并且只是放入一个普通的地址,那么0x2001的任何现有引用都不起作用,因为它们都期望Region个对象在那个地址。这就是为什么你不能“直接将”一个Java引用分配给另一个。

以下三个提示可帮助您重新设计算法:

  1. 您可以将0x1001中的所有数据复制到0x2001的对象中,而不是将地址0x1001复制到0x2001。这将使两个对象等效,但是分开。
  2. 您可以引入一个级别的间接。如果您了解C,请考虑“指针指针”。您的regions数组将包含对IndirectRegion个对象的引用,这些对象将依次保存对实际Region对象的引用。如果您要将region2更新为region1,则只需要求其中一个IndirectRegion个对象更新其内部参考。
  3. 在合并区域之前,请等待算法结束。如果您能够收集所有合并操作,则可以在单个O(n)循环中执行所有这些操作。

答案 1 :(得分:0)

你不能这样做,因为它会违反该对象对其他呼叫者的行为方式。你的第一个for循环是你能做的最好的。更好的解决方案可能是不使用数组而是使用具有O(1)访问权限的东西。例如,Set<T>。你可以像

set.remove(region2);
set.add(region1);

如果你写了.equals().hashcode()

,这将非常快

另一个解决方案是将所有内容从一个类复制到另一个类。我不确定我对此的感受以及它是否安全。但是你可以做类似的事情。

public void mergeRegions(Region region){
    this.a=region.a;
    this.b=region.b;
    this.c=region.c;
    this.d=region.d;
}

答案 2 :(得分:0)

你在使用数组是为了什么?我也想到了Amir和Dan关于交换内容或使用间接的建议。但我觉得你应该改变你的数据结构。那么请您详细说明阵列的用法吗?

例如,如果您只有几个区域n,那么可能不使用区域对象数组,您可以使用n组整数并使用联合,交集和补充或交换集等集合操作。或者你甚至不再需要整数,但可以使用EnumSets或EnumMaps。

如果您碰巧有Josh Bloch的书“Effective Java”,请查看关于数组的第25项和关于EnumSets / EnumMaps的第32/33项。