[11] RFR: 8193128: Reduce number of implementation classes returned by List/Set/Map.of()

Claes Redestad claes.redestad at oracle.com
Tue Jan 9 01:17:52 UTC 2018


Hi,


On 2018-01-09 00:04, Peter Levart wrote:
> Hi Claes,
>
> On 01/08/18 23:41, Peter Levart wrote:
>> Hi Claes,
>>
>> On 01/08/18 21:57, Claes Redestad wrote:
>>> CCE is specified to be thrown by Set::contains/containsAll, so I 
>>> think we should play it safe and
>>> leave it unchanged.
>>
>> It's probably specified so to accommodate for SortedSet(s) which 
>> don't use equals but compareTo / Comparator. But here you are calling 
>> containsAll on an abstract Set with known implementation(s) which are 
>> hash-based and CCE will never be thrown. If CCE is thrown from 
>> element's equals() then it should probably propagate out of 
>> AbstractImmutableSet.equals() and not silently translate to 
>> non-equality of sets.
>>
>> What do you think?
>
> I just noticed that AbstractSet does the same (catches CCE). That's 
> probably because of SortedSet subclasses too. So if you think 
> AbstractImmutableSet might be used for some immutable SortedSet 
> implementations in the future, you should probably leave it unchanged. 
> If elemen't equals() throws CCE it is violating the spec so it does 
> not matter what the outcome is (although probably propagating CCE 
> might help catching the bug). If you envision other 
> AbstractImmutableSet subclasses in the future, then perhaps it would 
> be good to declare an abstract hashCode() method in it. So 
> implementations can't forget to define it. When one sees that equals() 
> is already defined, he might falsely assume that hashCode() is defined 
> too.
>
> Regards, Peter

you're right that for this closed world of AbstractImmutableSets we can 
deduce that CCE can't be thrown and
ignore that possibility for now. Not sure it matters much.

Adding a public abstract int hashCode(); might be a kindness. I'll add 
that unless there are objections. :-)

If we took it a step further we could save us the trouble of throwing 
and swallowing NPEs in
AbstractImmutableSet::equals when the other set contains null, which 
might be an optimization
in that case:

         @Override
         public boolean equals(Object o) {
             if (o == this)
                 return true;

             if (!(o instanceof Set))
                 return false;

             Collection<?> c = (Collection<?>) o;
             if (c.size() != size())
                 return false;

             for (Object e : c)
                 if (e == null || !contains(e))
                     return false;
             return true;
         }

It might be rare enough that it's not worth bothering with, though.

/Claes



More information about the core-libs-dev mailing list