Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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 我应该使用迭代器还是forloop进行迭代?_Java_List_Loops_Map_Iterator - Fatal编程技术网

Java 我应该使用迭代器还是forloop进行迭代?

Java 我应该使用迭代器还是forloop进行迭代?,java,list,loops,map,iterator,Java,List,Loops,Map,Iterator,我不喜欢必须调用hasNext()和next()的想法,看看我需要一个循环来调用它们,我真的不认为使用列表和映射中提供给我们的迭代器有什么意义 是不是只有当你需要从列表中提取一个?或者,如果您从列表中选择一项,并且必须在无法测量的时间内这样做?我在Google或Stack上找不到这个,请帮我解决 我不是专门谈论增强的for循环(针对每个循环) 我也知道foreach循环在性能上很出色,但这更多的是一个“它为什么存在”的问题 编辑:意识到我说的是集合,而不是数组Foreach循环在这种情况下没有限

我不喜欢必须调用
hasNext()
next()
的想法,看看我需要一个循环来调用它们,我真的不认为使用列表和映射中提供给我们的迭代器有什么意义

是不是只有当你需要从列表中提取一个?或者,如果您从列表中选择一项,并且必须在无法测量的时间内这样做?我在Google或Stack上找不到这个,请帮我解决

我不是专门谈论增强的for循环(针对每个循环)

我也知道foreach循环在性能上很出色,但这更多的是一个“它为什么存在”的问题


编辑:意识到我说的是集合,而不是数组
Foreach
循环在这种情况下没有限制。

A
Foreach
相当于迭代器——它是相同事物的语法糖。因此,只要有可能,您应该总是选择
foreach
而不是iterator,因为这很方便,并且可以生成更简洁的代码

我在另一个答案中写到:

正如@RonnyShapiro所述,在某些情况下,您需要使用迭代器,但在许多情况下,
foreach
就足够了。请注意,
foreach
不是正常的
for
循环。当需要访问索引时,需要正常的
for
循环。虽然可以使用
foreach
手动创建单独的index int变量,但从某种角度来看,这并不理想

以下是更多信息:

访问集合时,
foreach
比循环数组访问的基本
更重要。然而,当访问数组时——至少在使用原语和包装器数组时——通过索引进行访问要快得多。见下文


当访问
int
Integer
数组时,索引比迭代器快23-40。下面是来自以下测试类的输出,它对100个元素的基本int数组中的数字求和(a是迭代器,B是索引):

完整测试等级:

   import  java.text.NumberFormat;
   import  java.util.Locale;
/**
   <P>{@code java TimeIteratorVsIndexIntArray 1000000}</P>

   @see  <CODE><A HREF="https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java">https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java</A></CODE>
 **/
public class TimeIteratorVsIndexIntArray  {
   public static final NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
   public static final void main(String[] tryCount_inParamIdx0)  {
      int testCount;
      //Get try-count from command-line parameter
         try  {
            testCount = Integer.parseInt(tryCount_inParamIdx0[0]);
         }  catch(ArrayIndexOutOfBoundsException | NumberFormatException x)  {
            throw  new IllegalArgumentException("Missing or invalid command line parameter: The number of testCount for each test. " + x);
         }

      //Test proper...START
         int[] intArray = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100};

         long lStart = System.nanoTime();
            for(int i = 0; i < testCount; i++)  {
               testIterator(intArray);
            }
         long lADuration = outputGetNanoDuration("A", lStart);

         lStart = System.nanoTime();
            for(int i = 0; i < testCount; i++)  {
               testFor(intArray);
            }
         long lBDuration = outputGetNanoDuration("B", lStart);

         outputGetABTestNanoDifference(lADuration, lBDuration, "A", "B");
   }
      private static final void testIterator(int[] int_array)  {
         int total = 0;
         for(int i = 0; i < int_array.length; i++)  {
            total += int_array[i];
         }
      }
      private static final void testFor(int[] int_array)  {
         int total = 0;
         for(int i : int_array)  {
            total += i;
         }
      }
      //Test proper...END

//Timer testing utilities...START
   public static final long outputGetNanoDuration(String s_testName, long l_nanoStart)  {
      long lDuration = System.nanoTime() - l_nanoStart;
      System.out.println("Test " + s_testName + ": " + nf.format(lDuration) + " nanoseconds");
      return  lDuration;
   }

   public static final long outputGetABTestNanoDifference(long l_aDuration, long l_bDuration, String s_aTestName, String s_bTestName)  {
      long lDiff = -1;
      double dPct = -1.0;
      String sFaster = null;
      if(l_aDuration > l_bDuration)  {
         lDiff = l_aDuration - l_bDuration;
         dPct = 100.00 - (l_bDuration * 100.0 / l_aDuration + 0.5);
         sFaster = "B";
      }  else  {
         lDiff = l_bDuration - l_aDuration;
         dPct = 100.00 - (l_aDuration * 100.0 / l_bDuration + 0.5);
         sFaster = "A";
      }
      System.out.println(sFaster + " faster by " + nf.format(lDiff) + " nanoseconds (" + dPct + "% faster)");
      return  lDiff;
   }
//Timer testing utilities...END
}
并对测试功能进行必要的更改(
int[]
List
length
size()
,等等)


在一次测试中,它们几乎是等价的,但迭代器仍然获胜。

在Java5中为每个都添加了,以便在集合上进行更简单的迭代。但是,它不会替换迭代器,因为只有使用迭代器,您才能在对集合进行迭代时(通过迭代器接口)修改集合。尝试从for each中的集合中添加\删除对象将导致ConcurrentModificationException


如果您只是读取值,foreach可能更好。

通常使用迭代器,它比使用
对象执行for循环要快一些。get(i)
,但差异对代码没有实际影响。
迭代器的主要优点是,通过调用迭代器上的remove方法,可以在对象交叉期间从列表中删除对象

这部分与java的发展历史有关。自从Java1.2以来,迭代器是一种处理对象集合的语言特性。Java1.5添加了iterable接口和for each循环

除非在循环过程中需要对迭代器执行某些特定操作,否则我将始终为每个块使用一个(在实现中使用迭代器)

好的,Java语言规范8(),14.14.2:

增强型for语句相当于以下形式的基本for语句:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
    {VariableModifier} TargetType Identifier =
    (TargetType) #i.next();
    Statement
}
所以,对于编译器来说,这是一样的。
此标准的早期版本包含对“foreach”语句的相同描述

当您想在迭代时删除它时,必须使用它,而这是foreach循环所不能做到的。请注意,“内部”foreach循环使用迭代器(请参见javadoc for
Iterable
)。
for(int i=0;i
这不起作用吗?是的,是的……我想是选择的问题;)但您在这里使用的不是foreach循环,这是第三种解决方案:p@VinceEmigh
foreach
for
具有性能优势,因为在许多情况下,基于迭代器的访问比基于索引的访问更快。请参阅我的答案。不,在for循环期间修改列表将不起作用。假设您有一个列表(a、b、c、d)。如果删除a,索引仍然会增加,并且使用修改后的列表(b、c、d),循环的下一次迭代将返回c并跳过b。为什么迭代器或foreach循环比另一个更快或更慢<(Object x:objects){…}
的code>就是(Iterator i=objects.Iterator();i.hasNext();){Object x=i.next();…}。除非你指的是带有整数索引的
循环,并使用
对象。get(i)
,因为如果您使用的列表具有非恒定时间的
get
(例如,LinkedList),则速度会较慢。不过,这不是foreach循环,这正是OP所要问的。还有一个问题。这是否意味着
foreach
是迭代器的替代品?我的意思是,除非你只想抓取一项,而不是浏览整个列表,否则我看不出使用迭代器的任何理由。使用迭代器一点问题都没有
foreach
只是为了方便起见,您不需要做任何事情,只需要按顺序逐个阅读每个元素。事实上,我会在一分钟内在我的答案中发布更多内容……好的,谢谢:)我不喜欢你需要一个循环来使用迭代器获取多个元素。如果出于某种原因,需要同步执行
hasNext()
next()
,但不同步列表。它可能会占用一些不需要的空间。(不是记忆,而是视觉)确切地说:视觉上,而不是实际上。我已经更新了我的答案来比较t
List<Integer> intList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100});
[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,429,929,976 nanoseconds
Test B: 5,262,782,488 nanoseconds
A faster by 1,832,852,512 nanoseconds (34.326681820485675% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,907,391,427 nanoseconds
Test B: 3,957,718,459 nanoseconds
A faster by 1,050,327,032 nanoseconds (26.038700083921256% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,566,004,688 nanoseconds
Test B: 4,221,746,521 nanoseconds
A faster by 1,655,741,833 nanoseconds (38.71935684115413% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,770,945,276 nanoseconds
Test B: 3,829,077,158 nanoseconds
A faster by 1,058,131,882 nanoseconds (27.134122749113843% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,467,474,055 nanoseconds
Test B: 5,183,149,104 nanoseconds
A faster by 1,715,675,049 nanoseconds (32.60101667104192% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,439,983,933 nanoseconds
Test B: 3,509,530,312 nanoseconds
A faster by 69,546,379 nanoseconds (1.4816434912159906% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,451,101,466 nanoseconds
Test B: 5,057,979,210 nanoseconds
A faster by 1,606,877,744 nanoseconds (31.269164666060377% faster)
for (I #i = Expression.iterator(); #i.hasNext(); ) {
    {VariableModifier} TargetType Identifier =
    (TargetType) #i.next();
    Statement
}