Collections.emptyList().spliterator() is not ORDERED

Tagir F. Valeev amaembo at gmail.com
Mon Sep 7 09:20:32 UTC 2015


Hello!

PS> Well spotted. We made an exception when the spliterator covers no elements:

PS>   https://bugs.openjdk.java.net/browse/JDK-8022797
PS>   http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/737b6c298d81

Thanks for the information, I did not know about that.

PS> In this case we should fix Stream.concat to check if a
PS> spliterator reporting SIZED is empty, which will allow us to optimize the concatenation [1].
PS> [1] https://bugs.openjdk.java.net/browse/JDK-8022805

That would be even better from performance point of view. Thanks.

By the way, probably it's reasonable then for Arrays.asList to check
the array length like:

    public static <T> List<T> asList(T... a) {
        if(a.length == 0)
          return Collections.emptyList();
        return new ArrayList<>(a);
    }

This would make Arrays.asList() (without arguments) and
Collections.emptyList() perfectly consistent (now their spliterators
report different characteristics) and reduce the number of heap
objects. Probably there are some caveats I'm not aware of. Sorry if it
was already discussed.

PS> P.S. I still have a bunch of your stuff in my queue to process,
PS> sorry it’s taking so long,i will get to them in the next couple of
PS> weeks, but i need to process some other stuff first.

No problems, I'm not in a hurry.

With best regards,
Tagir Valeev.

PS> On 6 Sep 2015, at 12:21, Tagir F. Valeev <amaembo at gmail.com> wrote:

>> Hello!
>> 
>> As Paul Sandoz pointed out in the "Custom spliterator for
>> Collections.nCopies(n, obj).stream()" discussion, the
>> List.spliterator() is specified to be ORDERED. However
>> Collections.emptyList().spliterator() violates this specification:
>> 
>> System.out.println(Collections.emptyList()
>>  .spliterator().hasCharacteristics(Spliterator.ORDERED));
>> // prints false
>> 
>> This becomes critical if I want to concatenate streams from the two
>> lists returned from two different methods (one of which returned
>> emptyList) and process the result in parallel. For example:
>> 
>> List<Integer> list1 = IntStream.range(0, 100).boxed().collect(Collectors.toList());
>> List<Integer> list2 = Collections.emptyList();
>> System.out.println(Stream
>>      .concat(list1.stream(), list2.stream()).parallel()
>>      .filter(x -> x >= 0).limit(10).collect(Collectors.toList()));
>> 
>> This code unexpectedly prints some random subset. This can be fixed by
>> replacing list2 with
>> 
>> List<Integer> list2 = Arrays.asList();
>> 
>> As Arrays.asList().spliterator() is ordered, the resulting stream is
>> ordered as well, so we see [0, ..., 9] as expected.
>> 
>> Looks like a bug in emptyList() implementation.
>> 
>> With best regards,
>> Tagir Valeev.
>> 




More information about the core-libs-dev mailing list