Java 到达数组中的最后一个索引后返回到第一个索引

Java 到达数组中的最后一个索引后返回到第一个索引,java,arrays,Java,Arrays,在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)); } charres;

在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));
}
charres;
int ctr=10
字符[]火焰={F','L','A','M','E','S'};
对于(intz=0;z
您应该使用
%
强制索引保持在
火焰长度范围内,以便它们成为有效的索引

int len = flames.length;
for(int z = 0; z < ctr-1; z++){
      res = (flames[z % len]);
      jLabel1.setText(String.valueOf(res));
}
int len=flames.length;
对于(intz=0;z
您可以尝试以下方法:-

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));
}
charres;
int ctr=10
字符[]火焰={F','L','A','M','E','S'};
int n=火焰。长度();
对于(intz=0;z
您需要使用一个受限于数组大小的索引。更准确地说,也更深奥地说,您需要将for循环迭代{0..9}映射到flame数组{0..
flames.length()-1
}的有效索引,在本例中,它们与{0..5}相同

当循环从0迭代到5时,映射很简单。当循环迭代第6次时,需要将其映射回数组索引0,当循环迭代到第7次时,需要将其映射到数组索引1,依此类推

==天真的方式==

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));
}
==怎么做==

现在,如果你注意的话,你可以看到我们只是在索引上做模运算。因此,如果我们使用模块化(%)运算符,我们可以简化您的代码:

final int n = flames.length();
for(int z = 0; z < ctr-1; z++)
{
      res = (flames[z % n]);
      jLabel1.setText(String.valueOf(res));
}
final int n=flames.length();
对于(intz=0;z
处理此类问题时,请考虑从域(在本例中,用于循环迭代)到范围(有效数组索引)的函数映射

更重要的是,在开始编写代码之前,先在纸上把它写出来。这将使您在解决这些基本问题方面走上很长的一段路。

虽然答案是性能方面的,但我认为您还应该研究一下,因为它们将为您提供更大的来回阅读灵活性

这意味着您可以像编写FLAMESSEMALF一样轻松地编写
FlamesFlamesFlames
,等等

int-ctr=10;
List flames=Arrays.asList('F','L','A','M','E','S');
迭代器it=flames.Iterator();

对于(intz=0;z,我将这样做:

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;
        }
}
void textLoop(可编辑文本、JLabel JLabel、int计数){
int-idx=0;
while(true)
for(字符:文本){
jLabel.setText(String.valueOf(ch));
如果(++idx

编辑:在代码中发现一个bug(
idx
需要在循环外初始化)。现在已修复。我还将其重构为一个单独的函数。

在访问
flames[]
时使用
flames[]
像…
flames[z%flames.length()];
在索引表达式上使用mod(%)操作符:
res=flames[z%flames.length()];
或者更好,在for循环之外有一个不变变量
n=flames.length()
,然后有
res=flames[z%n];
@luis.espinal:编译器不会为我们这样做吗?
flames.length()
在循环中会被编译器优化,对不对?@boxed\uu\l-好问题。我不相信它会IIRC。一种确认这一点的方法是在两个版本上使用javap反汇编程序(带和w/o循环外的不变量)然后比较两个的输出。@luis.espinal:看来你是对的。在类似的代码上进行了反汇编。没有优化。有类似的项目可以进行此优化和更多。+1move
flames.length()
离开for循环。它是一个不变量。move
flames.length()
超出for循环。它是一个不变量。@luis.espinal:-喜欢你的第二个想法。在我的回答中补充了这一点!!更优雅的是使用无限/循环迭代器,如下所示:@lbalazscs谢谢你的评论。做了一些测试并相应更新。
// guava example of cycle iterators
Iterator<Character> iterator = Iterators.cycle(flames);
for (int z = 0; z < ctr - 1; z++) {
    res = iterator.next();
}
String flames = "FLAMES";
int ctr = 10;

textLoop(flames.toCharArray(), jLabel1, ctr);
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;
        }
}