<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: On Iterators and Indexes</title>
	<atom:link href="http://cafe.elharo.com/blogroll/oniterators/feed/" rel="self" type="application/rss+xml" />
	<link>http://cafe.elharo.com/blogroll/oniterators/</link>
	<description>Longer than a blog; shorter than a book</description>
	<lastBuildDate>Tue, 09 Mar 2010 18:31:23 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: cowtowncoder</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-77</link>
		<dc:creator>cowtowncoder</dc:creator>
		<pubDate>Fri, 06 Jan 2006 22:06:11 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-77</guid>
		<description>&lt;h3&gt;O(1)... no, not really, you just need to dig deeper&lt;/h3&gt;

Elliotte, System.arraycopy does exactly the same copying under the hood (albeit possibly via a syscall that uses the most optimal native block copy available)? Complexity-wise it is still definitely O(N) for insertions in and deletions from the middle. There is no magic bullet available there; when elements need to be moved, they need to be moved, and the speed is relative to the size of the block moved. If this were not the case, insertion to bigger lists would not take any longer than those to smaller lists; you can benchmark and verify that longer lists do take longer to modify. It&#039;s enlightening to check out relative speed difference between simple loop copy and System.arraycopy. Which is faster depends on platform and the size of the block -- arraycopy has JNI overhead, and for smaller copies may be slower. More often though they are about as fast, for smallish blocks.</description>
		<content:encoded><![CDATA[<h3>O(1)&#8230; no, not really, you just need to dig deeper</h3>
<p>Elliotte, System.arraycopy does exactly the same copying under the hood (albeit possibly via a syscall that uses the most optimal native block copy available)? Complexity-wise it is still definitely O(N) for insertions in and deletions from the middle. There is no magic bullet available there; when elements need to be moved, they need to be moved, and the speed is relative to the size of the block moved. If this were not the case, insertion to bigger lists would not take any longer than those to smaller lists; you can benchmark and verify that longer lists do take longer to modify. It&#8217;s enlightening to check out relative speed difference between simple loop copy and System.arraycopy. Which is faster depends on platform and the size of the block &#8212; arraycopy has JNI overhead, and for smaller copies may be slower. More often though they are about as fast, for smallish blocks.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Elliotte Rusty Harold</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-76</link>
		<dc:creator>Elliotte Rusty Harold</dc:creator>
		<pubDate>Fri, 06 Jan 2006 22:05:18 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-76</guid>
		<description>&lt;h3&gt;ArrayList *is* O(1)&lt;/h3&gt;

&lt;code&gt;ArrayList&lt;/code&gt; is O(1) for all operations including insert and delete. The implementation is probably not what you think it is. The key is the use of &lt;code&gt;System.arraycopy()&lt;/code&gt; to copy elements when the list is resized, rather than manually copying each element in turn. The naive descriptions of array lists given in most data structures text book simply do not describe how Java implements this very efficient class. Look at the code in ArrayList.java some time. You&#039;ll be pleasantly surprised.</description>
		<content:encoded><![CDATA[<h3>ArrayList *is* O(1)</h3>
<p><code>ArrayList</code> is O(1) for all operations including insert and delete. The implementation is probably not what you think it is. The key is the use of <code>System.arraycopy()</code> to copy elements when the list is resized, rather than manually copying each element in turn. The naive descriptions of array lists given in most data structures text book simply do not describe how Java implements this very efficient class. Look at the code in ArrayList.java some time. You&#8217;ll be pleasantly surprised.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: cowtowncoder</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-75</link>
		<dc:creator>cowtowncoder</dc:creator>
		<pubDate>Fri, 06 Jan 2006 22:04:46 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-75</guid>
		<description> &lt;h3&gt;One reason to prefer forward indexing...&lt;/h3&gt;

caches are designed for it I&#039;m surprised that no one commented on something that is usually brought up: one of main reasons to loop upwards is that CPU caches generally are most adpated to such usage patterns, and may not like the &quot;wrong&quot; direction (pre-fetching not working as well). Now whether this is the case for all JVMs I don&#039;t know... and further, it may only matter for big arrays (array lists), not for smaller ones. Anyway, thought I&#039;ll add the one remaining somewhat well-known argument in the soup. For what it&#039;s worth, I do think that while Iterators have their place, the overhead is likely to always exist; and as such it makes sense to optimize accessing INTERNAL ArrayLists using direct indexing. For public API possibility of getting a LinkedList may be a valid concern, however  Posted by &lt;a href=&quot;mailto:cowtowncoder%40yahoo%2Ecom&quot; rel=&quot;nofollow&quot;&gt;&lt;/a&gt; on Thursday, December 2nd, 2004 at 11:08 AM</description>
		<content:encoded><![CDATA[<h3>One reason to prefer forward indexing&#8230;</h3>
<p>caches are designed for it I&#8217;m surprised that no one commented on something that is usually brought up: one of main reasons to loop upwards is that CPU caches generally are most adpated to such usage patterns, and may not like the &#8220;wrong&#8221; direction (pre-fetching not working as well). Now whether this is the case for all JVMs I don&#8217;t know&#8230; and further, it may only matter for big arrays (array lists), not for smaller ones. Anyway, thought I&#8217;ll add the one remaining somewhat well-known argument in the soup. For what it&#8217;s worth, I do think that while Iterators have their place, the overhead is likely to always exist; and as such it makes sense to optimize accessing INTERNAL ArrayLists using direct indexing. For public API possibility of getting a LinkedList may be a valid concern, however  Posted by <a href="mailto:cowtowncoder%40yahoo%2Ecom" rel="nofollow"></a> on Thursday, December 2nd, 2004 at 11:08 AM</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: hal</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-74</link>
		<dc:creator>hal</dc:creator>
		<pubDate>Fri, 06 Jan 2006 22:04:19 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-74</guid>
		<description>&lt;h3&gt;Reuse of iterators&lt;/h3&gt;

We can certainly discuss the difference in syntactic style when comparing indexes with iterators. But with the new for syntax in Java 1.5 (or was it 5.0?), the styles are very similar, so the biggest argument for using indexes is performance. The problem with iterators is of course that they have to be allocated, thus reducing speed and quickly generating garbage that must be reclaimed. Java is fairly good at both now, with the generational garbage collector, but one way of reducing the problem would be to define that iterators may be reused once they&#039;ve returned false for hasMore(). Hence, a class may hold a pool of iterators that are in use and once an iterator&#039;s hasMore() method returns false, it is put in a list of reusable iterators. The iterator method (in Iterable) may return a reusable iterator or create a new one. Usually iterators are shortlived and few are needed at once, so this should save both time and space.</description>
		<content:encoded><![CDATA[<h3>Reuse of iterators</h3>
<p>We can certainly discuss the difference in syntactic style when comparing indexes with iterators. But with the new for syntax in Java 1.5 (or was it 5.0?), the styles are very similar, so the biggest argument for using indexes is performance. The problem with iterators is of course that they have to be allocated, thus reducing speed and quickly generating garbage that must be reclaimed. Java is fairly good at both now, with the generational garbage collector, but one way of reducing the problem would be to define that iterators may be reused once they&#8217;ve returned false for hasMore(). Hence, a class may hold a pool of iterators that are in use and once an iterator&#8217;s hasMore() method returns false, it is put in a list of reusable iterators. The iterator method (in Iterable) may return a reusable iterator or create a new one. Usually iterators are shortlived and few are needed at once, so this should save both time and space.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Alex Blewitt</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-73</link>
		<dc:creator>Alex Blewitt</dc:creator>
		<pubDate>Fri, 06 Jan 2006 22:03:33 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-73</guid>
		<description>&lt;h3&gt;ArrayList is *not* O(1)&lt;/h3&gt;

The comment that &quot;ArrayList is O(1) for all operations&quot; is quite definitely not true. In fact, it&#039;s only true for get; insert and delete are O(n) operations. If you&#039;re dealing with a large (i.e. &gt; 10) amounts of data ArrayList append degrades to O(n), because when you insert data into the array, every now and again it has to resize. (The default implementation is to allocates space for 10 entries, but can be changed in the constructor.) The resize operation is O(n). So in fact, ArrayList is only O(1) for get; all others are O(n).

LinkedList, on the other hand, is O(1) for all operations *except* index -based access. But since most people really don&#039;t need index based accses (they&#039;re all using Iterators to go through the entire collection), iteration is O(1) per element anyway.</description>
		<content:encoded><![CDATA[<h3>ArrayList is *not* O(1)</h3>
<p>The comment that &#8220;ArrayList is O(1) for all operations&#8221; is quite definitely not true. In fact, it&#8217;s only true for get; insert and delete are O(n) operations. If you&#8217;re dealing with a large (i.e. &gt; 10) amounts of data ArrayList append degrades to O(n), because when you insert data into the array, every now and again it has to resize. (The default implementation is to allocates space for 10 entries, but can be changed in the constructor.) The resize operation is O(n). So in fact, ArrayList is only O(1) for get; all others are O(n).</p>
<p>LinkedList, on the other hand, is O(1) for all operations *except* index -based access. But since most people really don&#8217;t need index based accses (they&#8217;re all using Iterators to go through the entire collection), iteration is O(1) per element anyway.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Kevin Klinemeier</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-72</link>
		<dc:creator>Kevin Klinemeier</dc:creator>
		<pubDate>Fri, 06 Jan 2006 22:03:07 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-72</guid>
		<description> Re: Reason to count backwards But if you iterate backwards, and a listener is removed, don&#039;t you dispatch an event twice to the current listener? An example:
List location, listener
1, A
2, B
3, C

4, D
You&#039;re processing list location 4, listener D. During that time,
listener B removes itself. Your list now reads:

1, A
2, C
3, D

When you process location 3, you get D again? Or are double-deliveries not a problem for your system? Also, don&#039;t you face the problem that a listener can be removed between the time you called size() and the first list access? Small, but ArrayIndexOutOfBounds is kind of annoying at runtime. When I did listener dispatching (3 years ago) I never figured out a thread-safe approach to listener dispatch that didn&#039;t involve synchronization, which quickly required list copying to reduce lock contention. I&#039;ll admit I didn&#039;t spend a ton of time on it, as the solution I had was &quot;good enough&quot;.

-Kevin Klinemeier (who can&#039;t figure out how to add his name directly to the tagline)
</description>
		<content:encoded><![CDATA[<p>Re: Reason to count backwards But if you iterate backwards, and a listener is removed, don&#8217;t you dispatch an event twice to the current listener? An example:<br />
List location, listener<br />
1, A<br />
2, B<br />
3, C</p>
<p>4, D<br />
You&#8217;re processing list location 4, listener D. During that time,<br />
listener B removes itself. Your list now reads:</p>
<p>1, A<br />
2, C<br />
3, D</p>
<p>When you process location 3, you get D again? Or are double-deliveries not a problem for your system? Also, don&#8217;t you face the problem that a listener can be removed between the time you called size() and the first list access? Small, but ArrayIndexOutOfBounds is kind of annoying at runtime. When I did listener dispatching (3 years ago) I never figured out a thread-safe approach to listener dispatch that didn&#8217;t involve synchronization, which quickly required list copying to reduce lock contention. I&#8217;ll admit I didn&#8217;t spend a ton of time on it, as the solution I had was &#8220;good enough&#8221;.</p>
<p>-Kevin Klinemeier (who can&#8217;t figure out how to add his name directly to the tagline)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Kevin Klinemeier</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-71</link>
		<dc:creator>Kevin Klinemeier</dc:creator>
		<pubDate>Fri, 06 Jan 2006 22:01:41 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-71</guid>
		<description> &lt;h3&gt;One-off bug in counterexample (in response to hip@a.cs.okstate.edu) &lt;/h3&gt;

Yeah, I left the one-off bug pointed out by another poster in the code I used-- pure laziness on my part. The results are still valid, perhaps even moreso. No matter what order you do the two tests in, the first one is always longer. No performance difference is shown between != and &gt;=. </description>
		<content:encoded><![CDATA[<h3>One-off bug in counterexample (in response to <a href="mailto:hip@a.cs.okstate.edu">hip@a.cs.okstate.edu</a>) </h3>
<p>Yeah, I left the one-off bug pointed out by another poster in the code I used&#8211; pure laziness on my part. The results are still valid, perhaps even moreso. No matter what order you do the two tests in, the first one is always longer. No performance difference is shown between != and &gt;=.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: bchapman</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-70</link>
		<dc:creator>bchapman</dc:creator>
		<pubDate>Fri, 06 Jan 2006 22:01:06 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-70</guid>
		<description>&lt;h3&gt;Reason to count backwards&lt;/h3&gt;

One place where we deliberately count backwards is when we are dispatching events to listeners. There is a strong likelyhood that some listeners will remove themselves during the event processing. If you count forward, you need to iterate over a copy to prevent skipping over a listener following one that removes itself, whereas if you count backward, and the current listener gets removed from the List, it doesn&#039;t break the iterating logic. By the way I disagree with the FORTRAN professor, Given a choice I would take a maintainable incorrect program over an unmaintainable correct one. In the first case someone else can fix it. In the second case you cannot fix it when you find you were wrong about it being correct (or when the requirements change). I would put Readability ahead of Correctness. How can you possibly make it correct it if it is not readable?</description>
		<content:encoded><![CDATA[<h3>Reason to count backwards</h3>
<p>One place where we deliberately count backwards is when we are dispatching events to listeners. There is a strong likelyhood that some listeners will remove themselves during the event processing. If you count forward, you need to iterate over a copy to prevent skipping over a listener following one that removes itself, whereas if you count backward, and the current listener gets removed from the List, it doesn&#8217;t break the iterating logic. By the way I disagree with the FORTRAN professor, Given a choice I would take a maintainable incorrect program over an unmaintainable correct one. In the first case someone else can fix it. In the second case you cannot fix it when you find you were wrong about it being correct (or when the requirements change). I would put Readability ahead of Correctness. How can you possibly make it correct it if it is not readable?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: hip</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-69</link>
		<dc:creator>hip</dc:creator>
		<pubDate>Fri, 06 Jan 2006 22:00:39 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-69</guid>
		<description>&lt;h3&gt;Hotspot optimization, not faster operation&lt;/h3&gt;

Hmm, the last example still has a &quot;one-off&quot; error, probably from a cut-and-paste. But does that matter? A error is a error no matter where it comes from. I can hear my old FORTRAN professor &quot;&lt;i&gt;Correctness&lt;/i&gt; first, &lt;i&gt;Readability&lt;/i&gt; second, &lt;i&gt;Documentation&lt;/i&gt; third.&quot; And when someone would inevitably ask &quot;what about speed?&quot;, he would respond with &quot;you have enough to worry about with the first three.</description>
		<content:encoded><![CDATA[<h3>Hotspot optimization, not faster operation</h3>
<p>Hmm, the last example still has a &#8220;one-off&#8221; error, probably from a cut-and-paste. But does that matter? A error is a error no matter where it comes from. I can hear my old FORTRAN professor &#8220;<i>Correctness</i> first, <i>Readability</i> second, <i>Documentation</i> third.&#8221; And when someone would inevitably ask &#8220;what about speed?&#8221;, he would respond with &#8220;you have enough to worry about with the first three.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Kevin Klinemeier</title>
		<link>http://cafe.elharo.com/blogroll/oniterators/comment-page-1/#comment-68</link>
		<dc:creator>Kevin Klinemeier</dc:creator>
		<pubDate>Fri, 06 Jan 2006 21:59:40 +0000</pubDate>
		<guid isPermaLink="false">http://minicafe.elharo.com/wordpress/java/oniterators/#comment-68</guid>
		<description>&lt;h3&gt;Hotspot optimization, not faster operation&lt;/h3&gt;

Since the -server flag instructs the VM to do more aggressive optimization, I wondered if this were affecting micro-benchmark. So I first ran it as posted above, and got the same results: Increasing Delta: 67063 Decreasing Delta: 32516

Next, I switched the two for loops, so that the != comes before the &gt;= comparison (code below). Suprisingly, I got the same kind of results, the first loop takes longer: Increasing Delta: 67173 Decreasing Delta: 32485 I think that hotspot is either creating overhead that isn&#039;t there in the second loop, or finally performing some significant optimization while executing the second loop. The interesting bit is, of course, that it doesn&#039;t matter which loop is second. Modified code for second run:

&lt;pre&gt;public class TimeArray {
  public static void main(String args[]) {
    int something = 2;
    int k = 0;
    long startTime = System.currentTimeMillis();
        
    for (k = 0; k &lt; 10; k++) {
      for (int i = Integer.MAX_VALUE - 1; i != 0; i--) {
         something = -something;
      }
    }
        
    long midTime = System.currentTimeMillis();
    for (k = 0; k &lt; 10; k++) {
      for (int i = Integer.MAX_VALUE - 1; i &gt;= 0; i--) {
        something = -something;
      }
    }
    long endTime = System.currentTimeMillis();
    System.out.println(&quot;Increasing Delta: &quot; + (midTime - startTime));
    System.out.println(&quot;Decreasing Delta: &quot; + (endTime - midTime));
  }
}&lt;/pre&gt;
</description>
		<content:encoded><![CDATA[<h3>Hotspot optimization, not faster operation</h3>
<p>Since the -server flag instructs the VM to do more aggressive optimization, I wondered if this were affecting micro-benchmark. So I first ran it as posted above, and got the same results: Increasing Delta: 67063 Decreasing Delta: 32516</p>
<p>Next, I switched the two for loops, so that the != comes before the &gt;= comparison (code below). Suprisingly, I got the same kind of results, the first loop takes longer: Increasing Delta: 67173 Decreasing Delta: 32485 I think that hotspot is either creating overhead that isn&#8217;t there in the second loop, or finally performing some significant optimization while executing the second loop. The interesting bit is, of course, that it doesn&#8217;t matter which loop is second. Modified code for second run:</p>
<pre>public class TimeArray {
  public static void main(String args[]) {
    int something = 2;
    int k = 0;
    long startTime = System.currentTimeMillis();

    for (k = 0; k &lt; 10; k++) {
      for (int i = Integer.MAX_VALUE - 1; i != 0; i--) {
         something = -something;
      }
    }

    long midTime = System.currentTimeMillis();
    for (k = 0; k &lt; 10; k++) {
      for (int i = Integer.MAX_VALUE - 1; i &gt;= 0; i--) {
        something = -something;
      }
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Increasing Delta: " + (midTime - startTime));
    System.out.println("Decreasing Delta: " + (endTime - midTime));
  }
}</pre>
]]></content:encoded>
	</item>
</channel>
</rss>
