如何将IntBuffer复制到int[]?实现兼容堆内/堆外缓冲区的toArray方法
实现兼容堆内/堆外IntBuffer的toArray方法
碰到这种不确定缓冲区类型的情况,核心思路就是先判断缓冲区是否能直接访问底层堆数组,能就高效复制,不能就老老实实批量读取——毕竟堆外缓冲区直接调用array()会抛异常,可不能硬来。
给你一个实用的实现,兼顾效率和安全性:
public int[] toArray(IntBuffer b) { // 先把原缓冲区的位置存起来,别给调用方改了缓冲区状态 int originalPos = b.position(); int remaining = b.remaining(); int[] result = new int[remaining]; if (b.hasArray()) { // 堆内缓冲区:直接用System.arraycopy拷贝底层数组的对应片段,速度快 System.arraycopy( b.array(), b.arrayOffset() + originalPos, result, 0, remaining ); } else { // 堆外缓冲区:用批量get方法读取,读完把位置还原回去 b.get(result); b.position(originalPos); } return result; }
几个关键细节解释:
hasArray()是判断核心:这个方法是NIO缓冲区自带的,堆内缓冲区返回true,堆外直接缓冲区返回false,完美帮我们区分两种场景,比猜类型靠谱多了。- 保护原缓冲区状态:不管哪种情况,都不会修改原缓冲区的position(堆外场景读完手动还原了),调用方完全感知不到我们操作过缓冲区,不会引发意外问题。
- 效率优先:堆内场景用
System.arraycopy(native方法)比循环逐个get快得多;堆外场景用批量get也比循环高效,毕竟是一次性操作。
另外补充个小知识点:如果是只读的IntBuffer,这个实现也能正常工作——因为get操作对于只读缓冲区是允许的,只有写操作才会报错。
内容的提问来源于stack exchange,提问作者Przemek Piotrowski
相关产品推荐
相关产品推荐

