如何将Java的for each循环减半?

3

我经常在Java中使用for-each循环。我使用它们让我的对象的每个类都能够执行“绘图”操作,但这需要大量的内存,因此我想将其减半,有没有一种方法可以只对部分列表执行for-each循环?

for(Tile tile: tiles){
tile.draw();
}

我想要:

for(Tile tile: (half of)tiles){
    tile.draw();
}

这是否可能,或者我只需要获取瓷砖的长度,当它达到一定数量时中断循环?


你想怎样把它一分为二?例如,每隔一个瓷砖取一个,还是只取前半部分,...还是以其他方式? - Chthonic Project
我想仅处理“tiles”列表的前一半,需要时再处理其余部分。因此现在只处理前半部分。 - Tautvydas Jalinskas
这会如何节省内存?列表的后半部分是否多余?绘图操作的内存占用与绘制的瓷砖数量成比例吗? - RealSkeptic
我将通过将列表分成块来节省内存,这样当我在一侧时,只需遍历列表的一部分,而不是每5000个以上的元素。 - Tautvydas Jalinskas
3
@TautvydasJalinskas那可能不是真的。 浏览列表并不意味着在内存中有每个项目的额外副本。 - Dan Getz
5个回答

4

既然您已经明确使用了ArrayList,您可以使用subList函数来获取列表的前一半视图。

for(Tile tile: tiles.subList(0, tiles.size()/2){
  tile.draw();
}

这里使用了 foreach 循环,代码简洁易读。

由于子列表只是原始列表的一个视图,所以没有复制到新列表的惩罚。


3

好的,那么就老式的 for 循环吧。假设 tilesList<Tile> 的一个实例:

for(int i = 0; i < tiles.size() / 2; i++)
{
  tiles.get(i).draw();
}

或者,如果您想保持迭代器顺序:

Iterator<Tile> iter = tiles.iterator();
int i = 0;
int halfway = tiles.size() / 2;
while(i < halfway)
{
  Tile tile = iter.next();
  tile.draw();
  i++;
}

1
这里假设它是一个ArrayList,因为如果它是一个LinkedList,那么使用列表迭代器的操作就不等同于使用foreach循环。 - RealSkeptic
1
没问题。他的假设是正确的,这可能会有所帮助,所以我会点赞。 - Tautvydas Jalinskas
1
@shekharsuman:不做任何假设,这个问题无法回答。目前所有的回答都基于 OP 没有明确指定的假设。 - Chthonic Project
@RealSkeptic 是正确的。我添加了一个替代方案,保留了原始迭代器的顺序。 - Erick G. Hagstrom

2
我希望只完成“瓷砖”列表的一半,需要时再完成另一半。
如果两个部分的顺序无关紧要,可以这样做:
int counter = 0;
for(Tile tile: tiles) {
    if (counter++ % 2 == 0) {
        tile.draw();
    }
}

对于另一半,请执行counter++ %2 == 1


2
Oooh,有几种方法可以做到这一点。
JAVA
final List<Tile> tiles = .... // create the list of Tile instances
//Be sure that tiles is not empty before to do that
final List<Tile> firstHalfSubList=tiles.subList(0, tiles.size()/2);
final List<Tile> secondHalfSubList=tiles.subList(tiles.size()/2, tiles.length());

注意到这两个半列表都是备用的,因此使它们不可变。

但我的最爱是使用Guava库。

GUAVA

import com.google.common.collect.Lists;
import com.google.common.math.IntMath;
import java.math.RoundingMode;

final List<Tile> tiles = .... // create the list of Tile instances
final int partitionSize = IntMath.divide(tile.size(), 2, RoundingMode.UP);
final List<List<Tile>> partitions = Lists.partition(tile, partitionSize);

你有一个包含两个分区的列表,可以对它们进行迭代!


Guava的方法非常优美! - Erick G. Hagstrom
我认为是这样的。Guava是一个非常优秀的库,而Java8则吸收了很多它的优秀思想。 - JeanValjean

0

这里给出的答案已经很好了,但我注意到你在问题中想要使用 for-each 循环。因此,你可以使用流来将列表分成两半:

List<Tile> halve =tiles.stream().limit(tiles.size()/2).collect(Collectors.toList());
for(Tile tile : halve)
{   
}

这与其他答案相同的方法,只是一种风格选择的观点。


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