动态二维数组能够实现Java.Collection.size()方法吗?

5
好的,所以我正在使用Java制作一个动态2D数组,它实现了java.util.Collection接口。我让我的数组实现它是因为我希望它具有与普通 Collection 相同的功能。但是,我无法实现 size() 方法,因为在接口中它返回整数类型,而2D矩阵可能会导致整数类型溢出。
下面是我正在制作的类的一部分代码:
public abstract class AbstractMatrix<E> implements Collection<E>{
     @Override
     public long size() {
         return columns * rows;
     }
}

现在这种方法行不通,因为“返回类型与Collection<E>.size()不兼容”,如果我将类型更改为int,则可能会溢出columns * rows。
我知道我不能像这样覆盖size方法,但是否有任何方法可以确保该方法返回正确的大小,同时仍实现Collection接口?
是的,我知道这是不切实际的,并且很可能永远不会成为问题,但我很想知道是否有一个好的解决方案。

翻译:如果矩阵的大小超过45k行x 45k列(假设它是方阵),会发生溢出吗? - assylias
你计划拥有超过 2,147,483,647 个元素吗? - Stefan Haustein
一个 sizecolumns*rows 的矩阵,你可以用它来做什么?它会让你能够做些什么? - ewan.chalmers
2
我认为你应该问的问题是:“我的用例是否真的需要像这样定义大小?”“我的大小定义是否总体上合理?” - Tudor
相关:https://dev59.com/cmsz5IYBdhLWcg3w0rZC - assylias
是的,我意识到这可能永远不会被使用,但我想要学习的潜力。 - Wires77
4个回答

2
尽管您的size实现有问题,但是Collection#size的契约在javadoc中已定义:
返回此集合中的元素数。如果此集合包含超过Integer.MAX_VALUE个元素,则返回Integer.MAX_VALUE。
因此,您可以将大小计算为long,并在大于Integer.MAX_VALUE时返回Integer.MAX_VALUE
或者,您可以模仿例如LinkedList#add中实现的方式,在那里size仅递增并允许溢出。

2
假设您愿意拥有一个8GB的数组 - 这是一个二维数组的最小大小,它将用其总大小溢出一个int类型 - 并且假设您愿意对该集合执行任何有趣的操作,例如迭代它(仅为迭代而花费几分钟时间)... 我认为典型的方法要么是回退到实现Iterable而不是Collection,要么只返回Integer.MAX_VALUE,如Javadoc所指定的那样:
“返回此集合中的元素数。如果此集合包含超过Integer.MAX_VALUE个元素,则返回Integer.MAX_VALUE。”

1
有趣的是,LinkedList#add方法允许大小溢出且没有检查。 - assylias
这并不令人惊讶;通常在遇到这些问题之前,您的内存就已经耗尽了。 (此外,很难想象使用LinkedList会扩展到那么多元素的情况下有什么用途。) - Louis Wasserman

0

如果您真的关心可能会溢出的足够大的矩阵,您可以通过检查结果大小(初始化或调整大小)是否仍在整数范围内,并在这种情况下抛出(运行时)异常来确保不会发生这种情况。


-1

我不这么认为,你需要使用某种变通方法。你可以扩展你的大小以返回负数,并将其解释为无符号32位整数,这样你就可以得到最大的40亿多一点。

不过,请问你真的需要支持那么多对象吗?请记住,40亿多一点32位整数会占用16GB的内存。在使用64位Java时,一个4亿长的Object数组,全部设置为null,会占用32GB,因为64位Java上的引用是64位。这甚至还没有考虑实际实例化那么多类所使用的内存,而实际上这个数量很可能会更高。


是的,我意识到拥有一个会溢出的二维数组是不切实际的,但我只是想问问是否有解决方案。 - Wires77
你有没有考虑查看ArrayList的代码。为什么你的返回类型需要是long呢? - branchgabriel
mugafuga:ArrayList是集合,只有int size()方法,没有long size() - Wug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接