Java 从对象本身确定对象在数组中的索引

Java 从对象本身确定对象在数组中的索引,java,arrays,Java,Arrays,阵列中的对象是否有方法检测它们所在的插槽?如果我有一个对象数组,数组中的一个对象是否可以在没有被明确告知的情况下检测到它所在的单元格?不,不幸的是,数组在Java中的工作原理是数组只是“指向”一个对象。由于Java数组只存储对对象的引用,但是任意数量的变量都可以引用同一个对象,因此对象不知道它在数组中的位置。事实上,可以从数组中的多个索引指向同一对象 考虑 Object o = new Object(); // The variable o has a "reference" to the Ob

阵列中的对象是否有方法检测它们所在的插槽?如果我有一个对象数组,数组中的一个对象是否可以在没有被明确告知的情况下检测到它所在的单元格?

不,不幸的是,数组在Java中的工作原理是数组只是“指向”一个对象。由于Java数组只存储对对象的引用,但是任意数量的变量都可以引用同一个对象,因此对象不知道它在数组中的位置。事实上,可以从数组中的多个索引指向同一对象

考虑

Object o = new Object(); // The variable o has a "reference" to the Object in memory
Object[] arr = new Object[3]; // empty array to hold Object types
arr[0] = o; // the first index points to the Object we created above
arr[1] = o; // the second index points to that same object!
arr[2] = o; // still the same object! If we modified the original object (assuming it's not immutable) in any way, all the indices in this array would point to the modified object.
希望这有帮助

迭代对象数组的最快(最容易编写)方法是

for (Object o : arr) {
    // do something to the local variable o, which you can think of as representing each object in your array
}

不。如果你需要这样做,你可能有一个设计缺陷。为什么
对象
需要知道它在数组中的位置?如果索引对对象具有某种语义意义或兴趣,则对象应具有包含此信息的
int
字段。如果您试图基于一个对象修改原始数组,那么您可能在某个地方有一个分解不好的类,例如,如果发生了这样的情况:

class A {
    Object data[];
}

class B {
    remove(A a, Object instance) {
        // how to remove instance from a.data??
    }
}
那么真正的
B.remove
应该是
a
的一种方法,因此首先可以访问
数据。等等

此外,数组可能不是正确的数据结构。如果索引有很多语义值,
Map
可能更合适,尽管当索引从
1..n
连续且数组不可变时,通常使用数组来表示这一点。在我关于
删除
的愚蠢示例中,一个
列表将更合适。等等。

试试看

    int i = Arrays.asList(arr).indexOf(obj);

正如@Aaron_H所说,没有骰子。我要补充的是,您可以通过以下方式解决此问题:

public class Test {

    public static void main(String[] args) {
        ZenArray<IndexedString> z = new ZenArray(10);
        for (int i = 0; i < z.size(); i++) {
            z.set(i, new IndexedString("String " + i));
        }
        for (int i = 0; i < z.size(); i++) {
            System.out.println("I'm at index " + z.get(i).getIndex());
        }
    }
}

class ZenArray<T extends ZenArray.IndexedElement> {

    private Object [] a;

    interface IndexedElement {
        void setIndex(int i);
        int getIndex();
    }

    public ZenArray(int size) {
        a = new Object[size];
    }

    public void set(int i, T val) {
        val.setIndex(i);
        a[i] = val;
    }

    public T get(int i) {
        return (T)a[i];
    }

    public int size() {
        return a.length;
    }
}

// An example of an indexed element implementation.
class IndexedString implements ZenArray.IndexedElement {

    int i;
    String val;

    public IndexedString(String val) {
        this.val = val;
    }

    public String getVal() {
        return val;
    }

    @Override
    public void setIndex(int i) {
        this.i = i;
    }

    @Override
    public int getIndex() {
        return i;
    }    
}
公共类测试{
公共静态void main(字符串[]args){
天顶阵列z=新天顶阵列(10);
对于(int i=0;i
这里没有魔法。您可以通过在for循环中迭代数组并检查.AFAICT不是重复的来实现这一点。令人惊讶的是,向上投票。这是非常昂贵的,如果在
equal
下有重复项,则无法正常工作。这通常是正确的,但也有例外。我处理结构工程问题,其中列表元素是固有的,必须很快知道它们自己的索引。在C或C++中,这很简单。在java中,只有外部列表。正如您所暗示的,您必须存储索引,并在每次修改列表时使其保持最新。这很尴尬,而且容易出错。在这些问题中,我从未发现一个java实现像C/C++允许的那样干净。