安卓SparseArray的indexOfValue方法遇到的坑

在数据量比较少的情况下使用SparseArray可以提高效率,最近一个项目利用它存储int型数据,利用indexOfValue去获取value的索引,本以为value大小范围可以是int的范围大小,结果不是,数据可以存储但是利用indexOfValue方法得到的索引就是不对返回-1检索不到,特别坑,当value范围是-128到127,indexOfValue才能得到正确的索引,查阅官方文档也没有找到原因,如果有大佬发现原因麻烦指出了,一起交流。解决这个问题可以用SparseIntArray代替,value的值是int的范围通过indexOfValue方法也能获得正确的索引。实验代码如下: 

	SparseArray<Integer> abc = new SparseArray<Integer>();
	int gpuIndex = 0;
	abc.put(gpuIndex++, 127);
	abc.put(gpuIndex++, 128);
	abc.put(gpuIndex++, -128);
        int a, a1, a2;
        a = a1 = a2 = Integer.MIN_VALUE;
        a = abc.indexOfValue(127);
        a1 = abc.indexOfValue(128);
        a2 = abc.indexOfValue(-128);
        Log.i("SparseArray", "SparseArrayIndex127: " + a);
        Log.i("SparseArray", "SparseArrayIndex128: " + a1);
        Log.i("SparseArray", "SparseArrayIndex-128: " + a2);
        
        SparseIntArray def = new SparseIntArray();
        int index = 0;
        def.put(index++, 2147483647);
        int b = def.indexOfValue(2147483647);
        Log.i("SparseIntArray", "SparseIntArrayIndex: " + b);
输出的log日志为:

07-20 16:53:45.611: I/SparseArray(13173): SparseArrayIndex127: 0
07-20 16:53:45.611: I/SparseArray(13173): SparseArrayIndex128: -1
07-20 16:53:45.611: I/SparseArray(13173): SparseArrayIndex-128: 2
07-20 16:53:45.611: I/SparseIntArray(13173): SparseIntArrayIndex: 0

如果大佬知道原因还希望指出来一起讨论!

------------------------------------------------------------------2017.8.9更新----------------------------------------------------------------------------------------------

查看java的int的自动装箱机制发现了问题的原因,是由于自动装箱机制和“==”比较引起的

首先看一下SparseArray的indexOfValue方法源码

 /**
     * Returns an index for which {@link #valueAt} would return the
     * specified key, or a negative number if no keys map to the
     * specified value.
     * <p>Beware that this is a linear search, unlike lookups by key,
     * and that multiple keys can map to the same value and this will
     * find only one of them.
     * <p>Note also that unlike most collections' {@code indexOf} methods,
     * this method compares values using {@code ==} rather than {@code equals}.
     */
    public int indexOfValue(E value) {
        if (mGarbage) {
            gc();
        }

        for (int i = 0; i < mSize; i++)
            if (mValues[i] == value)
                return i;

        return -1;
    }
注释已经提示了是利用“==”来进行比较,比较的是对象引用的地址,而传进来的类型E是是Integer的对象,我们知道在-128至127的数自动装箱时,获得的是同一个对象,而不在这个范围的自动装箱获得的是不同的对象,例子如下:

Integer num1 = 666; Integer num2 = 666; Integer num3 = 88; Integer num4 = 88;

System.out.println("num1==num2: "+(num1==num2));

System.out.println("num3==num4: "+(num3==num4)); 

输出结果:num1==num2: false num3==num4: true 

所以indexOfValue(128)时,128自动装箱成Integer对象,利用“==”与原来put进去的128是不同的对象,所以检索不到,返回-1;

再看SparseIntArray的indexOfValue源码:

    /**
     * Returns an index for which {@link #valueAt} would return the
     * specified key, or a negative number if no keys map to the
     * specified value.
     * Beware that this is a linear search, unlike lookups by key,
     * and that multiple keys can map to the same value and this will
     * find only one of them.
     */
    public int indexOfValue(int value) {
        for (int i = 0; i < mSize; i++)
            if (mValues[i] == value)
                return i;

        return -1;
    }
用的也是“==”,但是比较的类型是基本数据类型int,而不是Integer对象,所以能够检索到之前的数据。问题根源解决!

------------------------------------------------------------------------------------------------------------------------------------------------

后记:细节决定成败啊


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值