Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 
Search the JavaFAQ.nu
1000 Java Tips ebook

1000 Java Tips - Click here for the high resolution copy!1000 Java Tips - Click here for the high resolution copy!

Java Screensaver, take it here

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java programming articles and tips. Please take your copy here.

Take your copy of free "Java Technology Screensaver"!.

Easy Learn Java: Programming Articles, Examples and Tips - Page 424


Previous 1060 Stories (530 Pages, 2 Per Page) Next

Q: I have a class with six instance variables, each of which could be initialize

Go to all tips in Java IAQ by Peter Norvig

Q: I have a class with six instance variables, each of which could be initialized or not. Should I write 64 constructors?

Answer: Of course you don't need (26) constructors. Let's say you have a class C defined as follows:

public class C { int a,b,c,d,e,f; }

Here are some things you can do for constructors:

  1. Guess at what combinations of variables will likely be wanted, and provide constructors for those combinations. Pro: That's how it's usually done. Con: Difficult to guess correctly; lots of redundant code to write.

  2. Define setters that can be cascaded because they return this. That is, define a setter for each instance variable, then use them after a call to the default constructor:

    public C setA(int val) { a = val; return this; }
    ...
    new C().setA(1).setC(3).setE(5);

    Pro: This is a reasonably simple and efficient approach. A similar idea is discussed by Bjarne Stroustrop on page 156 of The Design and Evolution of C++. Con: You need to write all the little setters, they aren't JavaBean-compliant (since they return this, not void), they don't work if there are interactions between two values.


  3. Use the default constructor for an anonymous sub-class with a non-static initializer:

    new C() {{ a = 1; c = 3; e = 5; }}

    Pro: Very concise; no mess with setters. Con: The instance variables can't be private, you have the overhead of a sub-class, your object won't actually have C as its class (although it will still be an instanceof C), it only works if you have accessible instance variables, and many people, including experienced Java programmers, won't understand it. Actually, its quite simple: You are defining a new, unnamed (anonymous) subclass of C, with no new methods or variables, but with an initialization block that initializes a, c, and e. Along with defining this class, you are also making an instance. When I showed this to Guy Steele, he said "heh, heh! That's pretty cute, all right, but I'm not sure I would advocate widespread use..." As usual, Guy is right. (By the way, you can also use this to create and initialize a vector. You know how great it is to create and initialize, say, a String array with new String[] {"one", "two", "three"}. Now with inner classes you can do the same thing for a vector, where previously you thought you'd have to use assignement statements: new Vector(3) {{add("one"); add("two"); add("three")}}.)

  4. You can switch to a language that directly supports this idiom.. For example, C++ has optional arguments. So you can do this:

    class C {
    public: C(int a=1, int b=2, int c=3, int d=4, int e=5);
    }
    ...
    new C(10); // Construct an instance with defaults for b,c,d,e

    Common Lisp and Python have keyword arguments as well as optional arguments, so you can do this:

    C(a=10, c=30, e=50)            # Construct an instance; use defaults for b and d.


This tip is reprinted on JavaFAQ.nu by by courtesy of Peter Norvig I am thankful for his important contributions to my site - 21 Infrequently Answered Java Questions. Alexandre Patchine


2438 bytes more | comments? | Printer Friendly Page  Send to a Friend | Score: 0
Posted by jalex on Wednesday, December 21, 2005 (00:00:00) (2332 reads)

HashMap requires a better hashCode() - JDK 1.4 Part II

Go to all tips in Story by Dr. Kabutz

The Java Specialists' Newsletter [Issue 054] - HashMap requires a better hashCode() - JDK 1.4 Part II

Author: Dr. Heinz M. Kabutz

JDK version:

Category: Performance

You can subscribe from our home page: http://www.javaspecialists.co.za (which also hosts all previous issues, available free of charge Smile

Welcome to the 54th edition of The Java(tm) Specialists' Newsletter sent to 4289 Java Specialists in 85 countries. I seem to have to explain with each newsletter why you have not heard from me for soooo long. Last night I was speaking to a Java guru at Dimension Data in Cape Town, and he mentioned that somehow he had gotten unsubscribed from my newsletter. "No", said I, "you are still subscribed. It has just been rather quiet lately."

We have now finally completed moving into our new home, which includes an office with a view across False Bay all the way to Cape Point (when the weather is nice, which is most of the time Smile, so perhaps, the newsletters will appear more frequently. Last week I had to go on an emergency mission to Europe to try help solve some Java deadlock in a very large piece of code. If you get stuck with a deadlock in Java, or even worse, a livelock, you are welcome to contact me and I will see if I can be of help.

Calling all Mac fans & haters! - I am considering buying a Mac notebook for Java development and to develop my courseware. If you have any horror stories (or success stories) regarding Java and Mac OS X, please let me know.

HashMap requires a better hashCode() - JDK 1.4 Part II

My explorations into the JDK 1.4 source code did not come unrewarded. Within a day of starting my expedition, I stumbled across something that ended up baffling several Java experts, including yours truly: java.util.HashMap now always has a power-of-two number of buckets, irrespective of what size and load factor you specify!!!

Conventional wisdom says that the buckets in a hash table should be a prime number size. That's what Craig Larman and Rhett Guthrie argued in their excellent (albeit a bit dated) book on Java Performance. The reason why the number of buckets should be prime is so that the hash values are well distributed, even when the hash function is not very well distributed. I'm sure you will find the theory behind it in some dusty CompSci 101 textbook somewhere. The worst possible number of buckets is a power-of-two! So, why on earth did Sun Microsystems deliberately change java.util.HashMap to force it to have a power-of-two number of buckets? (No, "Sun wants to sell more hardware" is not the correct answer Wink

I posed this question to Bruce Eckel, who also did not know the reason for this. However, he knew Joshua Bloch, the author of java.util.HashMap, so we asked him. Before reading the answer, spend a few minutes thinking about why this could be.

But before I expound the reason, and the problems that came with the change, I want to mention a problem that someone on JavaDesk (an advanced yahoogroups Java User Group with excellent content) mentioned: Since JDK 1.3, integer division and remainder calculation has become really slow. I've written a basic microbenching framework based on some code originally posted in the JavaDesk group, and also shown in the bug report where the slowdown was described. One has to be careful with Microbenchmarking, as you can read up in this article from the San Francisco conference.

We start with a simple interface:


Code:
<pre><i><font color="#808080">/**
 * Benchmark contains some calculation that is executed inside
 * the doCalculation() method a certain number of times.  The
 * number of iterations is returned from the method.
 */</font></i>
<b><font color="#000080">public interface</font></b> Benchmark {
  <b><font color="#000080">int</font></b> doCalculation();
}
</pre>

Add to it a little performance testing routine:

Code:

<pre><b><font color="#000080">public class</font></b> PerformanceTest {
  <b><font color="#000080">private static final int</font></b> REPEATS = <b><font color="#008000">10</font></b>;

  <b><font color="#000080">public static void</font></b> main(String[] args) {
    <b><font color="#000080">if</font></b> (args.length != <b><font color="#008000">1</font></b>) {
      usage();
    }
    System.out.println(
      <b><font color="#008000">"JVM version:"</font></b> + System.getProperty(<b><font color="#008000">"java.version"</font></b>));
    <b><font color="#000080">try</font></b> {
      evaluate((Benchmark)Class.forName(args[<b><font color="#008000">0</font></b>]).newInstance());
      System.out.println();
    } <b><font color="#000080">catch</font></b> (Exception ex) {
      ex.printStackTrace();
      usage();
    }
  }

  <b><font color="#000080">private static void</font></b> usage() {
    System.err.println(
      <b><font color="#008000">"usage: java PerformanceTest BenchmarkClass"</font></b>);
    System.err.println(
      <b><font color="#008000">"   BenchmarkClass is a class implementing Benchmark"</font></b>);
    System.exit(<b><font color="#008000">1</font></b>);
  }

  <b><font color="#000080">private static void</font></b> evaluate(Benchmark benchmark) {   
    <i><font color="#808080">// do the function once to "warm up" HotSpot compiler</font></i>
    benchmark.doCalculation();
    <b><font color="#000080">long</font></b> average = <b><font color="#008000">0</font></b>;
    <b><font color="#000080">for</font></b> (<b><font color="#000080">int</font></b> i = <b><font color="#008000">0</font></b>; i < REPEATS; i++) {
      <b><font color="#000080">long</font></b> time = -System.currentTimeMillis();
      <b><font color="#000080">int</font></b> iterations = benchmark.doCalculation();
      time += System.currentTimeMillis();
      System.out.print(iterations / time);
      System.out.print(<b><font color="#008000">"  "</font></b>);
      System.out.flush();
      average += iterations / time;
    }
    System.out.println();
    System.out.println(
      <b><font color="#008000">"Average "</font></b>
        + (average / REPEATS)
        + <b><font color="#008000">" iterations per millisecond"</font></b>);
  }
}
</pre>

The most basic test that I want to show is a simple empty loop. This "benchmark" is really quite useless - any half-decent compiler should optimize it away anyway. In addition, if you unroll the loop by 16 steps, you end up doing nothing 16 times and slice the loop into a 16th of the length. The reason for testing this is simply to have some indication of whether my other tests are actually going to measure anything besides the for loop. Please also note that in general each version of JDK makes programs run faster, but that you will always find some benchmark which seems to demonstrate that the old JDK was faster.

Code:


<pre><b><font color="#000080">public class</font></b> EmptyLoopBenchmark <b><font color="#000080">implements</font></b> Benchmark {
  <b><font color="#000080">private static final int</font></b> ITERATIONS = <b><font color="#008000">10</font></b> * <b><font color="#008000">1000</font></b> * <b><font color="#008000">1000</font></b>;
  <b><font color="#000080">public int</font></b> doCalculation() {
    <b><font color="#000080">for</font></b> (<b><font color="#000080">int</font></b> i = <b><font color="#008000">0</font></b>; i < ITERATIONS; i++) {
      ; // NOP
    }
    <b><font color="#000080">return</font></b> ITERATIONS;
  }
}
</pre>

The results are interesting, although they don't really tell us very much:

JVM version:1.2
333333  333333  333333  200000  333333 ...
Average 311056 iterations per millisecond

JVM version:1.3.1_03
250000  200000  250000  166666  250000  ...
Average 217941 iterations per millisecond

JVM version:1.4.0
142857  166666  166666  125000  166666  ...
Average 151785 iterations per millisecond

JVM version:1.4.1-beta
82644  76923  76923  76923  83333  ...
Average 78926 iterations per millisecond

Is the JDK 1.4.1 then slower than the JDK 1.2 ?!? Nope, not in general, but as I said, with benchmarks you can find strange things. However, let's look at a benchmark on addition. We have to use the val variable after the loop, otherwise a clever compiler could optimize the whole loop away.

Code:


<pre><b><font color="#000080">public class</font></b> AdditionBenchmark <b><font color="#000080">implements</font></b> Benchmark {
  <b><font color="#000080">private static final int</font></b> ITERATIONS = <b><font color="#008000">10</font></b> * <b><font color="#008000">1000</font></b> * <b><font color="#008000">1000</font></b>;
  <b><font color="#000080">private int</font></b> memory;
  <b><font color="#000080">public int</font></b> doCalculation() {
    <b><font color="#000080">int</font></b> val = <b><font color="#008000">0</font></b>;
    <b><font color="#000080">for</font></b> (<b><font color="#000080">int</font></b> i = <b><font color="#008000">0</font></b>; i < ITERATIONS; i++) {
      val = val + i;
    }
    memory = val;
    return ITERATIONS;
  }
}
</pre>

The results on my little Asus Notebook are as follows:

JVM version:1.2
333333  333333  200000  333333  500000  ...
Average 344999 iterations per millisecond

JVM version:1.3.1_03
200000  200000  200000  243902  200000  ...
Average 209390 iterations per millisecond

JVM version:1.4.0
125000  125000  125000  123456  125000  ...
Average 123853 iterations per millisecond

JVM version:1.4.1-beta
83333  76923  76335  90909  76923  ...
Average 79486 iterations per millisecond

These results at best demonstrate that addition is blindingly fast, as we would expect. Note that we have to compare the addition benchmark to the empty loop benchmark to realise that the actual addition operation is negligible. However, what about remainder, the % operator?

Code:


<pre><b><font color="#000080">public class</font></b> RemainderBenchmark <b><font color="#000080">implements</font></b> Benchmark {
  <b><font color="#000080">private static final int</font></b> ITERATIONS = <b><font color="#008000">10</font></b> * <b><font color="#008000">1000</font></b> * <b><font color="#008000">1000</font></b>;
  <b><font color="#000080">private int</font></b> memory;
  <b><font color="#000080">public int</font></b> doCalculation() {
    <b><font color="#000080">int</font></b> val = <b><font color="#008000">0</font></b>;
    <b><font color="#000080">for</font></b> (<b><font color="#000080">int</font></b> i = <b><font color="#008000">0</font></b>; i < ITERATIONS; i++) {
      val = i % <b><font color="#008000">11</font></b>;
    }
    memory = val;
    return ITERATIONS;
  }
}
</pre>

Here we see that performance has dropped significantly since JDK 1.2, as described in the bug report mentioned earlier:

JVM version:1.2
62500  62500  62111  58823  66666  ...
Average 62520 iterations per millisecond

JVM version:1.3.1_03
17513  17513  17513  17211  17513  ...
Average 17457 iterations per millisecond

JVM version:1.4.0
14903  16920  16638  15360  16366  ...
Average 16051 iterations per millisecond

JVM version:1.4.1-beta
17211  17513  17211  16920  16920  ...
Average 17217 iterations per millisecond

These results is somewhat disturbing! Isn't that one of the important functions that gets executed in the traditional java.util.HashMap class? The engineers at Sun (Joshua Bloch and Doug Lea) decided to rather use a bit masking approach instead of remainder, because that is much faster:

Code:


<pre><b><font color="#000080">public class</font></b> MaskingBenchmark <b><font color="#000080">implements</font></b> Benchmark {
  <b><font color="#000080">private static final int</font></b> ITERATIONS = <b><font color="#008000">10</font></b> * <b><font color="#008000">1000</font></b> * <b><font color="#008000">1000</font></b>;
  <b><font color="#000080">private int</font></b> memory;
  <b><font color="#000080">public int</font></b> doCalculation() {
    <b><font color="#000080">int</font></b> val = <b><font color="#008000">0</font></b>;
    <b><font color="#000080">for</font></b> (<b><font color="#000080">int</font></b> i = <b><font color="#008000">0</font></b>; i < ITERATIONS; i++) {
      val = i & <b><font color="#008000">0x000000ff</font></b>;
    }
    memory = val;
    return ITERATIONS;
  }
}
</pre>

You can see that the performance values are far more encouraging:

JVM version:1.2
166666  142857  166666  166666  125000  ...
Average 158416 iterations per millisecond

JVM version:1.3.1_03
142857  142857  100000  140845  111111  ...
Average 131624 iterations per millisecond

JVM version:1.4.0
111111  142857  125000  125000  123456  ...
Average 128813 iterations per millisecond

JVM version:1.4.1-beta
76923  76923  83333  76335  83333  ...
Average 80849 iterations per millisecond

In order to protect Sun against claims by the intellectual proletariat Wink, who have up to now managed to get away with writing bad hash functions, Josh wrote a super-fast rehash() function inside java.util.HashMap that attempted to redistribute the bits a little bit. Good hash code writers were rewarded with a nice improvement in performance for java.util.HashMap.get() in JDK 1.4.0 thanks to the new masking trick:

Code:


<pre><b><font color="#000080">import</font></b> java.util.*;

<i><font color="#808080">/**
 * The lower-order bits are used as part of this hashcode
 * which is good if you are using JDK 1.4.0
 */</font></i>
<b><font color="#000080">public class</font></b> GoodHashcodeBenchmark <b><font color="#000080">implements</font></b> Benchmark {
  <b><font color="#000080">private static final int</font></b> ITERATIONS = <b><font color="#008000">1000</font></b> * <b><font color="#008000">1000</font></b>;
  <b><font color="#000080">private</font></b> Object memory;
  <b><font color="#000080">private</font></b> HashMap map = new HashMap(<b><font color="#008000">203</font></b>);
  <b><font color="#000080">private</font></b> Integer[] values;
  <b><font color="#000080">public</font></b> GoodHashcodeBenchmark() {
    <b><font color="#000080">for</font></b> (<b><font color="#000080">int</font></b> i=<b><font color="#008000">0</font></b>; i < <b><font color="#008000">1000</font></b>; i++) {
      map.put(<b><font color="#000080">new</font></b> Integer(i), <b><font color="#008000">"Value"</font></b>);
    }
    TreeSet keys = <b><font color="#000080">new</font></b> TreeSet(map.keySet());
    values = (Integer[])keys.toArray(<b><font color="#000080">new</font></b> Integer[<b><font color="#008000">1000</font></b>]);
  }
  <b><font color="#000080">public int</font></b> doCalculation() {
    <b><font color="#000080">for</font></b> (<b><font color="#000080">int</font></b> i = <b><font color="#008000">0</font></b>; i < ITERATIONS; i++) {
      memory = map.get(values[i%<b><font color="#008000">1000</font></b>]);
    }
    return ITERATIONS;
  }
}
</pre>

When we run this benchmark, we get the following values:

JVM version:1.2
5555  5882  5882  5524  5555  5555  5555  5847  5555  6250
Average 5716 iterations per millisecond

JVM version:1.3.1_03
3846  3690  3846  3436  3846  3571  3831  3703  3690  3571
Average 3703 iterations per millisecond

JVM version:1.4.0
6250  6250  5847  6250  5882  5882  6622  5882  5882  5882
Average 6062 iterations per millisecond

JVM version:1.4.1-beta
4149  4347  4347  4329  4000  4329  4347  4545  4149  4347
Average 4288 iterations per millisecond

Despite the slowdown of JDK 1.[34].x with regards to remainder calculations, Joshua Bloch and Doug Lea still managed to actually make HashMap.get() function in the JDK 1.4.0 run faster than in the JDK 1.2! The observant reader would have noticed that JDK 1.4.1 runs slower than JDK 1.4.0 but faster than JDK 1.3.1. Before I explain why, let's have a look at what happens when you write a bad hash function:

Code:


<pre><b><font color="#000080">import</font></b> java.util.*;

<i><font color="#808080">/**
 * The lower-order bits are NOT used as part of this hashcode
 * which is bad if you are using JDK 1.4.0
 */</font></i>
<b><font color="#000080">public class</font></b> BadHashcodeBenchmark <b><font color="#000080">implements</font></b> Benchmark {
  <b><font color="#000080">private static final int</font></b> ITERATIONS = <b><font color="#008000">1000</font></b> * <b><font color="#008000">1000</font></b>;
  <b><font color="#000080">private</font></b> Object memory;
  <b><font color="#000080">private</font></b> HashMap map = new HashMap(<b><font color="#008000">203</font></b>);
  <b><font color="#000080">private</font></b> Integer[] values;
  <b><font color="#000080">public</font></b> BadHashcodeBenchmark() {
    <b><font color="#000080">for</font></b> (<b><font color="#000080">int</font></b> i=<b><font color="#008000">0</font></b>; i < <b><font color="#008000">1000</font></b>; i++) {
      map.put(<b><font color="#000080">new</font></b> Integer(i * <b><font color="#008000">1024</font></b>), <b><font color="#008000">"Value"</font></b>);
    }
    TreeSet keys = <b><font color="#000080">new</font></b> TreeSet(map.keySet());
    values = (Integer[])keys.toArray(<b><font color="#000080">new</font></b> Integer[<b><font color="#008000">1000</font></b>]);
  }
  <b><font color="#000080">public int</font></b> doCalculation() {
    <b><font color="#000080">for</font></b> (<b><font color="#000080">int</font></b> i = <b><font color="#008000">0</font></b>; i < ITERATIONS; i++) {
      memory = map.get(values[i%<b><font color="#008000">1000</font></b>]);
    }
    return ITERATIONS;
  }
}
</pre>

The result is obvious. Since the new JDK 1.4.0 HashMap is ultra-sensitive to lower-order bits being the same, due to it using masking instead of remainder, the HashMap basically becomes a linked list and the lookup for a single entry becomes O(n) instead of O(1). Oops:

JVM version:1.2
5524  5555  5882  5882  5524  5882  5555  5555  5524  5555
Average 5643 iterations per millisecond

JVM version:1.3.1_03
3571  3690  3571  3703  3558  3703  3558  3703  3571  3690
Average 3631 iterations per millisecond

JVM version:1.4.0
173  172  154  171  173  171  168  167  172  172
Average 169 iterations per millisecond

JVM version:1.4.1-beta
4149  4347  4347  4149  4166  4347  4329  4347  4347  4329
Average 4285 iterations per millisecond

Bug reports started surfacing on the bug parade saying that the HashMap in JDK 1.4.0 had a bug that caused it to be very slow. The following is an excerpt from a three-way conversation between Joshua Bloch, author of java.util.HashMap, Bruce Eckel and myself (quoted with permission):

Joshua Bloch: The downside of using a power-of-two is that the resulting hash table is very sensitive to the quality of the hash function (hashCode). It is imperative that any change in the input must affect the low order bits of the hash value. (Ideally, it should affect all bits of the hash value with equal likelihood.) Because we have no assurance that this is true, we put in a secondary (or "defensive") hash function when we switched to the power-of-two hash table. This hash function is applied to the results of hashCode before masking off the low order bits. Its job is to scatter the information over all the bits, and in particular, into the low order bits. Of course it has to run *very* fast, or you lose the benefit of switching to the power-of-two-sized table. The original secondary hash function in 1.4 turned out to be insufficient. We knew that this was a theoretical possibility, but we thought that it didn't affect any practical data sets. We were wrong. The replacement secondary hash function (which I developed with the aid of a computer) has strong statistical properties that pretty much guarantee good bucket distribution.

The rehash() method in JDK 1.4.1 is quite interesting, but let's hope that it does a good enough job. From my tests, it seems to distribute the bits beautifully, but you will have to test (I don't know how!) that your hash function is compatible with the rehash method of HashMap. Obviously, having a more complicated rehash() method causes a drop in performance (when the hash function was good anyway), but it gives us a better average performance than JDK 1.4.0 and JDK 1.3.1.

Moral of the story - write your own!

If you need to squeeze the last ounce of performance out of the JDK and you need to do that with hash tables, you should probably write your own stripped-down version of HashMap that works specifically for your key-domain.

Conclusion

I now understand the reason for using power-of-two for HashMap buckets, but, I am also disappointed. The old mechanism was so much more predictable in terms of distribution of keys into buckets. How am I going to explain this new mechanism to Java beginners?

On the other hand, this new knowledge allows me (and you) to amble up to people who claim to know Java and say: "Did you know that HashMap in JDK 1.4 forces the number of buckets to be a power-of-two?" If the innocent victim responds: "Yes", you can follow-up your question with "Why?" Try it out - and let me know the response Smile))

Heinz


Copyright 2000-2004 Maximum Solutions, South Africa

Reprint Rights. Copyright subsists in all the material included in this email, but you may freely share the entire email with anyone you feel may be interested, and you may reprint excerpts both online and offline provided that you acknowledge the source as follows: This material from The Java(tm) Specialists' Newsletter by Maximum Solutions (South Africa). Please contact Maximum Solutions for more information.

Java and Sun are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Maximum Solutions is independent of Sun Microsystems, Inc.

19364 bytes more | comments? | Printer Friendly Page  Send to a Friend | Score: 0
Posted by jalex on Friday, December 16, 2005 (00:00:00) (2521 reads)

Previous 1060 Stories (530 Pages, 2 Per Page) Next

530| 529| 528| 527| 526| 525| 524| 523| 522| 521| 520| 519| 518| 517| 516| 515| 514| 513| 512| 511| 510| 509| 508| 507| 506| 505| 504| 503| 502| 501| 500| 499| 498| 497| 496| 495| 494| 493| 492| 491| 490| 489| 488| 487| 486| 485| 484| 483| 482| 481| 480| 479| 478| 477| 476| 475| 474| 473| 472| 471| 470| 469| 468| 467| 466| 465| 464| 463| 462| 461| 460| 459| 458| 457| 456| 455| 454| 453| 452| 451| 450| 449| 448| 447| 446| 445| 444| 443| 442| 441| 440| 439| 438| 437| 436| 435| 434| 433| 432| 431| 430| 429| 428| 427| 426| 425|
424
| 423| 422| 421| 420| 419| 418| 417| 416| 415| 414| 413| 412| 411| 410| 409| 408| 407| 406| 405| 404| 403| 402| 401| 400| 399| 398| 397| 396| 395| 394| 393| 392| 391| 390| 389| 388| 387| 386| 385| 384| 383| 382| 381| 380| 379| 378| 377| 376| 375| 374| 373| 372| 371| 370| 369| 368| 367| 366| 365| 364| 363| 362| 361| 360| 359| 358| 357| 356| 355| 354| 353| 352| 351| 350| 349| 348| 347| 346| 345| 344| 343| 342| 341| 340| 339| 338| 337| 336| 335| 334| 333| 332| 331| 330| 329| 328| 327| 326| 325| 324| 323| 322| 321| 320| 319| 318| 317| 316| 315| 314| 313| 312| 311| 310| 309| 308| 307| 306| 305| 304| 303| 302| 301| 300| 299| 298| 297| 296| 295| 294| 293| 292| 291| 290| 289| 288| 287| 286| 285| 284| 283| 282| 281| 280| 279| 278| 277| 276| 275| 274| 273| 272| 271| 270| 269| 268| 267| 266| 265| 264| 263| 262| 261| 260| 259| 258| 257| 256| 255| 254| 253| 252| 251| 250| 249| 248| 247| 246| 245| 244| 243| 242| 241| 240| 239| 238| 237| 236| 235| 234| 233| 232| 231| 230| 229| 228| 227| 226| 225| 224| 223| 222| 221| 220| 219| 218| 217| 216| 215| 214| 213| 212| 211| 210| 209| 208| 207| 206| 205| 204| 203| 202| 201| 200| 199| 198| 197| 196| 195| 194| 193| 192| 191| 190| 189| 188| 187| 186| 185| 184| 183| 182| 181| 180| 179| 178| 177| 176| 175| 174| 173| 172| 171| 170| 169| 168| 167| 166| 165| 164| 163| 162| 161| 160| 159| 158| 157| 156| 155| 154| 153| 152| 151| 150| 149| 148| 147| 146| 145| 144| 143| 142| 141| 140| 139| 138| 137| 136| 135| 134| 133| 132| 131| 130| 129| 128| 127| 126| 125| 124| 123| 122| 121| 120| 119| 118| 117| 116| 115| 114| 113| 112| 111| 110| 109| 108| 107| 106| 105| 104| 103| 102| 101| 100| 99| 98| 97| 96| 95| 94| 93| 92| 91| 90| 89| 88| 87| 86| 85| 84| 83| 82| 81| 80| 79| 78| 77| 76| 75| 74| 73| 72| 71| 70| 69| 68| 67| 66| 65| 64| 63| 62| 61| 60| 59| 58| 57| 56| 55| 54| 53| 52| 51| 50| 49| 48| 47| 46| 45| 44| 43| 42| 41| 40| 39| 38| 37| 36| 35| 34| 33| 32| 31| 30| 29| 28| 27| 26| 25| 24| 23| 22| 21| 20| 19| 18| 17| 16| 15| 14| 13| 12| 11| 10| 9| 8| 7| 6| 5| 4| 3| 2| 1|


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy