RFR: 8166365: Small immutable collections should provide optimized implementations when possible
Paul Sandoz
paul.sandoz at oracle.com
Tue Jan 10 17:37:34 UTC 2017
Hi,
Cleary i should be more careful reviewing while eating my breakfast.
> On 10 Jan 2017, at 09:00, Claes Redestad <claes.redestad at oracle.com> wrote:
>
> Hi Paul,
>
> On 2017-01-10 17:32, Paul Sandoz wrote:
>> Hi,
>>
>> ImmutableCollections
>> —
>>
>> Did you forget or intentionally omit overriding the hashCode for List2 and ListN?
>
> Intentionally omitted: since List2 and ListN have O(1) get performance,
> the Iterator provided by AbstractList seems good enough for now.
>
Ok. Given the collections are small i wondered if the iterator allocation was significant.
>>
>>
>> 481 @Override
>> 482 public int hashCode() {
>> 483 int h = 0;
>> 484 for (E e : elements) {
>> 485 if (e != null) {
>> 486 h += e.hashCode();
>> 487 }
>> 488 }
>> 489 return h;
>> 490 }
>>
>> No need for the null check of e.
>
> Actually null checks are needed: SetN elements is a sparse array with
> null at indexes where there is no actual entry.
>
Doh!
> Or are you suggesting we do the following?
>
No, i forgot the table can contain null values.
> for (E e : elements) {
> h += Objects.hashCode(e);
> }
>
>> If you override hashCode should you override equals as well?
>
> I need to look into this one and get back to you, might be
> unintentionally left out.
>
Ok.
>>
>>
>> 617 @Override
>> 618 public int hashCode() {
>> 619 return k0.hashCode() ^ v0.hashCode();
>> 620 }
>>
>> That does not conform to the specification of Map.hashCode:
>>
>> /**
>> * Returns the hash code value for this map. The hash code of a map is
>> * defined to be the sum of the hash codes of each entry in the map's
>> * {@code entrySet()} view. This ensures that {@code m1.equals(m2)}
>>
>> (Your tests might be lucky with the summing of hash codes with distinct ranges of bits set?)
>
> I think you're mistaken: k0 and v0 constitute the sole entry of Map1,
> and k0.hashCode() ^ v0.hashCode() is the hash code for said entry;
> compare HashMap.Node.hashCode().
>
Another Doh! I got crosseyed thinking this for a map holding two entries.
Paul.
>>
>>
>> 669 @Override
>> 670 public boolean containsValue(Object o) {
>> 671 for (int i = 1; i < table.length; i += 2) {
>> 672 Object v = table[i];
>> 673 if (v != null && o.equals(v)) {
>> 674 return true;
>> 675 }
>> 676 }
>> 677 return false;
>> 678 }
>>
>> No need for the null check for v, can pass table[i] directly to o.equals
>
> Again, table is sparse and contain null entries when there's no map
> entry at that index in the table. In this case o.equals(null) would
> likely return the right thing (false) for all objects, but seems a bit
> odd to me.
>
> Thanks!
>
> /Claes
>
>>
>> Paul.
>>
>>> On 10 Jan 2017, at 03:50, Claes Redestad <claes.redestad at oracle.com> wrote:
>>>
>>> Hi,
>>>
>>> please review this change to improve startup/warmup characteristics
>>> and performance of the immutable collection factories:
>>>
>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8166365
>>> Webrev: http://cr.openjdk.java.net/~redestad/8166365/webrev.01/
>>>
>>> While filed as an RFE, and a more thorough examination of the hierarchy
>>> of the ImmutableCollection classes has been discussed[1], this more
>>> limited patch resolves some immediate issues related to module system
>>> bootstrap and is therefore motivated to push to 9.
>>>
>>> Thanks!
>>>
>>> /Claes
>>>
>>> [1] we should likely not inherit Iterator classes that check for
>>> co-modification etc,
>>
More information about the core-libs-dev
mailing list