【问题标题】:What is the java preferred way of serving byte data without copying itjava在不复制字节数据的情况下提供服务的首选方式是什么
【发布时间】:2014-01-21 13:38:49
【问题描述】:

就我而言,我有一个类在单个数组中保存大量字节数据。你可以说;

byte myData[];//myData.length = very large number

我要做的是通过这个类为其他类/用户提供数据。但是,每个请求都部分包含在 myData 数组中。对于请求,它具有起始索引和结束索引。当用户想要这个请求时,我需要返回以下内容:

System.arrayCopy(myArray,startIndex , requestBuffer , endIndex , requestBuffer.length);
return requestBuffer;

我想问的是;有没有在不复制数据的情况下这样做,因为当请求太多时,它可能会给我带来麻烦,比如内存不足。

【问题讨论】:

  • 在你的数组周围做一个包装器,让客户端只能看到它的一部分。如果您最终完成课程,您将享受到解决方案几乎原生的速度。

标签: java arrays object stream byte


【解决方案1】:

您可以做的是创建一个不可变对象,该对象将保存对字节数组的引用和两个整数 - 开始和结束索引。

然后您将传递所述对象而不是您的数组。

【讨论】:

    【解决方案2】:

    要在Kuba Spatny's answer 上进行扩展,您可以创建一个封装对象,该对象为主数组中的数据提供服务,而无需提供任何更改基础数据的机会。

    一个例子如下:

    public class EncapsulatedData {
        private final byte[] data; //<-- only holds a reference to the byte array, no data is copied
        private final int start;
        private final int range;
        
        public EncapsulatedData(byte[] data, int start, int end){
            this.data=data;
            this.start=start;
            this.range=end-start;
            
            if (end>=data.length || start<0){
                throw new IndexOutOfBoundsException();
            }
        }
        
        public byte get(int index){
            if (index>range){
                throw new IndexOutOfBoundsException();
            }
            return data[index+start];
        }
        
        public static void main(String[] args){
            byte[] bigData=new byte[]{0,1,2,3,4,5,6,7,8,9,10};
            
            EncapsulatedData dataProvider=new EncapsulatedData(bigData,4,9);
            
            System.out.println(dataProvider.get(0)); //prints 4
            System.out.println(dataProvider.get(2)); //prints 6
            System.out.println(dataProvider.get(4)); //prints 8
            System.out.println(dataProvider.get(5)); //prints 9
        }
        
        
    }
    

    在我的例子中, start 和 end 包含在内,所有值都像往常一样从零开始索引。如果您希望接收封装数据的类可以修改您公开的数据范围,您可以添加set(int index, byte value) 方法

    使封装范围本身可封装

    如果您发现您想进一步将公开范围分解为子范围,您可以通过使封装范围本身可封装来实现。这只需添加一个新的构造函数即可。

    EncapsulatedData(EncapsulatedData encapsulateData, int start, int end){
        this.data=encapsulateData.data;
        this.start=encapsulateData.start+start;
        this.range=end-start;
        
        if (end>encapsulateData.range || start<0){
            throw new IndexOutOfBoundsException();
        }
    }
    ....
    ....
    ....
    public static void main(String[] args){
        byte[] bigData=new byte[]{0,1,2,3,4,5,6,7,8,9,10};
        
        EncapsulatedData dataProvider=new EncapsulatedData(bigData,4,9);
        
        EncapsulatedData dataProvider2=new EncapsulatedData(dataProvider,1,3);
        
        System.out.println(dataProvider2.get(0)); //prints 5
    
    }
    

    这个新封装仍然直接与byte[] 对话,但表现得好像它是一个子封装

    【讨论】:

      【解决方案3】:

      看看ByteBuffer 类。

      【讨论】:

      • 包装现有数组的功能出现在 Java 7 中。
      • @SimonC - 你是对的,它至少在 Java 6 中存在。我将编辑答案。
      猜你喜欢
      • 1970-01-01
      • 2014-03-31
      • 2022-12-30
      • 1970-01-01
      • 1970-01-01
      • 2018-06-15
      • 2016-01-06
      • 2017-12-13
      • 2012-11-04
      相关资源
      最近更新 更多