Java 为什么使用布尔数组要花这么长时间?

Java 为什么使用布尔数组要花这么长时间?,java,arrays,bitset,Java,Arrays,Bitset,我正在做课堂作业。我应该为康威的人生游戏创作一个简单的版本。我在使用布尔值数组和使用位集之间做了一些实验。我最终创建了一个小测试: 每次对位集和布尔数组运行测试后,位集的平均值约为6ms,布尔数组的平均值约为1300ms。所以我的问题是,到底是什么导致了使用布尔运算而不是使用位集时的巨大开销?我希望会有所不同,但不是这么激烈 代码如下: java-主类 public class Life { private final int WIDTH = 100; private final

我正在做课堂作业。我应该为康威的人生游戏创作一个简单的版本。我在使用布尔值数组和使用位集之间做了一些实验。我最终创建了一个小测试:

每次对位集和布尔数组运行测试后,位集的平均值约为6ms,布尔数组的平均值约为1300ms。所以我的问题是,到底是什么导致了使用布尔运算而不是使用位集时的巨大开销?我希望会有所不同,但不是这么激烈

代码如下:

java-主类

public class Life
{
    private final int WIDTH = 100;
    private final int HEIGHT = 100;
    private Board board;

    public static void main(String[] args)
    {
        new Life();
    }

    public Life()
    {
        board = createBoard();

        // populate board with random data
        Random random = new Random();
        for (int j = 0; j < board.length(); j++)
        {
            boolean b = random.nextBoolean();
            board.set(j, b);
        }
        random = null;
        System.gc();


        System.out.println("Starting test...");
        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 10_000; i++)
        {
            Board tempBoard = createBoard();
            for (int j = 0; j < board.length(); j++)
            {
                byte count = getNeighborCount(j);
                boolean value = board.get(j);
                boolean next = value ? count >= 2 && count <= 3 : count == 3;
                tempBoard.set(j, next);
            }
            board = tempBoard;
        }

        long endTime = System.currentTimeMillis();
        System.out.format("Took %d ms", endTime - startTime);
    }

    public Board createBoard()
    {
        return new ArrayBoard(WIDTH * HEIGHT);
        //return new BitBoard(WIDTH * HEIGHT);
    }

    public byte getNeighborCount(int index)
    {
        byte count = 0;

        if (getRelative(index, -1, -1)) count++;
        if (getRelative(index, -1, 0)) count++;
        if (getRelative(index, -1, 1)) count++;

        if (getRelative(index, 0, -1)) count++;
        if (getRelative(index, 0, 0)) count++;
        if (getRelative(index, 0, 1)) count++;

        if (getRelative(index, 1, -1)) count++;
        if (getRelative(index, 1, 0)) count++;
        if (getRelative(index, 1, 1)) count++;

        return count;
    }

    public boolean getRelative(int index, int x, int y)
    {
        int relativeIndex = index + (WIDTH * y) + x;
        return board.get(relativeIndex);
    }
}
使用阵列的单板实现

public class ArrayBoard implements Board
{
    private boolean[] board;

    public ArrayBoard(int size)
    {
        board = new boolean[size];
    }

    @Override
    public void set(int index, boolean value)
    {
        board[index] = value;
    }

    @Override
    public boolean get(int index)
    {
        boolean output = false;
        if (index >= 0 && index < board.length)
            output = board[index];
        return output;
    }

    @Override
    public int length()
    {
        return board.length;
    }
}

位集比布尔[]内存效率更高,除了非常小的大小,以便进一步澄清,您可以阅读


位集比布尔[]内存效率更高,除了非常小的大小,以便进一步澄清,您可以阅读


您的问题与
位集
布尔[]
性能无关

比特板中,您将
length()
定义为:

class BitSetBoard {

    ...

    @Override
    public int length()
    {
        return board.length();
    }

}
您的意思是返回
board.size()
而不是
board.length()
。该方法返回最高位集的索引,但不返回总大小。因此,主循环实际上没有做任何事情,因为当电路板清除时,
length()
返回0


通过此更改(并将边界检查添加到
bitsboard.get()
),
bitsboard
的运行时间是
ArrayBoard
的两倍。您的问题与
BitSet
boolean[]
性能无关

比特板中,您将
length()
定义为:

class BitSetBoard {

    ...

    @Override
    public int length()
    {
        return board.length();
    }

}
您的意思是返回
board.size()
而不是
board.length()
。该方法返回最高位集的索引,但不返回总大小。因此,主循环实际上没有做任何事情,因为当电路板清除时,
length()
返回0


通过此更改(并向
BitsBoard.get()
)添加边界检查,
BitsBoard
的运行时间是
ArrayBoard
的两倍。

在测量Java代码性能时,请确保阅读(并遵循)“位集的每个组件都有一个布尔值”中的建议。这取自
位集
文档。无论哪种方式,您使用的都是
boolean
值。@christopher他们的实现非常不同。@christopher我很确定BitSet使用long来存储位的值,而不是boolean。@christopher
BitSet
的文档根本没有声明数据是如何存储的,只有它是如何表示的——这取决于实现。但是,如果您看一看,该实现使用了
long
s。在测量Java代码的性能时,请确保阅读(并遵循)“位集的每个组件都有一个布尔值”中的建议。这取自
位集
文档。无论哪种方式,您使用的都是
boolean
值。@christopher他们的实现非常不同。@christopher我很确定BitSet使用long来存储位的值,而不是boolean。@christopher
BitSet
的文档根本没有声明数据是如何存储的,只有它是如何表示的——这取决于实现。然而,如果你看一看,这个实现使用了
long
s。是的,我在发布这个之前就看到了这一点
boolean[]
应该更高效,这也是我对我的结果感到非常惊讶的原因之一。@user2249516,我认为无论以何种方式,Jon Skeet都解释过缓存可能存在这样的情况,即您的数据是如何可缓存的。是的,我在发布这篇文章之前就看到了这一点
boolean[]
应该更高效,这也是我对我的结果感到非常惊讶的原因之一。@user2249516,我认为无论以何种方式,Jon Skeet都解释过缓存可能存在这样的情况,即数据的可缓存性是的,我不相信我完全忽略了这一点。对一个问题如此愚蠢的回答。谢谢你。。。他们真的应该把
length()
命名为更合理的名称,比如
highestSetBit()
。是的,真不敢相信我完全忽略了这一点。对一个问题如此愚蠢的回答。谢谢你。。。他们真的应该把
length()
命名得更合理一些,比如
highestSetBit()
BitSet uses about 1 bit per boolean value, and boolean[] uses about 1 byte per boolean value. that also the case that BitSet are more efficient
class BitSetBoard {

    ...

    @Override
    public int length()
    {
        return board.length();
    }

}