以Java字节存储颜色;字节;字节vs.字节[3]vs.整数

以Java字节存储颜色;字节;字节vs.字节[3]vs.整数,java,byte,Java,Byte,我需要存储大量RGB颜色对象。对于一些常见用途,这些内存占用了我应用程序总内存的8%-12%。我目前将其定义如下: class MyColor { byte red; byte green; byte blue; } protected int create() { MyColor[] aa = new MyColor[100000]; for (int ind=0; ind<100000; ind++) aa[ind] =

我需要存储大量RGB颜色对象。对于一些常见用途,这些内存占用了我应用程序总内存的8%-12%。我目前将其定义如下:

class MyColor {
byte red;
byte green;
byte blue;
}
    protected int create() {
        MyColor[] aa = new MyColor[100000];
        for (int ind=0; ind<100000; ind++)
            aa[ind] = new MyColor2();
        return 2;
    }
}.averageBytes());
我假设(大多数)JVM实际上对每个条目都使用int。最简单的选择是:

class MyColor {
byte [] color = new byte[3];
private static final int red = 0;
private static final int green = 1;
private static final int blue = 2;
}
这会把整个数组放在一个int中吗?或者它是封面下的int[3]?如果是第一个,这很好。如果是第二种,那么最好的是:

class MyColor {
int color;
private static final int red_shift = 0;
private static final int green_shift = 8;
private static final int blue_shift = 16;
}
还是有更好的方法

更新:我还将有一个getRed(),setRed(int)。。。作为访问者。我只是列出了类的数据组件,以使其更小。而尺寸是这里的关键问题。代码不会花很多时间访问这些值,因此性能不是一个大问题

更新2:我使用(参考下文-谢谢)运行了此程序。我使用如下代码完成了此操作:

class MyColor {
byte red;
byte green;
byte blue;
}
    protected int create() {
        MyColor[] aa = new MyColor[100000];
        for (int ind=0; ind<100000; ind++)
            aa[ind] = new MyColor2();
        return 2;
    }
}.averageBytes());
protectedint create(){
MyColor[]aa=新MyColor[100000];

对于(int ind=0;ind将每种颜色作为RGB int存储在int数组中:

int[] colors;
使用字节数组也可以为每种颜色节省另一个字节(25%),但这不太方便,可能不值得

如果使用任何类型的MyColor对象,在开始存储颜色数据本身之前,至少有8个字节浪费在对象标题上,另外4个字节浪费在对象引用上

我假设(大多数)JVM实际上对每个条目都使用int

不,它们是实字节,虽然它会占用4个字节的空间,而不是3个字节,所以它占用的空间与int字段相同


byte[]color=新字节[3];
是效率最低的。数组是一个单独的对象,在计算实际数组数据之前,数组对象头至少需要8个额外字节,长度字段至少需要4个字节,引用字段至少需要4个字节。

由于四个
字节可以放入
int
,因此可以使用单个
int为您的颜色(如果您想添加,比如说,alpha,以后再添加),仍然有额外的空间容纳
字节)。示例一组方法(未经测试,只是为了让您了解这个想法):


您的第一种方法似乎比其他两种要好。64位JVM上需要16字节,32位JVM上需要12字节。第二种方法最昂贵,第三种方法也是16字节

您还可以将颜色存储在三个
byte[width][height]
矩阵中,如果您存储图像,这将为您节省大量字节。其想法是放弃
MyColor
类,该类每个实例需要额外13个字节,从而节省约80%的内存

class MyColor {
    byte red;
    byte green;
    byte blue;
}
为每种颜色创建一个新对象,也有作为对象的内存开销

这不是很理想,因为有两个对象,一个byte[]和一个MyColor。这将使开销加倍。据我所知,没有优化可以将byte[]转换为int

class MyColor {
    int color;
    private static final int red_shift = 0;
    private static final int green_shift = 8;
    private static final int blue_shift = 16;
}
这仍然具有与基于字节的MyColor相同的对象开销,并且还具有必须不断进行位移位的开销

我想推荐如下:

class MyColor{
  byte getR(int col){...}
  byte getG(int col){...}
  byte getB(int col){...}
  int getCol(byte r, byte g, byte b){...}
}
类型安全性差,但开销最小,可以按照建议存储在阵列中


单个字节不占用int值的空间,如一个简单的测试程序所示:

public class Test{
    public static byte[] bigarr = new byte[100000];

    public static void main(String[] args) {
        try{Thread.sleep(100000);}catch(Exception e){}
    }
}

还有一个分析器:这是使用Java HotSpot(TM)64位服务器VM(24.45-b08,混合模式)。

这一切都取决于您要存储的颜色深度。假设您有一个24位颜色深度,即8位红色、8位绿色和8位蓝色,那么您可以将所有三个值存储在一个整数中。因为Java integer是32位的

因此,请简单定义:

int colorValue = 0; //RGB Composite color value with 24 bit depth.
现在,您希望将所有颜色组件存储在一个整数中。这需要一些位运算技巧。假设您将整数存储为以下格式:

00000000 bbbbgggggggg rrrrrrrrrrrrr(R、G和B各8位)。然后需要以下功能:

int getRed(int colorVal)
{
    return colorVal & 127; //Gives the last 8 bits
}
int getGreen(int colorVal)
{
    return (colorVal >> 8) & 127; //Gives the middle 8 bits
}
int getBlue(int colorVal)
{
    return (colorVal >> 16) & 127; //Gives the first 8 bits
}
int getColorVal(int red, int green, int blue)
{
    return (blue << 16) | (green << 8) | red;
}
intgetred(intcolorval)
{
return colorVal&127;//给出最后8位
}
int getGreen(int colorVal)
{
return(colorVal>>8)&127;//给出中间的8位
}
int getBlue(int colorVal)
{
return(colorVal>>16)&127;//给出前8位
}
int getColorVal(int红色、int绿色、int蓝色)
{

返回(蓝色< P>一个基本问题,没有其他的答案已经考虑到是你想要一个颜色是一个RGB三元组还是识别一个拥有RGB三重的东西。考虑一个表单上的两个文本对象的场景;表单的背景颜色被指定为红色。e与表单相同;另一个指定为红色。尽管两个文本对象的背景显示为相同的红色,但一个对象将具有表单的背景色,而另一个对象将具有属性匹配的独立颜色。如果表单的背景色变为绿色,则其中一个文本对象将继续具有相同的颜色作为形式,而另一个将继续为红色

如果颜色使用可变类类型,则该类型的每个变量将标识一个包含RGB三元组的对象。如果多个变量标识同一个对象,则使用这些变量中的任何一个来更改对象的属性将有效地更改所有变量的该属性。如果只有v标识该对象的变量是应该更改的变量(与上面的文本对象一样),但如果标识该对象的某些变量与该对象无关(例如,如果文本对象标识了与背景相同的颜色对象),则可能会非常糟糕

使用不可变类类型可以使语义更清晰(对不可变对象的引用可能被认为只是封装了其内容),但任何时候都需要更改
int colorValue = 0; //RGB Composite color value with 24 bit depth.
int getRed(int colorVal)
{
    return colorVal & 127; //Gives the last 8 bits
}
int getGreen(int colorVal)
{
    return (colorVal >> 8) & 127; //Gives the middle 8 bits
}
int getBlue(int colorVal)
{
    return (colorVal >> 16) & 127; //Gives the first 8 bits
}
int getColorVal(int red, int green, int blue)
{
    return (blue << 16) | (green << 8) | red;
}
int width = <WIDTH>;
int height = <HEIGHT>;
int colorData[width * height];
Color c = new Color(55, 155, 255);
int ci = c.getRGB();
Color cd = new Color(ci);
int R = cd.getRed(); // 55