Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java';中是否有访问迭代计数器的方法;每个循环都有什么?_Java_Loops_For Loop_Foreach - Fatal编程技术网

在Java';中是否有访问迭代计数器的方法;每个循环都有什么?

在Java';中是否有访问迭代计数器的方法;每个循环都有什么?,java,loops,for-loop,foreach,Java,Loops,For Loop,Foreach,Java中是否有针对每个循环的方法 for(String s : stringArray) { doSomethingWith(s); } 了解循环已被处理的频率 除了对(inti=0;i{ System.out.println(“索引:”+index); System.out.println(“值:“+strings.get(index)); }); 以下是我如何做到这一点的示例。这将获取for each循环的索引。希望这有帮助 public class CheckForEachLoop

Java中是否有针对每个循环的方法

for(String s : stringArray) {
  doSomethingWith(s);
}
了解循环已被处理的频率

除了对(inti=0;i-loop使用古老而著名的
,还有

int i = 0;
for(String s : stringArray) {
  doSomethingWith(s);
  i++;
}

在for-each循环中有这样一个计数器的唯一方法是什么?

如果在for-each循环中需要一个计数器,您必须自己计数。据我所知,没有内置计数器。

最简单的解决方案是运行自己的计数器,因此:

int i = 0;
for (String s : stringArray) {
    doSomethingWith(s, i);
    i++;
}
这样做的原因是,无法保证集合中的项(该变量的
for
迭代)甚至具有索引,甚至具有定义的顺序(某些集合在添加或删除元素时可能会更改顺序)

例如,请参见以下代码:

import java.util.*;

public class TestApp {
  public static void AddAndDump(AbstractSet<String> set, String str) {
    System.out.println("Adding [" + str + "]");
    set.add(str);
    int i = 0;
    for(String s : set) {
        System.out.println("   " + i + ": " + s);
        i++;
    }
  }

  public static void main(String[] args) {
    AbstractSet<String> coll = new HashSet<String>();
    AddAndDump(coll, "Hello");
    AddAndDump(coll, "My");
    AddAndDump(coll, "Name");
    AddAndDump(coll, "Is");
    AddAndDump(coll, "Pax");
  }
}
表明顺序不被认为是集合的显著特征,这是正确的


没有手动计数器也有其他方法,但这是一项值得怀疑的工作。

没有,但您可以提供自己的计数器


原因是for-each循环内部没有计数器;它基于接口,也就是说,它使用一个
迭代器来循环“集合”-它可能根本不是集合,事实上也可能根本不是基于索引的东西(如链表)。

恐怕这在
foreach
中是不可能的。但我可以向您推荐一种简单的老式for循环:


Sun
正在考虑对
Java7
进行的更改之一是提供对foreach循环中内部
迭代器的访问。语法如下(如果接受):

这是语法上的甜点,但显然有很多人对这个特性提出了要求。但在批准之前,您必须自己计算迭代次数,或者使用带有
迭代器的常规for循环,还有另一种方法

假设您编写了自己的
索引
类和一个静态方法,该方法在该类的实例上返回一个
Iterable
,您可以

for (Index<String> each: With.index(stringArray)) {
    each.value;
    each.index;
    ...
}
帕克斯的答案有一个“变体”…;-)


我有点惊讶,没有人提出以下建议(我承认这是一种懒惰的方法…); 如果stringArray是某种类型的列表,则可以使用类似stringArray.indexOf的内容来返回当前计数的值

注意:这假设列表的元素是唯一的,或者它们是否非唯一并不重要(因为在这种情况下,它将返回找到的第一个副本的索引)


在某些情况下,这就足够了…

Java8中使用lambdas功能接口可以创建新的循环抽象。我可以使用索引和集合大小循环集合:

List<String> strings = Arrays.asList("one", "two","three","four");
forEach(strings, (x, i, n) -> System.out.println("" + (i+1) + "/"+n+": " + x));
我将其实施为:

   @FunctionalInterface
   public interface LoopWithIndexAndSizeConsumer<T> {
       void accept(T t, int i, int n);
   }
   public static <T> void forEach(Collection<T> collection,
                                  LoopWithIndexAndSizeConsumer<T> consumer) {
      int index = 0;
      for (T object : collection){
         consumer.accept(object, index++, collection.size());
      }
   }
public static <T> void forEachHeadTail(Collection<T> collection, 
                                       Consumer<T> headFunc, 
                                       Consumer<T> tailFunc) {
   int index = 0;
   for (T object : collection){
      if (index++ == 0){
         headFunc.accept(object);
      }
      else{
         tailFunc.accept(object);
      }
   }
}
可正确打印逗号分隔的列表:

one,two,three,four
我将其实施为:

   @FunctionalInterface
   public interface LoopWithIndexAndSizeConsumer<T> {
       void accept(T t, int i, int n);
   }
   public static <T> void forEach(Collection<T> collection,
                                  LoopWithIndexAndSizeConsumer<T> consumer) {
      int index = 0;
      for (T object : collection){
         consumer.accept(object, index++, collection.size());
      }
   }
public static <T> void forEachHeadTail(Collection<T> collection, 
                                       Consumer<T> headFunc, 
                                       Consumer<T> tailFunc) {
   int index = 0;
   for (T object : collection){
      if (index++ == 0){
         headFunc.accept(object);
      }
      else{
         tailFunc.accept(object);
      }
   }
}
公共静态void forEachHeadTail(集合,
消费者总部,
消费者(FUNC){
int指数=0;
for(T对象:集合){
如果(索引+==0){
headFunc.accept(对象);
}
否则{
tailFunc.accept(对象);
}
}
}

Java 8引入了
Iterable#forEach()
/
Map#forEach()
方法,与每个循环的“经典”方法相比,它对许多
集合
/
映射
实现更有效。但是,在这种情况下,也不提供索引。这里的技巧是在lambda表达式之外使用
AtomicInteger
。注意:lambda表达式中使用的变量必须是有效的final,这就是为什么我们不能使用普通的
int

final AtomicInteger indexHolder = new AtomicInteger();
map.forEach((k, v) -> {
    final int index = indexHolder.getAndIncrement();
    // use the index
});

对于偶尔只需要索引的情况,比如catch子句,我有时会使用indexOf

for(String s : stringArray) {
  try {
    doSomethingWith(s);
  } catch (Exception e) {
    LOGGER.warn("Had some kind of problem with string " +
      stringArray.indexOf(s) + ": " + s, e);
  }
}
惯用解决方案:
final Set double;//样板
final Iterator Iterator=doubles.Iterator();
for(int ordinal=0;iterator.hasNext();ordinal++)
{
System.out.printf(“%d:%f”,序号,迭代器.next());
System.out.println();
}
这实际上就是谷歌在《关于为什么他们不提供<代码>计数迭代器的文章》中提出的解决方案


虽然有很多其他的方法可以达到同样的效果,但我将为一些不满意的用户分享我的方法。我正在使用Java8intstream特性

1。数组

Object[] obj = {1,2,3,4,5,6,7};
IntStream.range(0, obj.length).forEach(index-> {
    System.out.println("index: " + index);
    System.out.println("value: " + obj[index]);
});
2。列表

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");

IntStream.range(0, strings.size()).forEach(index-> {
    System.out.println("index: " + index);
    System.out.println("value: " + strings.get(index));
});
List strings=new ArrayList();
集合.addAll(字符串“A”、“B”、“C”、“D”);
IntStream.range(0,strings.size()).forEach(索引->{
System.out.println(“索引:”+index);
System.out.println(“值:“+strings.get(index));
});

以下是我如何做到这一点的示例。这将获取for each循环的索引。希望这有帮助

public class CheckForEachLoop {

    public static void main(String[] args) {

        String[] months = new String[] { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST",
                "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" };
        for (String s : months) {
            if (s == months[2]) { // location where you can change
              doSomethingWith(s); // however many times s and months
                                  // doSomethingWith(s) will be completed and 
                                  // added together instead of counter
            }

        }
        System.out.println(s); 


    }
}

最佳和优化的解决方案是执行以下操作:

int i=0;

for(Type t: types) {
  ......
  i++;
}

Where Type可以是任何数据类型,Type是应用循环的变量。

(我已经修复了这个问题中的错误。)随着整个循环的性能接近O(n²),很难想象哪怕是在某些情况下,这种方法也会优于其他方法。对不起,好主意。如果不是索引类的短期对象创建,我会投赞成票。@mR_fr0g别担心,我对此进行了基准测试,创建所有这些对象并不比在每次迭代中重用同一对象慢。原因是,所有这些对象都只分配在eden空间中,并且永远不会有足够长的生命到达堆。所以分配它们和分配局部变量一样快。@akuhn Wait。伊甸园空间并不意味着不需要GC。恰恰相反,您需要调用构造函数,
final AtomicInteger indexHolder = new AtomicInteger();
map.forEach((k, v) -> {
    final int index = indexHolder.getAndIncrement();
    // use the index
});
for(String s : stringArray) {
  try {
    doSomethingWith(s);
  } catch (Exception e) {
    LOGGER.warn("Had some kind of problem with string " +
      stringArray.indexOf(s) + ": " + s, e);
  }
}
final Set<Double> doubles; // boilerplate
final Iterator<Double> iterator = doubles.iterator();
for (int ordinal = 0; iterator.hasNext(); ordinal++)
{
    System.out.printf("%d:%f",ordinal,iterator.next());
    System.out.println();
}
Object[] obj = {1,2,3,4,5,6,7};
IntStream.range(0, obj.length).forEach(index-> {
    System.out.println("index: " + index);
    System.out.println("value: " + obj[index]);
});
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");

IntStream.range(0, strings.size()).forEach(index-> {
    System.out.println("index: " + index);
    System.out.println("value: " + strings.get(index));
});
public class CheckForEachLoop {

    public static void main(String[] args) {

        String[] months = new String[] { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST",
                "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" };
        for (String s : months) {
            if (s == months[2]) { // location where you can change
              doSomethingWith(s); // however many times s and months
                                  // doSomethingWith(s) will be completed and 
                                  // added together instead of counter
            }

        }
        System.out.println(s); 


    }
}
int i=0;

for(Type t: types) {
  ......
  i++;
}