Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h3>Update</h3> <blockquote> <p>Let's say, for example, in the case where we'd have an array that we want to treat as a multiset.</p> </blockquote> <p>So you have to process all the entries as they come, you can't use <code>count</code>, and can't assume the entries come in a known order.</p> <p>The general function I'd consider is</p> <pre><code>int hashCode() { int x = INITIAL_VALUE; for (Object o : this) { x = f(x, o==null ? NULL_HASH : g(o.hashCode())); } return h(x); } </code></pre> <p>Some observations:</p> <ul> <li>As already stated in the other answers, the INITIAL_VALUE doesn't matter much.</li> <li>I wouldn't go for <code>NULL_HASH=0</code> since this would ignore null values.</li> <li>The function <code>g</code> can be used in case you expect the hashes of the members to be in a small range (which can happen in case they are e.g., single characters).</li> <li>The function <code>h</code> can be used to improve the result, which is not very important since this already happens e.g. in <code>HashMap.hash(int)</code>.</li> <li>The function <code>f</code> is the most important one, unfortunately, it's quite limited as it obviously must be both associative and commutative.</li> <li>The function <code>f</code> should be bijective in both arguments, otherwise you'd generate unnecessary collisions.</li> </ul> <p>In no case I'd recommend <code>f(x, y) = x^y</code> since it'd make two occurrences of an element to cancel out. Using addition is better. Something like</p> <pre><code>f(x, y) = x + (2*A*x + 1) * y </code></pre> <p>where <code>A</code> is a constant satisfies all the above conditions. It may be worth it. For <code>A=0</code> it degenerates to addition, using an even <code>A</code> is not good as it shift bits of <code>x*y</code> out. Using <code>A=1</code> is fine, and the expression <code>2*x+1</code> can be computed using a single instruction on the <code>x86</code> architecture. Using a larger odd <code>A</code> might work better in case the hashes of the members are badly distributed.</p> <p>In case you go for a non-trivial <code>hashCode()</code> you should test if it works correctly. You should measure the performance of your program, maybe you'll find simple addition sufficient. Otherwise, I'd for for <code>NULL_HASH=1</code>, <code>g=h=identity</code>, and <code>A=1</code>.</p> <h3>My old answer</h3> <p>It may be for efficiency reasons. Calling <code>count</code> may be expensive for some implementations, but <code>entrySet</code> may be used instead. Still it might be more costly, I can't tell.</p> <p>I did a simple collision benchmark for Guava's hashCode and Rinke's and my own proposals:</p> <pre><code>enum HashCodeMethod { GUAVA { @Override public int hashCode(Multiset&lt;?&gt; multiset) { return multiset.hashCode(); } }, RINKE { @Override public int hashCode(Multiset&lt;?&gt; multiset) { int result = 0; for (final Object o : multiset.elementSet()) { result += (o==null ? 0 : o.hashCode()) * multiset.count(o); } return result; } }, MAAARTIN { @Override public int hashCode(Multiset&lt;?&gt; multiset) { int result = 0; for (final Multiset.Entry&lt;?&gt; e : multiset.entrySet()) { result += (e.getElement()==null ? 0 : e.getElement().hashCode()) * (2*e.getCount()+123); } return result; } } ; public abstract int hashCode(Multiset&lt;?&gt; multiset); } </code></pre> <p>The collision counting code went as follows:</p> <pre><code>private void countCollisions() throws Exception { final String letters1 = "abcdefgh"; final String letters2 = "ABCDEFGH"; final int total = letters1.length() * letters2.length(); for (final HashCodeMethod hcm : HashCodeMethod.values()) { final Multiset&lt;Integer&gt; histogram = HashMultiset.create(); for (final String s1 : Splitter.fixedLength(1).split(letters1)) { for (final String s2 : Splitter.fixedLength(1).split(letters2)) { histogram.add(hcm.hashCode(ImmutableMultiset.of(s1, s2, s2))); } } System.out.println("Collisions " + hcm + ": " + (total-histogram.elementSet().size())); } } </code></pre> <p>and printed</p> <pre><code>Collisions GUAVA: 45 Collisions RINKE: 42 Collisions MAAARTIN: 0 </code></pre> <p>So in this simple example Guava's hashCode performed really bad (45 collisions out of 63 possible). However, I don't claim my example is of much relevance for real life.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload