在Java';中是否有访问迭代计数器的方法;每个循环都有什么?
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
for(String s : stringArray) {
doSomethingWith(s);
}
了解循环已被处理的频率
除了对(inti=0;i,还有
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++;
}