例如,我想在 java 中执行以下操作:
int[] numbers = {1,2,3,4,5};
int[] result = numbers*2;
//result now equals {2,4,6,8,10};
这可以在不遍历数组的情况下完成吗?我是否需要使用不同的数据类型,例如 ArrayList?当前的迭代步骤需要一些时间,我希望这样的事情会有所帮助。
不,您不能在不遍历整个数组的情况下将数组中的每个项目相乘。正如评论中所指出的,即使您可以*
以这种方式使用运算符,实现仍然必须触及数组中的每个项目。
此外,不同的数据类型将不得不做同样的事情。
我认为与显而易见的不同答案可能对遇到相同问题并且不介意一层(或两层)复杂性的其他人有益。
在 Haskell 中,有一种称为“惰性求值”的东西,您可以在其中执行诸如将无限大的数组乘以 2 之类的操作,而 Haskell 会“执行”该操作。当您访问该数组时,它会尝试根据需要评估所有内容。在 Java 中,我们没有这种奢侈,但我们可以以可控的方式模拟这种行为。
您将需要创建或扩展您自己的List
类并添加一些新功能。对于要支持的每个数学运算,您都需要函数。我有下面的例子。
LazyList ll = new LazyList();
// Add a couple million objects
ll.multiplyList(2);
其内部实现将是创建一个存储您需要执行的所有原始操作的队列,以便保留操作顺序。现在,每次读取一个元素时,您都会在返回结果之前执行队列中的所有操作。这意味着读取非常慢(取决于执行的操作数量),但我们至少得到了想要的结果。
如果您发现自己每次都遍历整个数组,那么在最后出队而不是保留原始值可能会很有用。
如果您发现您正在进行随机访问,我会在调用时保留原始值并返回修改后的结果。
如果您需要更新条目,您需要确定这意味着什么。您是在那里替换一个值,还是在执行操作后替换一个值?根据您的回答,您可能需要在队列中倒退以获得“预操作”值来替换旧值。原因是在下一次读取同一对象时,将再次应用操作,然后将值恢复为您打算在列表中替换的值。
此解决方案可能还有其他细微差别,并且根据您的需求和访问方式(顺序或随机),您实现它的方式将完全不同,但这应该是一个好的开始。
随着 Java 8 的引入,这项任务可以使用流来完成。
private long tileSize(int[] sizes) {
return IntStream.of(sizes).reduce(1, (x, y) -> x * y);
}
不,不是。如果您的集合真的很大并且您想更快地做到这一点,您可以尝试在 2 个或更多线程中对元素进行操作,但您必须注意同步(使用同步集合)或将您的集合划分为 2 个(或更多)集合并在每个线程中对一个集合进行操作。我不确定它是否会比仅遍历数组更快 - 这取决于您的集合的大小以及您想要对每个元素执行的操作。如果你想使用这个解决方案,你会知道它在你的情况下是否更快 - 它可能会更慢,而且肯定会更复杂。一般来说 - 如果它不是代码的关键部分并且执行时间不是太长,我会保留它现在的样子。