在for循环中的数组到达最后一个索引后,我得到一个异常,说索引超出范围。我想要的是它返回到第一个索引,直到z
等于ctr
。我怎么能这样做?
我的代码:
char res;
int ctr = 10
char[] flames = {'F','L','A','M','E','S'};
for(int z = 0; z < ctr-1; z++){
res = (flames[z]);
jLabel1.setText(String.valueOf(res));
}
答案 0 :(得分:6)
尽管luis.espinal回答,但性能方面更好,我认为您还应该查看Iterator's ,因为它们会为您提供更大的灵活性来回读 - 和 - 类推。
这意味着您可以轻松地将FLAMESFLAMES
写为FLAMESSEMALF
等等......
int ctr = 10;
List<Character> flames = Arrays.asList('F','L','A','M','E','S');
Iterator it = flames.iterator();
for(int z=0; z<ctr-1; z++) {
if(!it.hasNext()) // if you are at the end of the list reset iterator
it = flames.iterator();
System.out.println(it.next().toString()); // use the element
}
出于好奇心做这个循环1M次(平均100个样本的结果)需要:
using modulo: 51ms
using iterators: 95ms
using guava cycle iterators: 453ms
修改强> 循环迭代器,正如lbalazscs很好地说,它更优雅。它们付出了代价,番石榴的实施速度慢了4倍。你可以推行自己的实施,很难。
// guava example of cycle iterators
Iterator<Character> iterator = Iterators.cycle(flames);
for (int z = 0; z < ctr - 1; z++) {
res = iterator.next();
}
答案 1 :(得分:5)
您应该使用%
强制索引保持在flames.length
范围内,以便它们生成有效的索引
int len = flames.length;
for(int z = 0; z < ctr-1; z++){
res = (flames[z % len]);
jLabel1.setText(String.valueOf(res));
}
答案 2 :(得分:4)
您需要使用仅限于数组大小的索引。更确切地说,从根本上说,你需要将for循环迭代{0..9}映射到火焰数组{0 .. flames.length()-1
}的有效索引,它们是相同的,在这种情况下,到{0..5}。
当循环从0迭代到5时,映射很简单。当循环迭代第6次时,你需要将它映射回数组索引0,当它迭代到第7次时,你将它映射到数组索引1,依此类推。
==NaïveWay==
for(int z = 0, j = 0; z < ctr-1; z++, j++)
{
if ( j >= flames.length() )
{
j = 0; // reset back to the beginning
}
res = (flames[j]);
jLabel1.setText(String.valueOf(res));
}
==更合适的方式==
然后你可以通过实现flames.length()
是一个不变量来改进它,你可以从for循环中移出它。
final int n = flames.length();
for(int z = 0, j = 0; z < ctr-1; z++, j++)
{
if ( j >= n )
{
j = 0; // reset back to the beginning
}
res = (flames[j]);
jLabel1.setText(String.valueOf(res));
}
==如何做==
现在,如果您正在关注,您可以看到我们只是对索引进行模运算。因此,如果我们使用模块化(%)运算符,我们可以简化您的代码:
final int n = flames.length();
for(int z = 0; z < ctr-1; z++)
{
res = (flames[z % n]);
jLabel1.setText(String.valueOf(res));
}
在处理这类问题时,请考虑函数映射,从域(在本例中为循环迭代)到Range(有效数组索引)。
更重要的是,在开始编码之前先在纸上进行处理。这将为您解决这些类型的基本问题带来很长的路要走。
答案 3 :(得分:2)
您可以尝试以下方法: -
char res;
int ctr = 10
char[] flames = {'F','L','A','M','E','S'};
int n = flames.length();
for(int z = 0; z < ctr-1; z++){
res = flames[z %n];
jLabel1.setText(String.valueOf(res));
}
答案 4 :(得分:1)
我将如何做到这一点:
String flames = "FLAMES";
int ctr = 10;
textLoop(flames.toCharArray(), jLabel1, ctr);
textLoop方法:
void textLoop(Iterable<Character> text, JLabel jLabel, int count){
int idx = 0;
while(true)
for(char ch: text){
jLabel.setText(String.valueOf(ch));
if(++idx < count) return;
}
}
编辑:在代码中发现了一个错误(idx
需要在循环外初始化)。现在已经修好了。我也将它重构为一个独立的功能。